Adroid学习之 从源码角度分析-禁止使用回退按钮方案
2014-04-25 13:41
645 查看
有时候,不能让用户进行回退操作,如何处理?
查看返回键触发了哪些方法。在打开程序后把这个方法禁止了。
问题:程序在后台驻留,这样就会出现,其他时候也不能使用回退按钮。如何处理,在onpase()时方法失效。
方案一:
查看Adroid源码 onBackPressed ()源码:
重写这个方法会不会有什么问题呢?他执行一个finish();方法对其本身应该没什么问题,那么调用出呢?
下面是Activity中调用的两处:
Adroid源码调用1:
Adroid源码调用2:
到这里可以看出我们在onBackPressed()被调用处,都是在按下返回键的情况下,所以可以冲写onBackPressed方法,因为是被调用的,虽然不会出错,但是效率应该不高。
要不我们重写onKeyDown方法这样可行,直接拦截。
但是会如果在按钮处直接拦截,效果应该会高一些,这样就不会触发上面这两个方法了。
于是乎我们继续向上寻找。
细心的朋友可能发现onBackPressed()调用了finish()方法,所以干脆我们重写它吧。
方案二:重载finish函数:
查看Android的 finish()源码:
查看Android源码中调用它的方法:
从说明中我们知道这个方法是在子Activity结束时调用的这个方法,所以不行,如果我们要重写,需要进行判断拿到的键值。效率不高。
继续寻找,看看哪里执行了调用方法按键吧。
方案三:重写keyevent方法 大括号里加上return true 这样就禁用父类方法达到禁止返回键的目的
Android源码中找来找去找到了这个:
就是在按钮触发的事件,当然是Activity中的。到此我们发现我们找到地方了,按钮进入后第一个处理的地方,再次我们重写这个方法就OK了。
查看返回键触发了哪些方法。在打开程序后把这个方法禁止了。
问题:程序在后台驻留,这样就会出现,其他时候也不能使用回退按钮。如何处理,在onpase()时方法失效。
方案一:
//重载onBackPressed @Override public void onBackPressed() { // TODO Auto-generated method stub //super.onBackPressed(); }
查看Adroid源码 onBackPressed ()源码:
public void onBackPressed() { finish(); }
重写这个方法会不会有什么问题呢?他执行一个finish();方法对其本身应该没什么问题,那么调用出呢?
下面是Activity中调用的两处:
Adroid源码调用1:
public boolean onKeyDown(int keyCode, KeyEvent event) { //当按钮等于KEYCODE_BACK时执行下面方法,KEYCODE_BACK这个就是返回键 if (keyCode == KeyEvent.KEYCODE_BACK) { //检测版本号 ECLAIR 值为:public static final int ECLAIR = 5; if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.ECLAIR) { //当大于5是执行 /**startTracking()解释:调用onKeyUp()方法。 Call this during Callback.onKeyDown to have the system track the key through its final up (possibly including a long press). Note that only one key can be tracked at a time -- if another key down event is received while a previous one is being tracked, tracking is stopped on the previous event. */ event.startTracking(); } else { onBackPressed(); } return true; } }
Adroid源码调用2:
public boolean onKeyUp(int keyCode, KeyEvent event) { if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.ECLAIR) { if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking() && !event.isCanceled()) { onBackPressed(); return true; } } return false; }
到这里可以看出我们在onBackPressed()被调用处,都是在按下返回键的情况下,所以可以冲写onBackPressed方法,因为是被调用的,虽然不会出错,但是效率应该不高。
要不我们重写onKeyDown方法这样可行,直接拦截。
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode==KeyEvent.KEYCODE_BACK) { Toast.makeText(getApplicationContext(), "back press", Toast.LENGTH_LONG).show(); return false; // Disable back button.............. }
但是会如果在按钮处直接拦截,效果应该会高一些,这样就不会触发上面这两个方法了。
于是乎我们继续向上寻找。
细心的朋友可能发现onBackPressed()调用了finish()方法,所以干脆我们重写它吧。
方案二:重载finish函数:
查看Android的 finish()源码:
public void finish() { if (mParent == null) { int resultCode; Intent resultData; synchronized (this) { resultCode = mResultCode; resultData = mResultData; } if (Config.LOGV) Log.v(TAG, "Finishing self: token=" + mToken); try { if (ActivityManagerNative.getDefault() .finishActivity(mToken, resultCode, resultData)) { mFinished = true; } } catch (RemoteException e) { // Empty } } else { mParent.finishFromChild(this); } }
查看Android源码中调用它的方法:
/** * This is called when a child activity of this one calls its * {@link #finish} method. The default implementation simply calls * finish() on this activity (the parent), finishing the entire group. * * @param child The activity making the call. * * @see #finish */ public void finishFromChild(Activity child) { finish(); }
从说明中我们知道这个方法是在子Activity结束时调用的这个方法,所以不行,如果我们要重写,需要进行判断拿到的键值。效率不高。
继续寻找,看看哪里执行了调用方法按键吧。
方案三:重写keyevent方法 大括号里加上return true 这样就禁用父类方法达到禁止返回键的目的
Android源码中找来找去找到了这个:
/** * Called to process key events. You can override this to intercept all * key events before they are dispatched to the window. Be sure to call * this implementation for key events that should be handled normally. * * @param event The key event. * * @return boolean Return true if this event was consumed. */ public boolean dispatchKeyEvent(KeyEvent event) { onUserInteraction(); Window win = getWindow(); if (win.superDispatchKeyEvent(event)) { return true; } View decor = mDecor; if (decor == null) decor = win.getDecorView(); return event.dispatch(this, decor != null ? decor.getKeyDispatcherState() : null, this); }
就是在按钮触发的事件,当然是Activity中的。到此我们发现我们找到地方了,按钮进入后第一个处理的地方,再次我们重写这个方法就OK了。
@Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { return true; } return super.dispatchKeyEvent(event); }
相关文章推荐
- 开源中国源码学习UI篇(三)之ViewPager+Fragment的使用分析
- Hama框架学习(一) 从源码角度分析job的提交和运行过程
- Mybatis底层原理学习(二):从源码角度分析一次查询操作过程
- 友善之臂视频监控方案源码学习(1) - 架构分析
- 友善之臂视频监控方案源码学习(1) - 架构分析
- 一步步学习 Mybatis:缓存的使用及源码分析
- Android开发学习之路-LruCache使用和源码分析
- 从源码角度彻底分析layout_weight使用
- java学习之旅56--数组_StringBuilder和StringBuffer的使用_常用方法_方法链的实现_JDK源码分析
- java学习之旅65--常用类_Date类的使用_JDk源码分析
- java学习之旅57、58--数组_StringBuilder和StringBuffer的使用_JDK源码分析内部机制、常用方法补充_常见面试题答法
- 开源中国源码学习UI篇(一)之FragmentTabHost的使用分析
- 友善之臂视频监控方案源码学习(1) - 架构分析
- Volley简单学习使用五—— 源码分析三
- Volley简单学习使用四——源码分析二
- AIDL使用学习(三):源码深入分析
- 通过ArrayList迭代器使用进行JDK源码分析学习迭代器
- Libevent学习---evconnlistener使用和源码分析
- shiro学习笔记——从源码角度分析shiro身份验证过程
- [学习总结]8、android 自定义控件 使用declare-styleable进行配置属性(源码角度)