3. WebView 返回键与历史记录管理
返回键与历史记录:先判断“能不能回”,再决定“回哪里”
WebView 自带前进/后退历史栈,但系统返回键默认只会结束当前 Activity。要让返回键优先服务于网页历史,需要在 Activity 的按键分发阶段拦截 KEYCODE_BACK,先查询 canGoBack(),再决定调用 goBack() 还是交还给系统退出。
核心实现:重写 onKeyDown
在承载 WebView 的 Activity 中重写 onKeyDown,当按下返回键且 WebView 可回退时,调用 goBack() 并返回 true 表示事件已消费;否则调用 super.onKeyDown() 让系统执行默认退出逻辑。
public class WebViewActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);
webView = findViewById(R.id.webView);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("file:///android_asset/index.html");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (webView.canGoBack()) {
webView.goBack();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
}
为什么用 onKeyDown 而不是 onBackPressed?
onKeyDown 在按键分发阶段更早介入,能明确区分“返回键”与其他按键;onBackPressed() 在较新 API 中已被 OnBackPressedDispatcher 取代。若项目使用 AndroidX,推荐改用 getOnBackPressedDispatcher().addCallback(),逻辑等价但兼容性更好。
历史记录状态与行为对照
| canGoBack() | canGoForward() | 返回键行为 | 返回值 |
|---|---|---|---|
| true | 任意 | webView.goBack() | true(消费) |
| false | 任意 | super.onKeyDown() → finish() | false(交还系统) |
验证要点
- 加载首页后按返回键,应直接退出 Activity,而不是白屏或停留在首页。
- 点击页面内链接跳转到第二页后按返回键,应回到首页;再按一次才退出。
- 连续回退到栈底后,
canGoBack()返回false,此时返回键应触发退出。 - 若页面通过
loadUrl重新加载同一 URL,历史栈可能新增条目,需注意canGoBack()的返回值变化。
常见陷阱:在
onKeyDown 中只判断 canGoBack() 却忘记返回 true,会导致 WebView 回退后系统仍执行默认退出,出现“回退一页又立刻退出”的现象。务必在消费事件时返回 true。