Adroid学习之 从源码角度分析-禁止使用回退按钮方案

有时候,不能让用户进行回退操作,如何处理?

查看返回键触发了哪些方法。在打开程序后把这个方法禁止了。
问题:程序在后台驻留,这样就会出现,其他时候也不能使用回退按钮。如何处理,在onpase()时方法失效。
方案一:
1 //重载onBackPressed

2 @Override

3 public void onBackPressed() {

4         // TODO Auto-generated method stub

5         //super.onBackPressed();

6 }

查看Adroid源码 onBackPressed ()源码:

1     public void onBackPressed() {

2         finish();

3     }

重写这个方法会不会有什么问题呢?他执行一个finish();方法对其本身应该没什么问题,那么调用出呢?

下面是Activity中调用的两处:
Adroid源码调用1:
 1     public boolean onKeyDown(int keyCode, KeyEvent event) {

 2     //当按钮等于KEYCODE_BACK时执行下面方法,KEYCODE_BACK这个就是返回键

 3         if (keyCode == KeyEvent.KEYCODE_BACK) {

 4            //检测版本号   ECLAIR 值为:public static final int ECLAIR = 5;

 5             if (getApplicationInfo().targetSdkVersion

 6                     >= Build.VERSION_CODES.ECLAIR) {

 7             //当大于5是执行

 8             /**startTracking()解释:调用onKeyUp()方法。

 9             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.

10             */

11                 event.startTracking();

12             } else {

13                 onBackPressed();

14             }

15             return true;

16         }

17 }

Adroid源码调用2:

 1     public boolean onKeyUp(int keyCode, KeyEvent event) {

 2         if (getApplicationInfo().targetSdkVersion

 3                 >= Build.VERSION_CODES.ECLAIR) {

 4             if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()

 5                     && !event.isCanceled()) {

 6                 onBackPressed();

 7                 return true;

 8             }

 9         }

10         return false;

11     }

  到这里可以看出我们在onBackPressed()被调用处,都是在按下返回键的情况下,所以可以冲写onBackPressed方法,因为是被调用的,虽然不会出错,但是效率应该不高。

要不我们重写 onKeyDown方法这样可行,直接拦截。
1  @Override 

2     public boolean onKeyDown(int keyCode, KeyEvent event) { 

3         if(keyCode==KeyEvent.KEYCODE_BACK) {

4             Toast.makeText(getApplicationContext(), "back press", Toast.LENGTH_LONG).show();

5              return false; // Disable back button.............. 

6 }

但是会如果在按钮处直接拦截,效果应该会高一些,这样就不会触发上面这两个方法了。

于是乎我们继续向上寻找。
细心的朋友可能发现onBackPressed()调用了finish()方法,所以干脆我们重写它吧。
方案二:重载finish函数:
查看Android的 finish()源码:
 1 public void finish() {

 2         if (mParent == null) {

 3             int resultCode;

 4             Intent resultData;

 5             synchronized (this) {

 6                 resultCode = mResultCode;

 7                 resultData = mResultData;

 8             }

 9             if (Config.LOGV) Log.v(TAG, "Finishing self: token=" + mToken);

10             try {

11                 if (ActivityManagerNative.getDefault()

12                     .finishActivity(mToken, resultCode, resultData)) {

13                     mFinished = true;

14                 }

15             } catch (RemoteException e) {

16                 // Empty

17             }

18         } else {

19             mParent.finishFromChild(this);

20         }

21     }

查看Android源码中调用它的方法:

 1     /**

 2      * This is called when a child activity of this one calls its

 3      * {@link #finish} method. The default implementation simply calls

 4      * finish() on this activity (the parent), finishing the entire group.

 5      *

 6      * @param child The activity making the call.

 7      *

 8      * @see #finish

 9      */

10     public void finishFromChild(Activity child) {

11         finish();

12     }

从说明中我们知道这个方法是在子Activity结束时调用的这个方法,所以不行,如果我们要重写,需要进行判断拿到的键值。效率不高。

继续寻找,看看哪里执行了调用方法按键吧。
方案三: 重写keyevent方法 大括号里加上return true 这样就禁用父类方法达到禁止返回键的目的 
Android源码中找来找去找到了这个:
 1  /**

 2      * Called to process key events. You can override this to intercept all

 3      * key events before they are dispatched to the window. Be sure to call

 4      * this implementation for key events that should be handled normally.

 5      *

 6      * @param event The key event.

 7      *

 8      * @return boolean Return true if this event was consumed.

 9      */

10     public boolean dispatchKeyEvent(KeyEvent event) {

11         onUserInteraction();

12         Window win = getWindow();

13         if (win.superDispatchKeyEvent(event)) {

14             return true;

15         }

16         View decor = mDecor;

17         if (decor == null) decor = win.getDecorView();

18         return event.dispatch(this, decor != null

19                 ? decor.getKeyDispatcherState() : null, this);

20     }

就是在按钮触发的事件,当然是Activity中的。到此我们发现我们找到地方了,按钮进入后第一个处理的地方,再次我们重写这个方法就OK了。

 1 @Override

 2 

 3 public boolean dispatchKeyEvent(KeyEvent event) {

 4 

 5 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) 

 6         {     

 7 

 8      return true; 

 9 

10         }

11 

12 return super.dispatchKeyEvent(event);

13 

14 }

 


你可能感兴趣的:(adroid)