Android View 全局触摸事件监听基类

前文 Android超出父布局控件点击事件失效问题处理 讲了当使用 clipChildren=false 属性时,超出父控件的子控件区域点击会失效的问题,也给出了解决方案,但是觉得还不够方便,就封装了一个 GlobalTouchActivity 基类,以便于使用。

  • 代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    package com.game.win.xxx.sdk.pages.ui;

    import android.app.Activity;
    import android.graphics.Point;
    import android.graphics.Rect;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;

    import androidx.annotation.Nullable;

    import com.game.win.wallet.sdk.utils.ViewUtils;

    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;

    public class GlobalTouchActivity extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    supportGlobalTouchListener();
    }

    /**
    * 全局点击事件监听
    */
    public interface OnGlobalTouchListener{
    /**
    * 监听事件回调
    * @param rect View所在坐标范围
    * @param point 点击事件发生的坐标
    */
    void onTouch(Rect rect, Point point);
    }

    final Map<View,OnGlobalTouchListener> globalTouchViews = new HashMap<>();


    /**
    * 支持全局触摸事件监听
    */
    public void supportGlobalTouchListener(){
    getWindow().getDecorView().getRootView().setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
    Set<Map.Entry<View, OnGlobalTouchListener>> touchViewSet = globalTouchViews.entrySet();
    Iterator<Map.Entry<View, OnGlobalTouchListener>> it = touchViewSet.iterator();
    while(it.hasNext()){
    Map.Entry<View, OnGlobalTouchListener> entry = it.next();
    View view = entry.getKey();
    if(globalTouch(view,event)){
    Rect rect = new Rect();
    view.getGlobalVisibleRect(rect);
    OnGlobalTouchListener globalTouchListener = entry.getValue();
    if(globalTouchListener!=null){
    globalTouchListener.onTouch(rect,new Point((int)event.getRawX(),(int)event.getRawY()));
    }
    return true;
    }
    }
    return false;
    }
    });
    }

    /**
    * 设置全局触摸事件监听
    * @param view
    * @param listener
    */
    public void setGlobalTouchListener(View view,OnGlobalTouchListener listener){
    globalTouchViews.put(view,listener);
    }

    /**
    * 全局坐标点击判断
    * @param targetView
    * @param event
    * @return
    */
    private boolean globalTouch(View targetView, MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_UP){
    Rect r = new Rect();
    targetView.getGlobalVisibleRect(r);
    int x = (int) event.getRawX();
    int y = (int) event.getRawY();
    return r.contains(x,y);
    }
    return false;
    }

    @Override
    public void onDetachedFromWindow() {
    globalTouchViews.clear();
    super.onDetachedFromWindow();
    }
    }

    这样一来,当需要处理全局事件点击时,直接继承自 GlobalTouchActivity ,然后设置全局触摸点击事件,就变得非常简单了:

    1
    2
    3
    4
    5
    6
    setGlobalTouchListener(center_icon, new OnGlobalTouchListener() {
    @Override
    public void onTouch(Rect rect, Point point) {
    finish();
    }
    });
文章作者: 普通程序员
文章链接: https://programmerauthor.github.io/2020/03/15/globaltouch-activity/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 普通程序员