当指针在多个视图上时,如何获得指针的总数?

时间:2016-06-15 07:58:41

标签: android motionevent android-touch-event

当多个指针在不同的视图上时,如何获得屏幕上的指针总数?我在屏幕上有多个视图,如果指针不在视图的相关区域,则视图将在false ON_DOWN的情况下返回onTouchEvent

当第一根手指在一个视图上,第二根手指触摸到另一个视图时,两个视图都将返回" 1"用于getPointerCount方法。有没有办法在整个屏幕上获得总指针计数,无论哪个视图处理指针触摸?

修改 Views不在同一个父ViewGroup中,这就是onInterceptTouch无法返回总指针数的原因。我可以将onInterceptTouch放到非常根ViewGroup,但是我希望Android能够提供指针的总计数而不需要像这样的一些肮脏的解决方法。

2 个答案:

答案 0 :(得分:1)

没有直接的方法可以使用Activity上调用的方法,而是使用@ S.D。指出,您可以使用onInterceptTouchEvent的{​​{1}}来执行此操作:

<强> MyLinearLayout.java

ViewGroup

<强> mylayout.xml

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

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


    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(21)
    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean onInterceptTouchEvent(final MotionEvent ev) {
        Log.e("TOUCHES", "num: " + ev.getPointerCount());

        return super.onInterceptTouchEvent(ev);
    }
}

<强> MyActivity.java

<mypackage.MyLinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/t1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.5"
        android:clickable="true"
        android:gravity="center"
        android:text="0"/>

    <TextView
        android:id="@+id/t2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.5"
        android:clickable="true"
        android:gravity="center"
        android:text="0"/>

</mypackage.MyLinearLayout>

此示例将使用每个public class MapsActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mylayout); final TextView t1 = (TextView) findViewById(R.id.t1); final TextView t2 = (TextView) findViewById(R.id.t2); t1.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(final View view, final MotionEvent motionEvent) { t1.setText(""+motionEvent.getPointerCount()); return true; } }); t2.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(final View view, final MotionEvent motionEvent) { t2.setText(""+motionEvent.getPointerCount()); return true; } }); } } 收到的TextView的{​​{1}}设置t1和t2 getPointerCount()的文本,并记录总值MotionEvent

收到的TextView getPointerCount()

答案 1 :(得分:1)

您需要一个自定义ViewGroup来拦截传下来的所有触摸事件。

您需要了解Android中的工作原理:

  • ViewGroup.onInterceptTouchEvent(MotionEvent)允许ViewGroup在触及儿童之前拦截触摸事件。如果您在此处返回true,则会在onTouchEvent()中收到后续触摸事件,并且在当前事件结束(删除指针)之前,孩子将不再接收任何触摸事件
  • 子视图可以请求父级禁止使用ViewGroup.requestDisallowInterceptTouchEvent(boolean)进行拦截:他们通常在识别正在进行的触摸事件时执行,并且他们不希望父级中断它。如果ViewGroup收到此请求,它必须将其传递给父级并尊重它(=不要从此处拦截事件)
  • 内部ViewGroup在收到onInterceptTouchEvent后不会致电requestDisallowInterceptTouchEvent(true)

如果您需要听取每个触摸事件,即使孩子们不允许拦截,您也需要欺骗ViewGroup认为它没有被禁止但你仍然需要尊重禁止(避免拦截触摸事件)

这是我为我的一个项目编写的一个类,它正是这样做的:

public class InterceptTouchFrameLayout extends FrameLayout {
    private boolean mDisallowIntercept;

    public interface OnInterceptTouchEventListener {
        /**
         * If disallowIntercept is true the touch event can't be stealed and the return value is ignored.
         * @see android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
         */
        boolean onInterceptTouchEvent(InterceptTouchFrameLayout view, MotionEvent ev, boolean disallowIntercept);

        /**
         * @see android.view.View#onTouchEvent(android.view.MotionEvent)
         */
        public boolean onTouchEvent(InterceptTouchFrameLayout view, MotionEvent event);
    }

    private static final class DummyInterceptTouchEventListener implements OnInterceptTouchEventListener {
        @Override
        public boolean onInterceptTouchEvent(InterceptTouchFrameLayout view, MotionEvent ev, boolean disallowIntercept) {
            return false;
        }
        @Override
        public boolean onTouchEvent(InterceptTouchFrameLayout view, MotionEvent event) {
            return false;
        }
    }

    private static final OnInterceptTouchEventListener DUMMY_LISTENER = new DummyInterceptTouchEventListener();

    private OnInterceptTouchEventListener mInterceptTouchEventListener = DUMMY_LISTENER;

    public InterceptTouchFrameLayout(Context context) {
        super(context);
    }

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

    public InterceptTouchFrameLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        getParent().requestDisallowInterceptTouchEvent(disallowIntercept);
        mDisallowIntercept = disallowIntercept;
    }

    public void setOnInterceptTouchEventListener(OnInterceptTouchEventListener interceptTouchEventListener) {
        mInterceptTouchEventListener = interceptTouchEventListener != null ? interceptTouchEventListener : DUMMY_LISTENER;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean stealTouchEvent = mInterceptTouchEventListener.onInterceptTouchEvent(this, ev, mDisallowIntercept);
        return stealTouchEvent && !mDisallowIntercept || super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean handled = mInterceptTouchEventListener.onTouchEvent(this, event);
        return handled || super.onTouchEvent(event);
    }
}

您只需将听众设置为:view.setOnInterceptTouchEventListener()

在该侦听器中,您可以保持指针数量(在onIntercetTouchEvent()方法内)。 只需将该布局作为布局的根目录(全屏)。

如果你试图在没有禁令的情况下做同样的事情,你可能会得到不正确的信息,因为你没有被授予接收所有触摸事件的权利。