Android 同一自定义视图的多个实例的事件

Android 同一自定义视图的多个实例的事件,android,Android,我是Android新手。 在我的项目中,我有一个自定义视图MyView,代码如下 public class MyView extends View { private final Bitmap baseBitmap = BitmapFactory.decodeResource( getResources(), R.drawable.myImage); private final Matrix matrix; private boolean act

我是Android新手。 在我的项目中,我有一个自定义视图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;
    }
在我的活动中,我多次实例化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;
            }
      }                               
}
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>

我敢肯定,这是因为您基本上将视图堆积在了
RelativeLayout
的左上角。因此,只有最上面的(添加的最后一个)是可触摸的

我认为,如果您尝试将它们添加到
线性布局
,作为测试,您将看到您的视图是有效的。以编程方式设置
RelativeLayout
LayoutParams
不是很舒服

编辑

我试过你的密码。事实上,您的视图只是一个接一个地绘制,否则整个图形将无法绘制,因此我的第一个猜测是正确的(最上面的视图覆盖了其他视图,即使在其透明部分中也是如此)(顺便说一句,请尝试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中如何工作的说明,请参阅

这两种方法都需要
ispetalTouched()
逻辑来检测是否/哪些图形必须移动,但第一种方法当然更有效

另外,忘了
onMeasure()
这件事吧,我认为这有助于为视图提供一个环绕的大小,这样它就不会填充其父视图,而将视图放在一边是有意义的。但是,如果视图没有堆积起来,请确保触摸会起作用


(…allora
mPetali
stava proprio per petali!)

使用LinearLayout我只得到第一个视图,所以我尝试使用RelativeLayout.LayoutParams,所以我尝试使用RelativeLayout.LayoutParams,如下所示RelativeLayout.LayoutParams=新的RelativeLayout.LayoutParams(LayoutParams.FILL\u PARENT,LayoutParams.WRAP\u CONTENT);如果(i>0){params.addRule(RelativeLayout.ALIGN_LEFT,i-1)}myView.setLayoutParams(params);mainLayout.addView(myView,i);但是它仍然不起作用。@vilandra:在
params.addRule()
中,您需要传递视图的id(使用
getId()
获得的id),而不是作为布局的子级传递其索引。LinearLayout可能不起作用,因为您忘记设置
android:orientation=“vertical”
。但是,如果它仍然无法工作,您是否可以使用层次查看器检查视图是否占用了所有空间?然后,您可能需要在自定义视图中重写
onMeasure()
。@bigstones:不能使用LinearLayout和垂直方向,不能重写onMeasure(),不能将Previous MyView对象保存在while中,也不能调用getId而不是使用索引(我想这是同一回事,因为我对setId使用索引)。我真的不知道会有什么问题。发布包含onMeasure方法的代码是否有用?@vilandra
(这是一样的,因为我想我使用setId的索引)
哦,对不起,我没有看到。是的,请把代码也发出来,我希望我能帮上忙。@bigstones:好的,我很抱歉!现在的问题是要知道实际的触摸视图。我让我的视图实现View.OnTouchListener类,在视图构造函数setted
code
this.setOnTouchListener(this)
code
和onTouch方法(
code
onTouch(View v,MotionEvent事件)
code
)中验证了获得的视图。视图总是当前的,也就是说,对于我的问题,传递给onTouch的视图总是最后一个,因此
code
v.getId()
code
code
this.getId()
code
之间的比较总是正确的。这样,问题就一直存在。然后,我使用了一个视图组,其中。。。
@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
        }
//......