Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android橫豎屏切換小結

Android橫豎屏切換小結

編輯:關於Android編程

只需要點擊下“屏幕旋轉”按鈕就可以關閉橫豎屏切換了。   一、禁止APP內橫豎屏切換   上述設置更改的是整個手機的橫豎屏切換,當手機沒有關閉橫豎屏切換功能時,系統一旦觸發橫豎屏切換,缺省狀態下,當前活動的App的界面就會進行橫豎屏切換,由於橫豎屏的界面尺寸等參數不同,很多軟件在設計和開發中為了避免橫豎屏切換時引發不必要的麻煩,通常需要讓App禁止掉橫豎屏的切換,這就需要通過在AndroidManifest.xml中設置activity中的android:screenOrientation屬性值來實現。   該android:screenOrientation屬性,他有以下幾個參數:   "unspecified":默認值 由系統來判斷顯示方向.判定的策略是和設備相關的,所以不同的設備會有不同的顯示方向.   "landscape":橫屏顯示(寬比高要長)   "portrait":豎屏顯示(高比寬要長)   "user":用戶當前首選的方向   "behind":和該Activity下面的那個Activity的方向一致(在Activity堆棧中的)   "sensor":有物理的感應器來決定。如果用戶旋轉設備這屏幕會橫豎屏切換。   "nosensor":忽略物理感應器,這樣就不會隨著用戶旋轉設備而更改了("unspecified"設置除外)。   比如下列設置   android:screenOrientation="portrait"   則無論手機如何變動,擁有這個屬性的activity都將是豎屏顯示。   android:screenOrientation="landscape",為橫屏顯示。   上述修改也可以在Java代碼中通過類似如下代碼來設置   setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)   二、APP的橫豎屏切換可以手動觸發嗎   由上面描述可知,當android:screenOrientation為默認值"unspecified"或"sensor"等時,就會有系統根據設備的旋轉情況來觸發橫豎屏的切換,那麼有沒有方法我們手動在程序中觸發橫豎屏的變換呢,顯然上面為我們提供的setRequestedOrientation就是系統提供的一個入口,下面我們給出一個按鍵的方式來觸發的案列:   public class MainActivity extends Activity implements OnClickListener {        private Button mBtnLandscape;        private Button mBtnPortrait;               @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            mBtnLandscape = (Button) findViewById(R.id.but_landscape);            mBtnPortrait = (Button) findViewById(R.id.but_portrait);            mBtnLandscape.setOnClickListener(this);            mBtnPortrait.setOnClickListener(this);        }            @Override        public void onClick(View v) {                    // TODO Auto-generated method stub                    if(v == mBtnLandscape){                                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);                    }else{                                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);                    }        }               @Override        public void onConfigurationChanged(Configuration newConfig) {            super.onConfigurationChanged(newConfig);            String message=newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE ? "屏幕設置為:橫屏" : "屏幕設置為:豎屏";            Toast.makeText(this, message, Toast.LENGTH_LONG).show();        }   }   需要注意的是,手動調用時,無視AndroidManifest中關於screenOrientation的設置;另外上述代碼中的onConfigurationChanged要被調用到也是需要條件的,在這裡,只給代碼,不做討論,後面再給出一個相關的補充說明。   三、重啟Activity的橫豎屏切換   在上面的案列中,缺省狀態下,Activity每次橫豎屏切換(包括用setRequestedOrientation調用)都會重新調用一輪onPause-> onStop-> onDestory-> onCreate->onStart->onResume操作,從而銷毀原來的Activity對象,創建新的Activity對象,這是因為通常情況下軟件在橫豎屏之間切換,界面的高寬會發生轉換,從而可能會要求不同的布局。具體的布局切換可以通過如下兩種方法來實現:   1)在res目錄下建立layout-land和layout-port目錄,相應的layout文件名不變,比如main.xml。layout-land是橫屏的layout,layout-port是豎屏的layout,其他的不用管,橫豎屏切換時程序自己會調用Activity的onCreate方法,從而根據當前橫豎屏情況自動加載響應的布局。   2)假如布局資源是不一樣又不按照如上設置,則需要通過java代碼來判斷當前是橫屏還是豎屏然後來加載相應的xml布局文件(比如mainP為豎屏mainL為橫屏)。因為當屏幕變為橫屏的時候,系統會重新呼叫當前Activity的onCreate方法,你可以把以下方法放在你的onCreate中來檢查當前的方向,然後可以讓你的setContentView來載入不同的layout xml。   @Override   protected void onCreate(Bundle icicle) {    super.onCreate(icicle);    int mCurrentOrientation = getResources().getConfiguration().orientation;    if ( mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT ) {        // If current screen is portrait        Log.i("info", "portrait"); // 豎屏        setContentView(R.layout.mainP);    } else if ( mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE ) {        //If current screen is landscape        Log.i("info", "landscape"); // 橫屏        setContentView(R.layout.mainL);    }    init();//初始化,賦值等操作    findViews();//獲得控件    setListensers();//設置控件的各種監聽方法   }   上面只是對布局切換做了描述,實際上由於重啟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的橫豎屏切換   雖然重啟Activity為我們提供了保存數據和讀取數據的方式,但是如此一來程序會顯得有些繁瑣,所以有時候程序員往往就不想讓Activity重啟,Android也為我們提供了解決方案,就是通過onConfigurationChanged攔截橫豎屏變換,從而進行必要的重新布局和切換操作。操作步驟如下:   首先,manifest中為相應的Activity設置android:configChanges屬性,從而讓Activity不延續上述的重建流程,具體如下:   Andorid 3.2以前的SDK可以使用如下配置   android:configChanges="orientation|keyboardHidden"   而Adnroid 3.2以後的SDK必須添加一個screenSize屬性,具體如下   android:configChanges="keyboardHidden|orientation|screenSize"   或者   android:configChanges="orientation|screenSize"   關於configChanges的詳細描述,後面有個簡單補充章節,這裡不做過多展開。   其次,在Activity或View的onConfigurationChanged(Configuration newConfig)函數中獲取當前橫豎屏參數。至於其調用順序跟touch事件的傳遞順序相似,不過他沒有消費事件的概念,會順次調用到每一個onConfigurationChanged函數。下面是重寫Activity的例子:   //布局分別在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("當前屏幕為豎屏");           }       }      }   需要注意的是,onConfigurationChanged函數中只能獲得橫豎屏切換後的參數,在該函數中獲取不到新的Layout和控件的尺寸位置信息,如果要處理尺寸和位置信息,必須通過消息異步或者延時調用,下面是一個App在橫豎屏切換時需要重新設置popupWindow位置的代碼:   @Override   protected void onConfigurationChanged(Configuration newConfig) {       super.onConfigurationChanged(newConfig);       //View中不用創建Handler,可直接調用post操作       //new Handler().postDelayed(new Runnable() {       //    @Override       //    public void run() {       //        updatePopup();           //    }       //}, 500);           postDelayed(new Runnable() {           @Override           public void run() {               updatePopup();      //           }       }, 500);//如果不在post中,而是直接調用,那麼彈出位置就會有問題   }   雖然上面沒有看到對布局的顯式調用進行重新布局,照理控件的對象沒有被銷毀,但是控件在橫豎屏切換時應該是需要進行重新layout和measure,然後再進行重繪的,否則不會引發彈出框位置的變化,至於如何調用重新layout、measure和Draw操作,在這裡就不多展開了。   五、對於AndroidManifest.xml設置的補充   經過上面代碼演示,我們可以看到具體實現涉及到了Manifest工程配置裡面具體Activity的screenOrientation和configChanges兩個參數,這兩個參數screenOrientation的優先級是高於configChanges,即假如screenOrientation設置為固定橫豎屏時,那麼configChanges參數無論怎麼設都沒有辦法引發橫豎屏切換,除非在代碼中手動調用setRequestedOrientation函數進行修改。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved