您的位置:首页 > 其它

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

2014-04-25 13:41 645 查看
有时候,不能让用户进行回退操作,如何处理?

查看返回键触发了哪些方法。在打开程序后把这个方法禁止了。
问题:程序在后台驻留,这样就会出现,其他时候也不能使用回退按钮。如何处理,在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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: