1

当多个指针位于不同的视图上时,如何获取屏幕上的指针总数?我在屏幕上有多个视图,如果指针不在视图的相关区域,视图将falseON_DOWN.onTouchEvent

当第一根手指在一个视图上并且第二根手指触摸另一个视图时,两个视图都将为getPointerCount方法返回“1”。无论哪个视图处理指针的触摸,有什么方法可以在整个屏幕上获得总指针计数?

编辑: Views不在同一个 parentViewGroup中,这就是为什么onInterceptTouch不返回总指针计数的原因。我可以onInterceptTouch非常root ViewGroup,但是我希望Android能够在没有像这样的肮脏解决方法的情况下给出指针总数。

4

2 回答 2

1

没有直接的方法可以使用被调用的方法来做到这一点,Activity但正如@SD 指出的那样,您可以使用onInterceptTouchEventofViewGroup来做到这一点:

MyLinearLayout.java

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);
    }
}

我的布局.xml

<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>

我的活动.java

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;
            }
        });
    }
}

本例将 t1 和 t2 的文本设置为TextView每个getPointerCount()接收MotionEvent到的文本,并将记录接收到的TextView总值getPointerCount()MotionEventMyLinearLayout

于 2016-06-17T12:26:10.270 回答
1

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

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

  • ViewGroup.onInterceptTouchEvent(MotionEvent)允许 ViewGroup 在触摸事件到达子级之前拦截它们。如果您返回true此处,您将收到后续的触摸事件,onTouchEvent()并且在当前事件结束之前,孩子将不会再收到任何触摸事件(指针已移除)
  • 子视图可以通过以下方式请求父级禁止拦截ViewGroup.requestDisallowInterceptTouchEvent(boolean):它们通常在识别正在进行的触摸事件并且不希望父级中断它时这样做。如果 ViewGroup 收到这个请求,它必须将它传递给父级并尊重它(= 从这里开始不要拦截事件)
  • 内部 a ViewGroupwill not call onInterceptTouchEventafter requestDisallowInterceptTouchEvent(true)is received

如果您需要监听每个触摸事件,即使孩子不允许拦截,您也需要诱使孩子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()方法内部)。只需将该布局作为布局的根目录(全屏)。

如果您尝试在不使用禁止技巧的情况下执行相同操作,则最终可能会得到不正确的信息,因为您没有被授予接收所有触摸事件的权限。

于 2016-06-17T13:28:50.010 回答