1. 程式人生 > >Android橫屏豎屏切換的問題

Android橫屏豎屏切換的問題

一、禁止橫豎屏轉換

Android橫豎屏切換在手機開發中比較常見,很多軟體在開發過程中為了避免橫豎屏切換時引發不必要的麻煩,通常禁止掉橫豎屏的切換,

通過在AndroidManifest.xml中設定activity中的android:screenOrientation屬性值來實現。

比如下列設定

android:screenOrientation="portrait"

則無論手機如何變動,擁有這個屬性的activity都將是豎屏顯示。

android:screenOrientation="landscape",為橫屏顯示。

上述修改也可以在Java程式碼中通過類似如下程式碼來設定

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

另外,android中每次螢幕的切換動會重啟Activity,所以應該在Activity銷燬前儲存當前活動的狀態,在Activity再次Create的時候載入配置,那樣,進行中的遊戲就不會自動重啟了!

二、橫豎屏切換

如果要讓軟體在橫豎屏之間切換,由於橫豎屏的高寬會發生轉換,有可能會要求不同的佈局。可以通過以下兩種方法來切換佈局:

1)在res目錄下建立layout-landlayout-port目錄,相應的layout檔名不變,比如main.xml

layout-land是橫屏的layout,layout-port是豎屏的layout,其他的不用管,橫豎屏切換時程式為呼叫ActivityonCreate方法,從而載入相應的佈局。

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

if(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE)

{  

     Log.i("info", "landscape"); // 橫屏

}  else if(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT)

{  

    Log.i("info", "portrait"); // 豎屏

 }

三、通過onConfigurationChanged攔截橫豎屏變換

按照二的操作,Activity每次橫豎屏切換都會重新呼叫onPause-> onStop-> onDestory-> onCreate->onStart->onResume,為此涉及到內容和資料的儲存和讀取,否則轉屏之前的內容就會消失了。很多時候這樣的結果讓程式繁瑣,為此Android提供了在manifest中設定android:configChanges屬性,從而讓Activity不延續上述的重建流程。Android工程的Mainfest.xml配置Activityandroid:configChanges="keyboardHidden|orientation"橫豎屏切換之後就不會去執行OnCreat函數了,而是會去呼叫onConfigurationChanged()這樣就能控制橫豎屏的切換了。使用者可以在ActivityViewonConfigurationChanged(Configuration newConfig)函式中獲取當前橫豎屏引數。至於其呼叫順序跟touch時間的傳遞順序相似,不過他沒有消費事件的概念,會順次呼叫到每一個onConfigurationChanged函式。

需要重寫ActivityonConfigurationChanged方法。實現方式如下,不需要做太多的內容:
@Override
        public void onConfigurationChanged(Configuration newConfig) {
                super.onConfigurationChanged(newConfig);
                if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                        // land do nothing is ok
                } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                        // port do nothing is ok
                }
        }

需要注意的是,onConfigurationChanged函式中只能獲得橫豎屏切換後的引數,在該函式中獲取不到新的Layout和控制元件的尺寸位置資訊,如果要處理尺寸和位置資訊,必須通過訊息非同步或者延時呼叫。

四、徹底禁止翻轉

當然如果要徹底禁止翻轉,可以設定android:screenOrientation的屬性為nosensor,如此就可以忽略重力感應帶來的麻煩了。不過在模擬器上不管用,在真機上是正確的。

這裡提一個小知識,Android模擬器中,快捷鍵"Ctrl+F11/F12"可以實現轉屏

五,自適應轉換

如果想讓它啟動的時候是橫屏的話就橫屏表示,縱屏的話就縱屏表示,然後手機切換橫豎屏就不能用了該怎麼解決呢?

首先:在Mainfest.xml中追加

android:screenOrientation="sensor" android:configChanges="orientation|keyboardHidden"

這兩個屬性。

第二步:取得螢幕的長和寬,進行比較設定橫豎屏的變數。

1. Display display = getWindowManager().getDefaultDisplay();  

2. int width = display.getWidth();  

3. int height = display.getHeight();  

4. if (width > height) {  

5.     orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;  //橫屏

6. else {  

7.     orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;  //豎屏

8. }  

第三步:在onConfigurationChanged()函式中追加this.setRequestedOrientation(orientation)就行了

1. publicvoid onConfigurationChanged(Configuration newConfig) {  

2. super.onConfigurationChanged(newConfig);  

3. this.setRequestedOrientation(orientation);  

4. }  

但是這樣的話你切到別的畫面的時候再回到原畫面,它就仍然是橫的或者是縱的。怎麼讓它從別的螢幕回來後,又重新橫豎屏佈局呢?

只要在OnResume()中在設定下就行了。但是這個只支援橫豎屏只有一個layout的。橫豎屏分別對應layout的還不知道該怎麼解決。

1. protectedvoid onResume() {  

2.     orientation = ActivityInfo.SCREEN_ORIENTATION_USER;  

3. this.setRequestedOrientation(orientation);  

4.     Display display = getWindowManager().getDefaultDisplay();  

5. int width = display.getWidth();  

6. int height = display.getHeight();  

7. if (width > height) {  

8.         orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;  

9.     } else {  

10.         orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;  

11.     }  

12. super.onResume();  

13. }  

六、總結

總之,對於橫豎屏切換的問題,統計了下,大家的解決辦法是: 不理會。。 只豎屏顯示(android:screenOrientation="portrait")
 只橫屏顯示(android:screenOrientation="landscape")
簡單的防止過載:   AndroidManifest.xml中加入:android:configChanges="orientation|keyboardHidden"
 activity中過載onConfigurationChanged事件 
 @Override
 public void onConfigurationChanged(Configuration config) {
 super.onConfigurationChanged(config);
 }
橫豎屏分別佈局  橫豎屏分別佈局的方法是:  res下新建 
 layout-land
 橫屏 
 layout-port
 豎屏  然後把layout中的xml檔案分別考到以上目錄,修改佈局就可以了程式碼中不做任何更改。   AndroidManifest.xml檔案中的 Activity中加入 
 android:configChanges="orientation|keyboardHidden"
 然後在主Activity中的onConfigurationChanged加入 
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);

