在父视图和子视图的单击事件上

时间:2013-07-31 11:26:56

标签: android onclick onclicklistener

我有RelativeLayoutImageView 布局如下 -

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rlMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black" >

<ImageView
    android:id="@+id/ivIcon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/ic_launcher" />

</RelativeLayout>

Activity代码是 -

public class MainActivity extends Activity implements OnClickListener{

private RelativeLayout rlMain;
private ImageView ivIcon;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    rlMain = (RelativeLayout) findViewById(R.id.rlMain);
    ivIcon = (ImageView) findViewById(R.id.ivIcon);
    rlMain.setOnClickListener(this);
    ivIcon.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.rlMain:
        Toast.makeText(this, "Relative Layout clicked", Toast.LENGTH_SHORT).show();
        break;

    case R.id.ivIcon:
        Toast.makeText(this, "Image View clicked", Toast.LENGTH_SHORT).show();
        break;
    }

}

}

我已为RelativeLayout(父级)和ImageView(子级)应用了点击侦听器。
在点击相对布局时 - 它由相对布局点击处理程序处理。(这似乎是正确的。)

点击Imagview时 - 它由imageview处理。 (这是混乱)。

如果父视图(相对布局)和子视图(imageview)都处理了对imageview的点击吗? 如果只有子视图处理点击,那么逻辑是什么?

3 个答案:

答案 0 :(得分:1)

clickEvent将传递到布局层次结构中的最低子元素。如果此元素没有onClick行为,它会将事件传递给其父元素,直到处理完该事件。

因此,您可以将LinearLayout视为onClick行为的单个块。如果在布局中创建另一个可点击元素,请务必使其足够大,以减少用户错过正确项目的可能性。

来源:Does making parent clickable make all child element clickable as well?

答案 1 :(得分:0)

通常,在要点击的图像尺寸非常小的情况下,将imageView保留在给定一些填充的布局内,然后处理布局的点击。这在屏幕上提供了足够的区域供用户点击

答案 2 :(得分:0)

  1. 重写dispatchTouchEvent函数
  2. 获得接触点
  3. 获取视图的位置。您可以使用getGlobalVisibleRect()getLocalVisibleRect()来检测视图在您的位置上的位置。
  4. 设置简单的if语句并查找点的位置是否在ImageView中。
  5. 操作应为MotionEvent.ACTION_DOWN,以在用户在屏幕上进行滑动操作时仅获得第一触摸。

科特林代码:

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    if(ev?.action == MotionEvent.ACTION_DOWN) {
        val pointX = ev.x
        val pointY = ev.y
        val locationIvIcon = Rect()
        if(iv_icon.getGlobalVisibleRect(locationIvIcon)) {
            if(isInChildView(pointX, pointY, locationSendGiftPopup)) {
                // Do action for ImageView
            } else {
                // Do action for RelativeLayout
            }
        }
    }
    return super.dispatchTouchEvent(ev)
}


private fun isInChildView(x: Float?, y: Float?, location: Rect): Boolean {
        x?.let {
            y?.let {
                return x >= location.left && x <= location.right 
                        && y >= location.top && y <= location.bottom
            }
        }
        return false
    }