gpt4 book ai didi

Android - 拦截并传递所有触摸事件

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:23:36 25 4
gpt4 key购买 nike

我有一个覆盖 View 组,它是我想在用户与应用程序交互时用来显示效果的屏幕大小,但仍将 onTouch 事件传递给任何基础 View 。

我对所有 MotionEvents(不仅仅是 DOWN)都很感兴趣,所以 onInterceptTouchEvent() 在这里不适用,因为如果我返回 true,我的覆盖将消耗所有事件,如果为 false,将只接收 DOWN 事件(同样适用于 onTouch ).

我想我可以覆盖 Activity dispatchTouchEvent(MotionEvent ev) 并在我的叠加层中调用自定义触摸事件,但这具有不根据我的 View 位置转换输入坐标的效果(例如,所有事件都将通过似乎发生在实际触摸下方 20 像素左右,因为未考虑系统栏)。

最佳答案

构建此类拦截器的唯一正确方法是使用自定义 ViewGroup 布局。

但是执行ViewGroup.onInterceptTouchEvent()仅仅捕捉每个触摸事件是不够的,因为 subview 可​​以调用 ViewParent.requestDisallowInterceptTouchEvent() :如果 subview 这样做,您的 View 将停止接收对 interceptTouchEvent 的调用(有关 subview 何时可以执行此操作的示例,请参见 here)。

这是我写的一个类(Java,很久以前......),当我需要这样的东西时使用它,它是自定义的 FrameLayout 可以完全控制委托(delegate)人的触摸事件

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;

/**
* A FrameLayout that allow setting a delegate for intercept touch event
*/
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)
*/
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 defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public InterceptTouchFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyle) {
super(context, attrs, defStyleAttr, 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);
}
}

此类提供了一个 setInterceptTouchEventListener() 来设置您的自定义拦截器。

当需要禁止拦截触摸事件时,它会作弊:将禁止传递给父 View ,就像它应该的那样,但继续拦截它们。但是,它不再让监听器拦截事件,因此如果监听器在拦截触摸事件时返回 true 将被忽略(如果您愿意,您可以选择抛出 IllegalStateException

通过这种方式,您可以透明地接收通过 ViewGroup 的每个触摸事件,而不会中断 subview 行为。

关于Android - 拦截并传递所有触摸事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6841971/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com