Android 多Fragment屏幕旋轉的問題

平時寫項目的時候會碰到一些需求是涉及到屏幕旋轉的,如果旋轉屏幕,你的界面佈局什麼都沒改變的話,那就很簡單了,但是如果當你屏幕旋轉後,需要更改頁面佈局的話,那就有點麻煩了。
舉個簡單的例子:
一開始新建一個項目,studio已經自動幫你新建好hello world的代碼。運行,然後手機設置可旋轉屏幕。
當你旋轉屏幕,你看到其實頁面沒什麼變化,還是一樣的佈局。但是這個顯示的Activity卻已經變化了。
任何“設置”(Configuration)的改變都可能對Activity的界面造成影響,這時系統會銷燬並重建Activity以便反映新的Configuration。 例如orientation,screenSize,字體大小,語言等都是屬於configuration,如果你在系統設置裏改變了這些,是需要反映到你的app上,那麼就會銷燬現有的activity,然後重新創建activity顯示。該activity先走了onPause,onStop,onDestroy,然後在onCreate。
假設屏幕旋轉前,用戶正在手機上填寫一個註冊表單,如果處理不當,用戶會發現旋轉後的表單變成空白的了,嚴重影響使用體驗。
分兩種情況講:

  1. 如果你的activity只有一種佈局(橫豎屏都是一樣的),那你旋轉的話,什麼代碼都不用寫。你的頁面還是一模一樣的。如果你頁面上有EditText,然後輸入一些內容,當你旋轉後發現這個輸入框中還是有你剛剛輸入的內容。明明說Activity重新創建了,爲什麼EditText中還有內容呢?這是因爲Google已經考慮到這種情況,對一些基本的控件做了處理,例如EditText,在旋轉時會記錄該EditText中的內容,當旋轉後activity重新創建後,會重新給該EditText賦值。但是不是所有的控件都有這種恢復能力。
    當然如果你界面上還有其他控件的話,沒有恢復能力,那你又只有一種佈局的話,其實只要設置旋轉對其activity無影響就好了。那就是在manifest中給該activity設置android:configChanges="orientation|screenSize|keyboardHidden"
    orientation,屏幕界面旋轉(可能是用戶手動旋轉的),【注意:如果你的開發API等級等於或高於13,你還需要設置screenSize,因爲screenSize會在屏幕旋轉時改變】。keyboardHidden,鍵盤輔助功能改變。
    注意,如果你給activity設置了這個,那麼當你旋轉的時候,就算你佈局有橫豎屏兩種,他也不會變了。這時候他顯示的佈局取決於一開始你打開這個app時的佈局。比如說當你打開app的時候,手機橫屏,那麼加載出來的佈局爲橫屏佈局,當你再旋轉到豎屏的話,佈局還是顯示爲橫屏。那如果你打開app的時候,手機豎屏,app首先加載出來的佈局是豎屏,當你再旋轉到橫屏的話,還是顯示豎屏。這主要是因爲你設置了那個configChanges,設置那個的意思就是當這些configuration發生的時候並不銷燬activity,而是沿用原來的。
    所以這時候oncreate和ondestroy這些聲明週期都不會觸發了,但是會觸發onConfigurationChanged方法。
    如果你需要在橫豎屏旋轉時,處理一些事情的話,可以在這個函數中處理,例如彈個toast什麼的,看你自己的需求。
  2. 如果你的activity有兩種佈局,分爲橫豎屏,那麼你的layout就有兩個了。
    橫屏佈局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="landscape" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

豎屏:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="portrait" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

主要就是改了linearlayout的方向。
當你在運行的時候,你會發現在豎屏時在輸入框輸入內容,旋轉至橫屏的時候,輸入框的內容沒了,這是爲什麼呢?雖然說光看佈局文件代碼,幾乎都是一樣的,但是爲什麼會這樣呢?因爲你使用了兩個佈局文件,兩個輸入框看似一樣,但在android這裏理解卻不一定是一樣,雖然都是同樣的輸入框,但是意義可能是不一樣的,可能在豎屏這個是輸入名字,在橫屏是輸入性別的。那如何做到輸入框內容保留呢?那就是給這兩個輸入框都加上id,並且兩個輸入框的id需要一樣,那麼android就會理解爲這兩個是一樣輸入框。

現在來講講當activity上顯示多個fragment當遇到屏幕旋轉怎麼辦?
比如你的屏幕上有4個fragment,分別爲abcd,按照順序顯示a->b->c->d,那麼當現在顯示c的時候,屏幕旋轉了,按理來講應該是顯示c,但是卻顯示了a,這是因爲你的activity未設置configChanges,導致屏幕旋轉重新創建activity,那麼按你代碼顯示的話,當然是顯示第一個了。那如何做到顯示c呢,你可以給你的activity設置configChanges,這樣就可以了。但是如果你的activity屏幕旋轉時,界面的確需要變化,需要顯示橫屏佈局呢?那設置configChanges當然不行了。那你可以旋轉前先記錄當前顯示哪個fragment,當重新創建完畢後,可以再顯式調用去顯示那個fragment。

我項目的需求是,activity沒有橫豎屏佈局,activity上面顯示的fragment們只有一個fragment是有橫豎屏的,記那個有橫豎屏的fragment爲a。而其他的fragment旋轉時不需要變,所以我的做法是給該activity設置configChanges,這樣可以保證Activity不會重新創建,其他fragment旋轉的時候也不會出錯,那a怎麼辦呢?如果只是單純設置configChanges的話,剛剛說了會顯示第一個fragment,可能不是a。
那我的做法是監聽activity的onConfigurationChanged這個函數,在這個裏面去判斷當前顯示的fragment是不是a,如果是a則先dismiss掉,然後在重新顯示這個fragment,因爲再顯示的時候,頁面已經爲橫屏,該fragment是會自己選擇正確的佈局文件的。那麼就完成了我的需求,看代碼:

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        List<Fragment> frags = getSupportFragmentManager().getFragments();
        Fragment frag;
        for (int i = 0; frags != null && frags.size() > i; i++) {
            frag = frags.get(i);
            if (frag!=null && frag instanceof AFragment) {
                ((AFragment) frag).dismissAllowingStateLoss();
                AFragment temp = new Afragment();
                temp.show(getSupportFragmentManager(),"afragment");
            }
        }
    }

完美解決

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章