關於Android中使用BottomNavigationView切換橫屏導致返回主頁的問題

蕭安發表於2019-04-20

問題:

如圖,“發現”頁即為主頁,然後我們切換到“我”頁,一切正常。

Avatar
Avatar

那麼問題來了,如果切換到“我”頁後把手機橫屏,則會出現下面的情況。

Avatar

嗯?怎麼又回到“發現”頁了??

解決辦法:

思考

據自己瞭解,Android應用程式重新整理頁面有兩種情況,第一種是使用者操作;
第二種非使用者操作,即系統觸發的。很明顯這是系統觸發的咯。
然後,搬來Android應用程式生命週期圖:

Avatar

看到,在整個生命週期中,APP會呼叫onCreate()、onStart()、onResume()、onPause()、onStop()、onRestart()、onDestroy()這幾個函式。所以,我在MainActivity.java中重構這幾個函式,使用LogCat來驗證在橫屏的過程中,APP就呼叫了哪些函式。


    public class MainActivity extends AppCompatActivity {

        private BottomNavigationView bottomNavigationView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //隱藏預設的頂部導航
            getSupportActionBar().hide();
    
            //獲取底部導航檢視例項
            bottomNavigationView = findViewById(R.id.bottomNavi);
    
            //把“發現”頁作為主頁
            getSupportFragmentManager().beginTransaction().replace(R.id.contentFrame,new DiscoverFragment()).commit();
            //註冊底部導航按鈕點選事件
            bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                    FragmentTransaction transition = getSupportFragmentManager().beginTransaction();
    
                    switch (menuItem.getItemId()){
                        case R.id.bottomNavi_discover:
                            transition.replace(R.id.contentFrame,new DiscoverFragment()).commit();
                            break;
                        case R.id.bottomNavi_friends:
                            transition.replace(R.id.contentFrame,new FriendFragment()).commit();
                            break;
                        case R.id.bottomNavi_communicate:
                            transition.replace(R.id.contentFrame,new CommunicateFragment()).commit();
                            break;
                        case R.id.bottomNavi_myself:
                            transition.replace(R.id.contentFrame,new MeFragment()).commit();
                            break;
                    }
                    return true;
                }
            });
            Log.i("MainActivity","onCreate()");
    
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.i("MainActivity","onStart()");
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            Log.i("MainActivity","onResume()");
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            Log.i("MainActivity","onPause()");
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            Log.i("MainActivity","onStop()");
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.i("MainActivity","onDestroy()");
        }
    
        @Override
        protected void onRestart() {
            super.onRestart();
            Log.i("MainActivity","onRestart()");
        }
    }

下面執行程式,橫屏後,LogCat輸出如下:

Avatar

仔細觀察發現,橫屏後,程式再次呼叫了onCreate()函式,頁面不重新整理才怪勒!

解決

思路

在橫屏前,先儲存當前瀏覽的資料,然後在橫屏後,恢復這個資料就可以了。
所以,新增一個訊號量(全域性變數),用來儲存當前瀏覽的頁面位置(1,2,3,4)

    private int PageFlag = 1;

然後再加入如下程式碼,目的是在程式呼叫onDestroy()之前,通過onSaveInstanceState()函式儲存當前的PageFlag值,在橫屏後呼叫onRestoreInstanceState()時,恢復PageFlag的值,通過此方法恢復橫屏前訪問的頁面。



    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("KEY_PAGE_INDEX",PageFlag);

    }
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        if (savedInstanceState!=null){
            PageFlag = savedInstanceState.getInt("KEY_PAGE_INDEX");
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            switch (PageFlag){
                case 1:
                    transaction.replace(R.id.contentFrame,new DiscoverFragment()).commit();
                    PageFlag = 1;
                    break;
                case 2:
                    transaction.replace(R.id.contentFrame,new FriendFragment()).commit();
                    PageFlag = 2;
                    break;
                case 3:
                    transaction.replace(R.id.contentFrame,new CommunicateFragment()).commit();
                    PageFlag = 3;
                    break;
                case 4:
                    transaction.replace(R.id.contentFrame,new MeFragment()).commit();
                    PageFlag = 4;
                    break;
            }
        }
    }

再次橫屏,

Avatar

OK,問題解決!

注意

此APP僅用於學習,其中使用的是《小黑盒APP》中的資源

相關文章