if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
setContentView(R.layout.main); //
佈局 
tv = (TextView) findViewById(R.id.EditText01); //
控制元件 
}

if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.main); //
佈局 
tv = (TextView) findViewById(R.id.EditText01); //
控制元件 
}
}

七、示例詳細步驟

//------ 第一步:獲得許可 需要在中新增相應許可

//------ 第二步:根據不同的目標,針對Activity進行設定

目標1遮蔽橫豎屏的切換

步驟:為Activity設定一個預設的螢幕方向 方法如下: AndroidManifest.xml中找到該Activity 新增程式碼: 

android:name=".ActivityName"
android:screenOrientation="landscape"
>
設定Activity的預設方向為橫向
此處的screenOrientation有如下選項: 
==================================================================
= unspecified
 預設值,由系統判斷狀態自動切換 
landscape
 橫屏 
= portrait
 豎屏 = user 使用者當前設定的orientation 
= behind
 下一個要顯示的Activityorientation 
= sensor
 使用感測器 感測器的方向 
= nosensor
 不使用感測器 基本等同於unspecified
==================================================================
目標2:防止Activity的銷燬

步驟:為Activity設定configChanges屬性 AndroidManifest.xml中找到該Activity 新增程式碼: 

android:name=".ActivityName"
android:configChanges="orientation|keyboardHidden"
>
此處的configChanges有如下選項: 
==================================================================
= orientation
 螢幕在縱向和橫向間旋轉 
= keyboardHidden
 鍵盤顯示或隱藏 = fontScale 使用者變更了首選的字型大小 
= locale
 使用者選擇了不同的語言設定 
= keyboard
 鍵盤型別變更,例如手機從12鍵盤切換到全鍵盤 
= touchscreen
navigation 鍵盤或導航方式變化,一般不會發生這樣的事件 
==================================================================
如果需要多個選項 "|"隔開 此處注意:如果是在實體機上測試橫豎屏切換 需要orientation選項 【重點】如果要使得程式可以在Android模擬器上測試 需要寫orientation|keyboardHidden
如果缺少了keyboardHidden選項 不能防止Activity的銷燬 並且在之後提到的onConfigurationChanged事件中 只能捕獲豎屏變橫屏的事件 不能捕獲橫屏變豎屏

目標3:捕獲橫豎屏切換的事件 步驟:在Activity中(ActivityName.java)重寫onConfigurationChanged事件 
@Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
switch (newConfig.orientation)
{
//
更改為LANDSCAPE
case (Configuration.ORIENTATION_LANDSCAPE):
//
如果轉換為橫向屏時,有要做的事,請寫在這裡 
break;
//
更改為PORTRAIT
case (Configuration.ORIENTATION_PORTRAIT):
//
如果轉換為豎向屏時,有要做的事,請寫在這裡 
break;
}
}

八、備註:

1、不設定Activityandroid:configChanges時,切屏會重新呼叫各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次 
2
、設定Activityandroid:configChanges="orientation"時,切屏還是會重新呼叫各個生命週期,切橫、豎屏時只會執行一次 
3
、設定Activityandroid:configChanges="orientation|keyboardHidden"時,切屏不會重新呼叫各個生命週期,只會執行onConfigurationChanged方法

轉自網路,自己整合整理。非利益驅使,寫於新浪只為便於自己查閱相關資料。感謝各位貢獻者!

##################3

Android系統不像iOS有shouldAutorotateToInterfaceOrientation:以及專案info.plist中的支援螢幕朝向屬性設定那麼直白的螢幕朝向支援,而且2.2以下和2.3以上還有對自動旋屏功能支援的差異:

在2.2一下,manifest中可以通過:screenOrientation=””屬性設定朝向,但這顯然沒有像iOS那樣指明是 right還是landscape left,而且測試發現實際效果也只是鎖定在了landscape的一個朝向,並不支援根據重力感應的兩方向自動旋轉。

在2.3及以上的target下,可以通過設定:screenOrientation=”sensorLandscape”實現landscape的兩方向自動旋轉,為了同時相容兩種情況,可以採用以下的方法:

public static final int ANDROID_BUILD_GINGERBREAD = 9;
public static final int SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 6;

@Override
public void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);
     if (Build.VERSION.SDK_INT >= ANDROID_BUILD_GINGERBREAD)
     {
         setRequestedOrientation(SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
     }
}