【问题标题】:How to dispatch touch events to children after consuming消费后如何向孩子发送触摸事件
【发布时间】:2013-06-08 12:22:31
【问题描述】:

布局是这样的:

View 1 是自定义布局FlipperLayout,View 2 是扩展ListView PinnedHeaderListView,我想添加一个“拉动刷新”功能。视图 1 需要监听触摸事件才能向左或向右翻转。视图 2 也需要触摸事件。问题是,如果 View 1 消耗了触摸事件,View 2 就无法获取它。

即使在 View 1 使用事件之后,我如何才能将事件分派给 View 2?

【问题讨论】:

  • 你想向 view2 发送什么样的事件?
  • @pskink 我想听一个手势,所以基本上我需要 ACTION_DOWN、ACTION_MOVE、ACTION_UP
  • 好的,但是为什么 view1 中发生的事件必须传递给 view2?
  • @pskink Cuz 视图 1 包含视图 2
  • view1 是自定义布局,对吧?覆盖其 onInterceptTouchEvent mwthod 并在那里返回 false

标签: android


【解决方案1】:

考虑以下自定义布局:

class FlingLinearLayout extends LinearLayout {

    private GestureDetector mDetector;

    public FlingLinearLayout(Context context) {
        super(context);
        setOrientation(LinearLayout.VERTICAL);
        OnGestureListener listener = new SimpleOnGestureListener() {
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                Log.d(TAG, "onFling vx: " + velocityX + ", vy: " + velocityY);
                if (Math.abs(velocityX) > Math.abs(velocityY)) {
                    String text = (velocityX > 0? "left to right" : "right to left") + " fling";
                    Toast.makeText(getContext(), text, Toast.LENGTH_LONG).show();
                    return true;
                }
                return false;
            }
        };
        mDetector = new GestureDetector(context, listener);
        setBackgroundColor(0xaaff0000);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //Log.d(TAG, "onTouchEvent " + event);
        // handle own events (initiated in red area)
        mDetector.onTouchEvent(event);
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //Log.d(TAG, "onInterceptTouchEvent " + ev);
        // handle child events
        // note: if you horizontally fling over button its onClick() is not performed
        return mDetector.onTouchEvent(ev);
    }
}

及其在您的 Activity 中的用法:

ViewGroup ll = new FlingLinearLayout(this);
Button b;
OnClickListener l = new OnClickListener() {
    @Override
    public void onClick(View v) {
        Button b = (Button) v;
        Log.d(TAG, "onClick " + b.getText());
    }
};
b = new Button(this);
b.setText("first");
b.setOnClickListener(l);
ll.addView(b);
b = new Button(this);
b.setText("second");
b.setOnClickListener(l);
ll.addView(b);
b = new Button(this);
b.setText("third");
b.setOnClickListener(l);
ll.addView(b);
setContentView(ll);

【讨论】:

  • 返回的好处是 mDetector.onTouchEvent(ev);在 onInterceptTouchEvent
【解决方案2】:

触摸事件返回一个布尔值,指定事件是否被消费,只返回false,事件将继续隧道到子视图

【讨论】:

  • 不,这仅适用于第一个事件 ACTION_DOWN。下面的 ACTION_MOVE 和 ACTION_UP 会直接派发到返回 true 的那一个(在这种情况下应该是视图 2)。所以基本上,如果你只是在父视图中返回 false,你可以在父视图和子视图中捕获 ACTION_DOWN。但是您不能在父视图中捕获其他人,而只能在子视图2中捕获。这就是问题所在。
猜你喜欢
  • 2016-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-18
  • 1970-01-01
  • 1970-01-01
  • 2015-01-01
相关资源
最近更新 更多