【问题标题】:dispatchTouchEvent issue for passing the touch event to children将触摸事件传递给孩子的 dispatchTouchEvent 问题
【发布时间】:2015-11-19 09:45:41
【问题描述】:

我正在尝试为棒棒糖前版本创建棒棒糖工具栏图标的效果。

我编写了一个扩展 LinearLayout 的类,并在 dispatchTouchEvent 中检查哪个孩子更接近触摸位置并将该事件仅发送给该孩子,以便它忽略孩子的重叠区域和 z-index:

public class OverlappingLayout extends LinearLayout {
 public OverlappingLayout(Context context) {
    super(context);
}

public OverlappingLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

int lastAction = 0;
View lastView = null;

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {

    if(lastView != null){

        lastView.dispatchTouchEvent(ev);

        if(ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP)
            lastView = null;

        return true;
    }

    float min = 99999999f;
    int minIndex = 0;

    for (int i = 0; i < getChildCount(); i++) {

        View child = getChildAt(i);

        float centerX = child.getX() + child.getWidth() / 2;
        float centerY = child.getY() + child.getHeight() / 2;

        float dis = (float) Math.sqrt(
                (ev.getX() - centerX) *  (ev.getX() - centerX) +
                        (ev.getY() - centerY) *  (ev.getY() - centerY)
        );

        if(dis < min) {
            min = dis;
            minIndex = i;
        }
    }

    getChildAt(minIndex).setClickable(true);
    getChildAt(minIndex).dispatchTouchEvent(ev);

    lastView = getChildAt(minIndex);
    lastAction = ev.getAction();


    lastView.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            //never works for the last child, or the right half of the second child


            return false;
        }
    });

    return true;
}
 }

但问题是代码在布局的前半部分工作正常,而在后半部分不起作用。

代码在调试模式下工作,并找到最近的孩子并将事件传递给它,但孩子的drawable的按下状态不起作用。

我也将它更改为RelativeLayout,但仍然有同样的问题。

【问题讨论】:

  • 您在布局中尝试过 blockDescendentsFocusability 吗?
  • 没有,我也不知道怎么用!
  • 我认为情况并非如此。如果是这样的话,就不可能有任何视图是可触摸的。
  • 没错,困扰我的问题是它适用于布局的后半部分!!!

标签: android android-linearlayout children overlapping touch-event


【解决方案1】:

我发现了问题所在。 当我将motionEvent对象发送给孩子时,触摸的x和y在孩子的矩形之外(如孩子所见)。所以它只适用于前半部分,因为第一个和第二个孩子看到他们的矩形内的触摸位置。所以我将代码更改为:

private Rect rect;
View lastView;

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

    for (int i = 0; i < getChildCount(); i++) {
        getChildAt(i).setClickable(false);
    }

    if(lastView == null)
        lastView = getClosestChildToTouch(event);


    if (event.getAction() == MotionEvent.ACTION_DOWN) {

        lastView.setPressed(true);
        rect = new Rect(lastView.getLeft(), lastView.getTop(), lastView.getRight(), lastView.getBottom());
    }

    if (event.getAction() == MotionEvent.ACTION_UP) {

        if (!rect.contains((int) event.getX(), (int) event.getY())) {

            lastView.setPressed(false);
            lastView=null;

        }  else {

            lastView.performClick();
            lastView.setPressed(false);
            lastView=null;
        }
    }

    if(event.getAction() == MotionEvent.ACTION_MOVE){

        if(!rect.contains((int) event.getX(),(int) event.getY())){

            lastView.setPressed(false);
            lastView=null;
        }
    }

    if (event.getAction() == MotionEvent.ACTION_CANCEL){

        lastView.setPressed(false);
        lastView=null;
    }

    return true;
}


public View getClosestChildToTouch(MotionEvent ev){

    float min = 99999999f;
    int minIndex = 0;

    for (int i = 0; i < getChildCount(); i++) {

        View child = getChildAt(i);

        float centerX = child.getX() + child.getWidth() / 2;
        float centerY = child.getY() + child.getHeight() / 2;

        float dis = (float) Math.sqrt(
                (ev.getX() - centerX) *  (ev.getX() - centerX) +
                        (ev.getY() - centerY) *  (ev.getY() - centerY)
        );

        if(dis < min) {
            min = dis;
            minIndex = i;
        }
    }

    return getChildAt(minIndex);
}

我也可以修改motionEvent对象并将孩子的左侧或右侧位置添加到x属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-18
    • 2016-06-04
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    相关资源
    最近更新 更多