同一自定义View的更多实例的事件

时间:2011-04-05 18:37:18

标签: android

我是Android新手。 在我的项目中,我有自定义的View MyView和以下代码

public class MyView extends View {

    private final Bitmap baseBitmap = BitmapFactory.decodeResource(
            getResources(), R.drawable.myImage);
    private final Matrix matrix;
    private boolean active = true;

    public MyView(Context context, Matrix matrix) {
        super(context);
        this.matrix = matrix;
        this.setFocusable(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);   
        if (active) {
            System.out.println("draw "+this.getId());
            canvas.drawBitmap(baseBitmap, matrix, null);
        } else {
        ...
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            System.out.println("--------->"+this.getId());
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            this.matrix.setTranslate(event.getX()-(baseBitmap.getWidth()/2), event.getY()-(baseBitmap.getHeight()/2));
            this.invalidate();
        } else if (event.getAction() == MotionEvent.ACTION_UP) {

            this.active = false;
        }
        return true;
    }

在我的Activity中,我多次实例化MyView,然后将它们添加到主布局中。这是它的代码:

public class MyActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Display display = getWindowManager().getDefaultDisplay();
      float cx = display.getWidth() / 2, cy = display.getHeight() / 2;
      int radius = 80;
      double distance = 0, distancePoint = 0;
      final int flags = PathMeasure.POSITION_MATRIX_FLAG
            | PathMeasure.TANGENT_MATRIX_FLAG;
      float length = 0;
      setContentView(R.layout.main);
      RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.main_view);
      Path pathCircle = new Path();
      pathCircle.addCircle(cx, cy, radius, Direction.CW);
      PathMeasure meas = new PathMeasure(pathCircle, false);
      int nObject = 10;
      length = meas.getLength();
      distance = length/nObject;
      int i = 0;        
            while(i<nObject){
                Matrix m = new Matrix();
                meas.getMatrix((float)distancePoint, m, flags);
                MyView myView = new MyView(this, m);
                System.out.println(myView.toString());
                myView.setId(i);
                mainLayout.addView(myView,i);
                i++;
                distancePoint = distance*i;
            }
      }                               
}

在运行时,当我触摸任何MyView元素时,我总是得到最后一个。使用“System.out.println("--------->"+this.getId());”我可以看到被触摸元素的id始终是最后一个,即使我是第一个或任何其他元素。 Actualy,我可以移动最后一个元素 有谁知道为什么我不能得到MyView触及的正确的事件?
(我希望我的问题很明确)
感谢


我更改了添加onMeasure方法的代码。我使用了教程的代码,尺寸不是特定于我的图像。绘制视图并且结果是相同的,遗憾的是具有相同的问题。我也发布了布局xml,也许有用。

    public class MyActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Display display = getWindowManager().getDefaultDisplay();
      float cx = display.getWidth() / 2, cy = display.getHeight() / 2;
      int radius = 80;
      double distance = 0, distancePoint = 0;
      final int flags = PathMeasure.POSITION_MATRIX_FLAG
            | PathMeasure.TANGENT_MATRIX_FLAG;
      float length = 0;
      setContentView(R.layout.main);
      RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.main_view);
      Path pathCircle = new Path();
      pathCircle.addCircle(cx, cy, radius, Direction.CW);
      PathMeasure meas = new PathMeasure(pathCircle, false);
      int nObject = 10;
      length = meas.getLength();
      distance = length/nObject;
      int i = 0;        
            while(i<nObject){
                Matrix m = new Matrix();
                meas.getMatrix((float)distancePoint, m, flags);
                MyView myView = new MyView(this, m);
                System.out.println(myView.toString());
                myView.setId(i);
                nt spec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
                      myView.measure(spec, spec);
                mainLayout.addView(myView,i);
                i++;
                distancePoint = distance*i;
            }
      }                               
}


public class MyView extends View {

    private final Bitmap baseBitmap = BitmapFactory.decodeResource(
            getResources(), R.drawable.myImage);
    private final Matrix matrix;
    private boolean active = true;

    public MyView(Context context, Matrix matrix) {
        super(context);
        this.matrix = matrix;
        this.setFocusable(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);   
        if (active) {
            System.out.println("draw "+this.getId());
            canvas.drawBitmap(baseBitmap, matrix, null);
        } else {
        ...
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            System.out.println("--------->"+this.getId());
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            this.matrix.setTranslate(event.getX()-(baseBitmap.getWidth()/2), event.getY()-(baseBitmap.getHeight()/2));
            this.invalidate();
        } else if (event.getAction() == MotionEvent.ACTION_UP) {

            this.active = false;
        }
        return true;
    }


     @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);

            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);

            int chosenWidth = chooseDimension(widthMode, widthSize);
            int chosenHeight = chooseDimension(heightMode, heightSize);

            int chosenDimension = Math.min(chosenWidth, chosenHeight);

            setMeasuredDimension(chosenDimension, chosenDimension);
        }

        private int chooseDimension(int mode, int size) {
            if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
                return size;
            } else { // (mode == MeasureSpec.UNSPECIFIED)
                return getPreferredSize();
            } 
        }

        // in case there is no size specified
        private int getPreferredSize() {
            return 300;
        }
}

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/main_view"
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:background="#FF66FF33">
  </RelativeLayout>

1 个答案:

答案 0 :(得分:0)

我很确定这是因为你基本上堆积了RelativeLayout左上角的观点。因此,只有最上面的(最后添加的)是可触摸的。

我认为如果您尝试将它们添加到LinearLayout,作为测试,您会看到您的视图有效。以编程方式为LayoutParams设置RelativeLayout并不是很舒服恕我直言。

修改

我尝试了你的代码。事实是你的视图只是被绘制成一个在另一个上面,否则整个绘图就不会出现,所以我的第一个猜测是正确的(最重要的是覆盖其他的 - 即使在透明的部分 em>)(顺便说一下尝试Hierarchy Viewer,你可以自己看看)。所以你需要在一个视图中完成你的工作,或者处理这样的接触:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        if(!isPetaloTouched()) {// check if the actual drawing was touched
            return false; // discard the event so that it reaches
                          // the underlying view
        }
//......

有关事件在Android中如何运作的说明,请参阅this post

两种方式都需要一个isPetaloTouched()逻辑来检测是否必须移动/哪个绘图,但第一个当然会更有效。

另外,忘掉onMeasure()这个东西,我认为这可以帮助给视图一个大小来包装,这样它就不会填充它的父级并且将视图放在一边是有意义的。但是,如果视图没有堆积,请确保触摸可以正常工作。

(... allora mPetali stava proprio per petali!)