gpt4 book ai didi

android - 我如何在 Android 中打开微调器之外监听触摸?

转载 作者:搜寻专家 更新时间:2023-11-01 07:45:44 26 4
gpt4 key购买 nike

我正在做一个项目,要求我在屏幕上发生不同类型的触摸时写入日志。当我触摸打开的微调器下拉菜单的外部时,它会关闭。我不知道如何检测这种触摸。

这段代码没有捕捉到它,但它似乎捕捉到了小部件之外的所有其他触摸:

mFullView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
touchCounter++;
Log.d(TAG, "Touch #" + touchCounter + ", no button touch registered.");
}
return false;
}
});

其中 mFullView 是我拥有的父 RelativeLayout 并且设置如下:

mFullView = findViewById(R.id.full_view);

我也试过像这样使用 onTouchEvent:

@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
Log.d(TAG, "screen was touched outside of open spinner dropdown");
}
return super.onTouchEvent(event);
}

我在 onCreate 之外有这段代码,对放置或实现不太自信。

我找不到关于如何实现这个的任何信息,感谢您的帮助!

最佳答案

单击时,Spinner 将显示一个Dialog 或一个PopupWindow。这些都不会附加到与您的 Activity 相同的 Window,因此您将无法从那里拦截触摸事件。

也许有人可以破解他的子类化 Spinner

我找到了一种方法来做到这一点,它非常 hacky。

1- 我们需要覆盖 public void onWindowFocusChanged(boolean hasFocus) 这个方法将在 ActivityWindow 丢失时被调用焦点是因为 PopupWindow 的 View 已附加到 Activity 的 View 之上的新 Window

2- 获取所有 Window 的根 View 的列表,this answer有一个非常肮脏的 hacky 方法来做到这一点

3- 这些根 View 之一将是 PopupDecorView,它是 PopupWindow 的私有(private)非静态类。我们需要通过反射获取PopupWindow的实例

4- 一旦我们有了 PopupWindow 的实例,我们需要获取 OnTouchListener,将它包裹在我们自己的一个实例上并将其设置回 弹出窗口

重写的方法如下所示:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
new Handler().post(new Runnable() {
@Override
public void run() {
for(View view : getWindowManagerViews()){
try {
Class clazz = view.getClass();
Field outerField = clazz.getDeclaredField("this$0");
outerField.setAccessible(true);
Object popupWindow = outerField.get(view);

Field field = popupWindow.getClass().getDeclaredField("mTouchInterceptor");
field.setAccessible(true);
final View.OnTouchListener innerOnTouchListener = (View.OnTouchListener) field.get(popupWindow);
View.OnTouchListener outerOnTOuchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d(MainActivity.class.getSimpleName(), String.format("popupwindow event %s at %s-%s", event.getAction(), event.getX(), event.getY()));
return innerOnTouchListener.onTouch(v, event);
}
};
field.set(popupWindow, outerOnTOuchListener);
}catch (Exception e){
//e.printStackTrace();
}
}
}
});
}

其中 getWindowManagerViews() 取自上述答案,看起来像这样

public static List<View> getWindowManagerViews() {
try {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {

// get the list from WindowManagerImpl.mViews
Class wmiClass = Class.forName("android.view.WindowManagerImpl");
Object wmiInstance = wmiClass.getMethod("getDefault").invoke(null);

return viewsFromWM(wmiClass, wmiInstance);

} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {

// get the list from WindowManagerGlobal.mViews
Class wmgClass = Class.forName("android.view.WindowManagerGlobal");
Object wmgInstance = wmgClass.getMethod("getInstance").invoke(null);

return viewsFromWM(wmgClass, wmgInstance);
}

} catch (Exception e) {
e.printStackTrace();
}

return new ArrayList<View>();
}

private static List<View> viewsFromWM(Class wmClass, Object wmInstance) throws Exception {

Field viewsField = wmClass.getDeclaredField("mViews");
viewsField.setAccessible(true);
Object views = viewsField.get(wmInstance);

if (views instanceof List) {
return (List<View>) viewsField.get(wmInstance);
} else if (views instanceof View[]) {
return Arrays.asList((View[])viewsField.get(wmInstance));
}

return new ArrayList<View>();
}

关于android - 我如何在 Android 中打开微调器之外监听触摸?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44785267/

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