android 如何监听用户无操作

官方没有给我们提供一个这样的API,一切都靠自己想逻辑啦!
我是这样想的:
用户无操作实际上就是用户不在编辑,也不在屏幕上点击或摩擦(Move);
监听点击和摩擦时间就是要用activity的API,但是特么像dialog和popuWindow这种弹窗的点击和摩擦就不归activity管的。
然而需求是 当有弹窗出现时,认为用户有操作。那么有两个办法:

1.基类管理法:自定义一个基类BaseDialog继承自Dialog,或者基类BasePopuWindow继承自PopuWindow,然后重写show()(如果是popuWindow就是showAtLocation()或showAsDropDown())和dismiss()方法,在里面加自己的boolean值标志符。然后项目中所有的dialog和popuWindow全部继承对应基类即可。

2.activity焦点管理法:这个方法也需要写一个activity的基类BaseActivity,里面重写方法

 @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        //activity发生焦点变化监听
        Log.e(TAG, "onWindowFocusChanged: activity焦点变化=="+hasFocus );
    }

应用里全部activity都去继承BaseActivity。
在这个onWindowFocusChanged(boolean hasFocus)方法里加你自己定的boolean值标志符,以后既可以拿这个标志符作为判断是否activity的焦点被弹窗所抢。从而判断弹窗是否弹出来或者应用是否进入后台了。

我用的是第二种方法,省事儿…

那么在没有弹窗的情况下,监听用户是否在点击activity或摩擦activity呢?
<通过Window的回调!>
以下自定义一个Window的回调:

public class WinCallback implements Window.Callback {
    Window.Callback callback;

    public WinCallback(Window.Callback callback) {
        this.callback = callback;
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        return callback.dispatchKeyEvent(event);
    }

    @Override
    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
        return callback.dispatchKeyShortcutEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        return callback.dispatchTouchEvent(event);
    }

    @Override
    public boolean dispatchTrackballEvent(MotionEvent event) {
        return callback.dispatchTrackballEvent(event);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
    @Override
    public boolean dispatchGenericMotionEvent(MotionEvent event) {
        return callback.dispatchGenericMotionEvent(event);
    }

    @Override
    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
        return callback.dispatchPopulateAccessibilityEvent(event);

    }

    @Override
    public View onCreatePanelView(int featureId) {
        return callback.onCreatePanelView(featureId);
    }

    @Override
    public boolean onCreatePanelMenu(int featureId, Menu menu) {
        return callback.onCreatePanelMenu(featureId, menu);
    }

    @Override
    public boolean onPreparePanel(int featureId, View view, Menu menu) {
        return callback.onPreparePanel(featureId, view, menu);
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        return callback.onMenuOpened(featureId, menu);
    }

    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        return callback.onMenuItemSelected(featureId, item);
    }

    @Override
    public void onWindowAttributesChanged(WindowManager.LayoutParams attrs) {
        callback.onWindowAttributesChanged(attrs);
    }

    @Override
    public void onContentChanged() {
        callback.onContentChanged();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        callback.onWindowFocusChanged(hasFocus);
    }

    @Override
    public void onAttachedToWindow() {
        callback.onAttachedToWindow();
    }

    @Override
    public void onDetachedFromWindow() {
        callback.onDetachedFromWindow();
    }

    @Override
    public void onPanelClosed(int featureId, Menu menu) {
        callback.onPanelClosed(featureId, menu);
    }

    @Override
    public boolean onSearchRequested() {
        return callback.onSearchRequested();
    }

    @Override
    public boolean onSearchRequested(SearchEvent searchEvent) {
        return false;
    }

    @Override
    public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
        return this.callback.onWindowStartingActionMode(callback);
    }

    @Nullable
    @Override
    public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
        return null;
    }

    @Override
    public void onActionModeStarted(ActionMode mode) {
        callback.onActionModeStarted(mode);
    }

    @Override
    public void onActionModeFinished(ActionMode mode) {
        callback.onActionModeFinished(mode);
    }
}

怎么用呢?
请看:

Activity activity = ContextBean.getInstance().getActivity();
 if (activity == null) { return; }
 Window win = activity.getWindow();
        Log.e(TAG, "touchOnclick: activity="+activity );
        win.setCallback(new WinCallback(win.getCallback()) {
            @Override
            public boolean dispatchTouchEvent(MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                    case MotionEvent.ACTION_MOVE:
                        Log.e(TAG, "dispatchTouchEvent:activity窗口被触摸");
                        break;
                    case MotionEvent.ACTION_UP:
                       Log.e(TAG, "dispatchTouchEvent:手指离开activity窗口");
                        break;
                }
                return super.dispatchTouchEvent(event);
            }
        });

ContextBean.getInstance().getActivity()就是上一篇文章全局获取当前展示的activity。

还有一种情况,就是EditText这个控件被编辑的时候,是不归以上的触摸监听管的。
整个工程那么多EditText,总不能一个一个去写监听,那么还是用基类管理的思路,写一个自定义基类MyEditText继承自AppCompatEditText:

public class MyEditText extends AppCompatEditText {
    private static final String TAG = "MyEditText";
    public MyEditText(Context context) {
        super(context);
        setOnFocusChangeListener(listener);
    }

    public MyEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOnFocusChangeListener(listener);
    }

    public MyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setOnFocusChangeListener(listener);
    }

    OnFocusChangeListener listener = new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            //是否在编辑editText,editText被销毁时不调用这个,调用onDetachedFromWindow()
    			 Log.e(TAG, "EditText是否被编辑=="+hasFocus);
        }
    };

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        Log.e(TAG, "EditText被销毁==");
    }
}

同理,这儿可以加boolean值标志符,作为你判断用户是否在编辑的依据。
然后,整个工程里所有用到EditText的布局文件,全部“<EditText ” 改为“<你的app包名.MyEditText”即可。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值