ViewPager 內含 WebView 等複雜視圖時,螢幕旋轉觸發 Activity 重建,導致 ViewPager 重置至第 0 頁。需結合 onSaveInstanceState、Fragment.setRetainInstance(已棄用)、ViewModel 或 configChanges 保存當前頁面索引與片段狀態。
class PagerViewModel : ViewModel() {
var currentPage = 0
private set
fun setCurrentPage(page: Int) {
currentPage = page
}
}
// Activity/Fragment
val viewModel = ViewModelProvider(this).get(PagerViewModel::class.java)
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
viewModel.setCurrentPage(position)
}
})
// 恢復
viewPager.post { viewPager.setCurrentItem(viewModel.currentPage, false) }
private static final String KEY_CURRENT_PAGE = "current_page";
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_CURRENT_PAGE, viewPager.getCurrentItem());
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int page = savedInstanceState.getInt(KEY_CURRENT_PAGE, 0);
viewPager.post(() -> viewPager.setCurrentItem(page, false));
}
// Fragment 內
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true); // 保留 Fragment 實例,但 View 仍會重建
}
// ViewPager 使用 FragmentStatePagerAdapter(而非 FragmentPagerAdapter)
// FragmentStatePagerAdapter 會銷毀不可见 Fragment 的 View,保留實例
注意:setRetainInstance 在 Fragment 1.3.0+ 棄用,改用 ViewModel。
<activity
android:name=".PagerActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
</activity>
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// ViewPager、WebView 實例保留,無需重載
// 若需切換佈局,手動調用 viewPager.setAdapter(...) 或調整參數
}
// 方案 A:configChanges(最簡單)
// 方案 B:儲存/恢復 WebView 狀態
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
webView.saveState(outState); // 儲存歷史、捲動位置、表單資料
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
webView.restoreState(savedInstanceState);
}
| 場景 | 推薦方案 | 理由 |
|---|---|---|
| 一般 ViewPager + 簡單 Fragment | ViewModel + onSaveInstanceState | 架構清晰、支援進程死後恢復 |
| ViewPager + WebView(重載慢) | configChanges + WebView.saveState | 避免重建開銷、保留網頁狀態 |
| 複雜巢狀 Fragment | ViewModel + FragmentStateAdapter | 生命週期自動管理 |
理解 Activity 重建機制並選擇適當策略,能讓 ViewPager 在旋轉、多視窗、折疊螢幕等場景下保持流暢體驗。