1. 程式人生 > >Android 橫豎屏切換載入不同的佈局

Android 橫豎屏切換載入不同的佈局

橫屏豎屏在配置檔案中的設定,之前已經說過。那麼現在主要是說,切換之後由於螢幕寬高尺寸的改變,因此需要重新設定一個佈局檔案以適應現在的新的尺寸。

預設狀態下,Activity每次橫豎屏切換(包括用setRequestedOrientation呼叫)都會重新呼叫一輪onPause-> onStop-> onDestory-> onCreate->onStart->onResume操作,從而銷燬原來的Activity物件,建立新的Activity物件,這是因為通常情況下軟體在橫豎屏之間切換,介面的高寬會發生轉換,從而可能會要求不同的佈局。具體的佈局切換可以通過如下兩種方法來實現:

1.直接新建兩個佈局檔案,剩下的就什麼也不用管了:右鍵單擊‘res’資料夾  -> 'new'  ->  'Android resource directory'; 將 Directory name 填寫 layout-land,Resource type 選擇layout,這是建立了一個橫屏的佈局檔案,同樣的方式再建立一個layout-port資原始檔夾,裡面放一個豎屏的佈局檔案,名字要起一樣的,這個很重要,然後再java檔案中設定setvontentview就行  了。這樣螢幕切換的時候他們會被自動載入

 

2.假如佈局資源是不一樣又不按照如上設定,則需要通過java程式碼來判斷當前是橫屏還是豎屏然後來載入相應的xml佈局檔案(比如mainP為豎屏mainL為橫屏)。因為當螢幕變為橫屏的時候,系統會重新呼叫當前Activity的onCreate方法,你可以把以下方法放在你的onCreate中來檢查當前的方向,然後可以讓你的setContentView來載入不同的layout xml。

首先在layout下,建立兩個佈局檔案,一個是橫屏的一個是豎屏的,然後再java檔案中佈置這兩個檔案就行了。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        int orientation = getResources().getConfiguration().orientation;
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            setContentView(R.layout.land);
        } else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            setContentView(R.layout.port);
        }
        //接下來,就可以做一些初始化等操作了

    }
上面這兩種方式實現對於橫豎屏的切換載入不同的佈局檔案,都會讓activity重新載入一次,那麼必然就會導致資料的丟失或者是資料的重新獲取,造成了過多的額外的功耗,那麼我們可以在翻轉之前儲存一下現在已經獲取到的資料,那麼在翻轉之後就可以直接使用,而不需要重新獲取或者重新載入,具體在下面看
重寫Activity.onRetainNonConfigurationInstance(),使用者橫豎屏切換前儲存資料

@Override 

public Object onRetainNonConfigurationInstance() { 

    final MyDataObject data = collectMyLoadedData(); 

    return data; 

}

在onCreate()函式中呼叫getLastNonConfigurationInstance(),獲取onRetainNonConfigurationInstance()儲存的資料

@Override 

public void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 

    setContentView(R.layout.main); 

 

    final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance(); 

    if (data == null) { 

        data = loadMyData(); 

    } 

    ... 

}

到這個地方,可能有人還會問,我就是同一個activity為什麼切換個橫豎屏一定要重新載入,我不想重新載入有沒有辦法呢,有的,需要攔截,具體如下:

首先需要配置檔案中做點屬性的配置

Andorid 3.2以前的SDK可以使用如下配置

android:configChanges="orientation|keyboardHidden"

而Adnroid 3.2以後的SDK必須新增一個screenSize屬性,具體如下

android:configChanges="keyboardHidden|orientation|screenSize"

或者

android:configChanges="orientation|screenSize"


然後重寫activity中onConfigurationChanged 方法,這裡也分為三種情況:

//1.佈局分別在layout-land和layout-port目錄中的同名main.xml時,就是上面說的第一種情況

@Override

public void onConfigurationChanged (Configuration newConfig){

    super.onConfigurationChanged(newConfig);

    setContentView(R.layout.main);

    //注意,這裡刪除了init(),否則又初始化了,狀態就丟失

    findViews();

    setListensers();

}

//佈局為不按照layout-land和layout-port目錄,而自定義名字時

@Override

public void onConfigurationChanged (Configuration newConfig){

    super.onConfigurationChanged(newConfig);

    int mCurrentOrientation = getResources().getConfiguration().orientation;

    if ( mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT ) {

        // If current screen is portrait

        setContentView(R.layout.mainP);

        //注意,這裡刪除了init(),否則又初始化了,狀態就丟失

        findViews();

        setListensers();

    } else if ( mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE ) {

        //If current screen is landscape

        setContentView(R.layout.mainL);

        //注意,這裡刪除了init(),否則又初始化了,狀態就丟失

        findViews();

        setListensers();

    }

}

當然有時候連佈局都不用更改的話,就可以直接對原有控制元件進行呼叫操作了,比如:

public class MainActivity extends Activity {

    private TextView textView;

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        Log.i("--Main--", "onCreate");

        textView=(TextView)findViewById(R.id.tv_id);

    }

       

    @Override

    public void onConfigurationChanged(Configuration newConfig) {

        super.onConfigurationChanged(newConfig);

        Log.i("--Main--", "onConfigurationChanged");

        if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){

            textView.setText("當前螢幕為橫屏");

        }else{

            textView.setText("當前螢幕為豎屏");

        }

    }   

}