<kbd id="9plqc"><label id="9plqc"></label></kbd>

        <th id="9plqc"></th>
        1. <center id="9plqc"><video id="9plqc"></video></center>
          <sub id="9plqc"><form id="9plqc"><pre id="9plqc"></pre></form></sub>
          <nav id="9plqc"><form id="9plqc"><legend id="9plqc"></legend></form></nav>
          Android橫豎屏切換小結(jié) 您所在的位置:網(wǎng)站首頁 八字深度解析pdf Android橫豎屏切換小結(jié)

          Android橫豎屏切換小結(jié)

          2024-12-07 02:05| 來源: 網(wǎng)絡整理| 查看: 265

          Android橫豎屏切換小結(jié)

          (老樣子,圖片啥的詳細文檔,可以下載后觀看?https://files.cnblogs.com/franksunny/635350788930000000.pdf)

          Android手機或平板都會存在橫豎屏切換的功能,通常是由物理重力感應觸發(fā)的,但是有時候也不盡然,通常在設置里面我們可以對手機的橫豎屏切換進行關閉,作界面如下

          ?

          只需要點擊下“屏幕旋轉(zhuǎn)”按鈕就可以關閉橫豎屏切換了。

          一、禁止APP內(nèi)橫豎屏切換

          上述設置更改的是整個手機的橫豎屏切換,當手機沒有關閉橫豎屏切換功能時,系統(tǒng)一旦觸發(fā)橫豎屏切換,缺省狀態(tài)下,當前活動的App的界面就會進行橫豎屏切換,由于橫豎屏的界面尺寸等參數(shù)不同,很多軟件在設計和開發(fā)中為了避免橫豎屏切換時引發(fā)不必要的麻煩,通常需要讓App禁止掉橫豎屏的切換,這就需要通過在AndroidManifest.xml中設置activity中的android:screenOrientation屬性值來實現(xiàn)。

          該android:screenOrientation屬性,他有以下幾個參數(shù):

          "unspecified":默認值 由系統(tǒng)來判斷顯示方向.判定的策略是和設備相關的,所以不同的設備會有不同的顯示方向.

          "landscape":橫屏顯示(寬比高要長)

          "portrait":豎屏顯示(高比寬要長)

          "user":用戶當前首選的方向

          "behind":和該Activity下面的那個Activity的方向一致(在Activity堆棧中的)

          "sensor":有物理的感應器來決定。如果用戶旋轉(zhuǎn)設備這屏幕會橫豎屏切換。

          "nosensor":忽略物理感應器,這樣就不會隨著用戶旋轉(zhuǎn)設備而更改了("unspecified"設置除外)。

          比如下列設置

          android:screenOrientation="portrait"

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

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

          上述修改也可以在Java代碼中通過類似如下代碼來設置

          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

          二、APP的橫豎屏切換可以手動觸發(fā)嗎

          由上面描述可知,當android:screenOrientation為默認值"unspecified"或"sensor"等時,就會有系統(tǒng)根據(jù)設備的旋轉(zhuǎn)情況來觸發(fā)橫豎屏的切換,那么有沒有方法我們手動在程序中觸發(fā)橫豎屏的變換呢,顯然上面為我們提供的setRequestedOrientation就是系統(tǒng)提供的一個入口,下面我們給出一個按鍵的方式來觸發(fā)的案列:

          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();

          ???? }

          }

          需要注意的是,手動調(diào)用時,無視AndroidManifest中關于screenOrientation的設置;另外上述代碼中的onConfigurationChanged要被調(diào)用到也是需要條件的,在這里,只給代碼,不做討論,后面再給出一個相關的補充說明。

          三、重啟Activity的橫豎屏切換

          在上面的案列中,缺省狀態(tài)下,Activity每次橫豎屏切換(包括用setRequestedOrientation調(diào)用)都會重新調(diào)用一輪onPause-> onStop-> onDestory-> onCreate->onStart->onResume作,從而銷毀原來的Activity對象,創(chuàng)建新的Activity對象,這是因為通常情況下軟件在橫豎屏之間切換,界面的高寬會發(fā)生轉(zhuǎn)換,從而可能會要求不同的布局。具體的布局切換可以通過如下兩種方法來實現(xiàn):

          1)在res目錄下建立layout-land和layout-port目錄,相應的layout文件名不變,比如main.xml。layout-land是橫屏的layout,layout-port是豎屏的layout,其他的不用管,橫豎屏切換時程序自己會調(diào)用Activity的onCreate方法,從而根據(jù)當前橫豎屏情況自動加載響應的布局。

          2)假如布局資源是不一樣又不按照如上設置,則需要通過java代碼來判斷當前是橫屏還是豎屏然后來加載相應的xml布局文件(比如mainP為豎屏mainL為橫屏)。因為當屏幕變?yōu)闄M屏的時候,系統(tǒng)會重新呼叫當前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();//設置控件的各種監(jiān)聽方法

          }

          上面只是對布局切換做了描述,實際上由于重啟Activity在未加處理的情況下必然導致數(shù)據(jù)的丟失和重新獲取,這樣用戶體驗會非常差。為此就要在切換前對數(shù)據(jù)進行保存,切換重啟后對數(shù)據(jù)進行恢復,具體作的步驟如下:

          重寫Activity.onRetainNonConfigurationInstance(),用戶橫豎屏切換前保存數(shù)據(jù)

          @Override?

          public Object onRetainNonConfigurationInstance() {?

          ??? final MyDataObject data = collectMyLoadedData();?

          ??? return data;?

          }

          在onCreate()函數(shù)中調(diào)用getLastNonConfigurationInstance(),獲取onRetainNonConfigurationInstance()保存的數(shù)據(jù)

          @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為我們提供了保存數(shù)據(jù)和讀取數(shù)據(jù)的方式,但是如此一來程序會顯得有些繁瑣,所以有時候程序員往往就不想讓Activity重啟,Android也為我們提供了解決方案,就是通過onConfigurationChanged攔截橫豎屏變換,從而進行必要的重新布局和切換作。作步驟如下:

          首先,manifest中為相應的Activity設置android:configChanges屬性,從而讓Activity不延續(xù)上述的重建流程,具體如下:

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

          android:configChanges="orientation|keyboardHidden"

          而Adnroid 3.2以后的SDK必須添加一個screenSize屬性,具體如下

          android:configChanges="keyboardHidden|orientation|screenSize"

          或者

          android:configChanges="orientation|screenSize"

          關于configChanges的詳細描述,后面有個簡單補充章節(jié),這里不做過多展開。

          其次,在Activity或View的onConfigurationChanged(Configuration newConfig)函數(shù)中獲取當前橫豎屏參數(shù)。至于其調(diào)用順序跟touch事件的傳遞順序相似,不過他沒有消費事件的概念,會順次調(diào)用到每一個onConfigurationChanged函數(shù)。下面是重寫Activity的例子:

          //布局分別在layout-land和layout-port目錄中的同名main.xml時

          @Override

          public void onConfigurationChanged (Configuration newConfig){

          ??? super.onConfigurationChanged(newConfig);

          ??? setContentView(R.layout.main);

          ??? //注意,這里刪除了init(),否則又初始化了,狀態(tài)就丟失

          ??? 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(),否則又初始化了,狀態(tài)就丟失

          ??????? findViews();

          ??????? setListensers();

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

          ??????? //If current screen is landscape

          ??????? setContentView(R.layout.mainL);

          ??????? //注意,這里刪除了init(),否則又初始化了,狀態(tài)就丟失

          ??????? findViews();

          ??????? setListensers();

          ??? }

          }

          當然有時候連布局都不用更改的話,就可以直接對原有控件進行調(diào)用作了,比如:

          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函數(shù)中只能獲得橫豎屏切換后的參數(shù),在該函數(shù)中獲取不到新的Layout和控件的尺寸位置信息,如果要處理尺寸和位置信息,必須通過消息異步或者延時調(diào)用,下面是一個App在橫豎屏切換時需要重新設置popupWindow位置的代碼:

          @Override

          protected void onConfigurationChanged(Configuration newConfig) {

          ??? super.onConfigurationChanged(newConfig);

          ??? //View中不用創(chuàng)建Handler,可直接調(diào)用post作

          ??? //new Handler().postDelayed(new Runnable() {

          ??? //??? @Override

          ??? //??? public void run() {

          ??? //??????? updatePopup();????

          ??? //??? }

          ??? //}, 500);

          ?

          ??? postDelayed(new Runnable() {

          ??????? @Override

          ??????? public void run() {

          ??????????? updatePopup();????? //

          ??????? }

          ??? }, 500);//如果不在post中,而是直接調(diào)用,那么彈出位置就會有問題

          }

          雖然上面沒有看到對布局的顯式調(diào)用進行重新布局,照理控件的對象沒有被銷毀,但是控件在橫豎屏切換時應該是需要進行重新layout和measure,然后再進行重繪的,否則不會引發(fā)彈出框位置的變化,至于如何調(diào)用重新layout、measure和Draw作,在這里就不多展開了。

          五、對于AndroidManifest.xml設置的補充

          經(jīng)過上面代碼演示,我們可以看到具體實現(xiàn)涉及到了Manifest工程配置里面具體Activity的screenOrientation和configChanges兩個參數(shù),這兩個參數(shù)screenOrientation的優(yōu)先級是高于configChanges,即假如screenOrientation設置為固定橫豎屏時,那么configChanges參數(shù)無論怎么設都沒有辦法引發(fā)橫豎屏切換,除非在代碼中手動調(diào)用setRequestedOrientation函數(shù)進行修改。

          screenOrientation屬性在前面已經(jīng)講過了,而關于configChanges屬性設置有如下選項:

          描述

          mcc

          IMSI移動臺的國家代碼(MCC)發(fā)生變化——一個SIM被探測到并且更新MCC

          mnc

          IMSI移動臺的網(wǎng)絡代碼(MNC)發(fā)生變化——一個SIM被探測到并且更新MNC

          locale

          區(qū)域發(fā)生變化——用戶選擇了一個文本需要顯示的新語言

          touchscreen

          觸摸屏發(fā)生變化。(這個通常不會發(fā)生。)

          keyboard

          鍵盤類型發(fā)生變化——例如:用戶插入了外接鍵盤。

          keyboardHidden

          鍵盤的可訪問性發(fā)生變化——例如:用戶發(fā)現(xiàn)了硬件鍵盤。

          navigation

          導航類型(軌跡球或dpad)發(fā)生變化。(通常不會發(fā)生。)

          screenLayout

          屏幕布局發(fā)生變化——這個會導致顯示不同的Activity。

          fontScale

          字體縮放因子發(fā)生變化——用戶選擇了新的字體大小。

          uiMode

          當UI模式發(fā)生改變的時候——當用戶放置設備到桌子或/汽車或夜間模式改變的時候可以引起UI模式變化。閱讀UiModeManager。在API級別8時引入。

          orientation

          屏幕方向發(fā)生變化——用戶旋轉(zhuǎn)了屏幕。注意:如果應用程序的目標API級別是13或更高(通過屬性minSdkVersion和屬性targetSdkVersion聲明),你也需要聲明配置項screenSize,因為這將在設備選擇肖像和屏幕方向時發(fā)生改變。

          screenSize

          當前可用屏幕大小發(fā)生變化。這代表一個當前可用大小的變化,和當前的比率相關,因此當用戶選擇不同的畫面和圖像,會發(fā)生變化。然而,如果你的程序目標API級別是12或更低,你的Activity總是會自己處理這個配置變化(這個變化不會引起Activity的重啟,甚至在Android 3.2或更新的設備上)。在API級別13里加入的。

          smallestScreenSize

          物理屏幕大小的變化。不管方向的變化,僅僅在實際物理屏幕打包變化的時候,如:外接顯示器。這個配置項的變化引起在smallestWidth configuration里的變化。然而,如果你的程序目標API級別是12或更低,你的Activity將自己處理這個變化(這個變化不會引起Activity的重啟,甚至在Android 3.2或更新的設備上)在API級別13里加入的。

          layoutDirection

          布局方向變化。例如書寫方式從左向右(LTR)轉(zhuǎn)換為從右向左(RTL)

          ?

          從上述這個表我們可以看到除了橫豎屏,包括語言、網(wǎng)絡、鍵盤和外設等變化都可以被onConfigurationChanged函數(shù)監(jiān)控到,具體的內(nèi)容和釋義還是查看官方英文文檔吧,詳見如下鏈接

          http://developer.android.com/guide/topics/manifest/activity-element.html

          中文翻譯可以查閱 http://wiki.eoe.cn/page/Activity.html

          結(jié)合網(wǎng)上的整理,小結(jié)跟這幾配置相關的情景:

          1、不設置Activity的android:configChanges時,切屏會重新調(diào)用各個生命周期,切橫屏時會執(zhí)行一次,切豎屏時會執(zhí)行兩次(我在三星4.0設備上發(fā)現(xiàn)切橫屏和豎屏都是執(zhí)行一次,而并非這里說的有執(zhí)行兩次的情況,不知道是否以前版本手機會這樣?);

          2、設置Activity的android:configChanges="orientation"時,切屏還是會重新調(diào)用各個生命周期,切橫、豎屏時只會執(zhí)行一次;

          3、設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調(diào)用各個生命周期,只會執(zhí)行onConfigurationChanged方法。

          注:上述描述是在Android3.2以前,如果缺少了keyboardHidden選項,不能防止Activity的銷毀重啟,也就不能執(zhí)行onConfigurationChanged方法了。在3.2之后,必須加上screenSize屬性才可以屏蔽調(diào)用Activity的生命周期(我在一些設備上親測可以不需要keyboardHidden,只要screenSize就可以了,但是保險起見還是繼續(xù)保留keyboardHidden吧)。

          六、對于setRequestedOrientation函數(shù)的補充說明

          在上述(二)對于手動觸發(fā)橫豎屏切換的時候,我們用到了setRequestedOrientation,那時只是簡單做了下演示,后來發(fā)現(xiàn)還是需要做下補充說明的:

          首先在非重啟Activity模式下

          手動調(diào)用setRequestedOrientation之后,假如會引發(fā)橫豎屏切換(即請求的橫豎屏要求與當前的橫豎屏情況不一致,就會引發(fā)切換),那么會立即調(diào)用onConfigurationChanged函數(shù);假如不會引發(fā)橫豎屏切換(請求前后一致),那么也就不會調(diào)用到onConfigurationChanged函數(shù)。

          這個手動調(diào)用setRequestedOrientation的地方也可以在Activity中的任何地方,即也可以在onConfigurationChanged中調(diào)用,但是一旦指定為橫屏或豎屏完成這個變換之后,后面不論屏幕如何進行怎么翻轉(zhuǎn)變化,都不會再觸發(fā)橫豎屏切換了,也即等同于在manifest中設置了android:screenOrientation屬性為橫屏或豎屏。如果要恢復為響應橫豎屏隨物理傳感器設備變換,那么就需要手動調(diào)用類似如下代碼進行恢復:

          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

          其次在重啟Activity模式下

          手動調(diào)用setRequestedOrientation發(fā)出橫豎屏設定請求之后,假如需要進行橫豎屏切換(即請求前后橫豎屏狀態(tài)不一致),則會對Activity進行銷毀并重啟;假如不需要需要進行橫豎屏切換,則Activity維持現(xiàn)狀不變;

          手動調(diào)用setRequestedOrientation一次,完成變換之后,也跟上面非重啟一樣,相當于在manifest中設置了android:screenOrientation屬性為橫屏或豎屏。要想恢復也需要重新調(diào)用類似上面非重啟的調(diào)用。

          在這樣一個原理下,就有了對如下一種需求的解決方案:

          讓App啟動的時候是橫屏的話就橫屏表示,縱屏的話就縱屏表示,然后手機切換橫豎屏就不能用了該怎么解決呢?

          網(wǎng)上給出了一個例子代碼,這里就不做摘抄了,有興趣可以試一下,然后對比一下人家的實現(xiàn)方式,具體見如下鏈接

          http://blog.csdn.net/yimo29/article/details/6030445

          ?

          另外再給出幾個我做整理時參考的帖子,覺得對我?guī)椭艽螅謩e如下

          Android橫屏豎屏切換的問題(一個總結(jié)帖,還是不錯的)

          http://blog.sina.com.cn/s/blog_77c632410101790w.html

          解決Android手機屏幕橫豎屏切換(一個真實測試過的小結(jié))

          http://www.cnblogs.com/zhangkai281/archive/2011/07/06/2099277.html

          Android 處理橫豎屏切換事件

          http://ipjmc.iteye.com/blog/1265991

          ?



          【本文地址】

          公司簡介

          聯(lián)系我們

          今日新聞

          推薦新聞

          專題文章
            CopyRight 2018-2019 實驗室設備網(wǎng) 版權所有
            黄色免费网站在线看,韩国精品在线观看,韩国美女一区二区,99国产热 罗源县| 应城市| 巴马| 绥棱县| 精河县| 新兴县| 达孜县| 山西省| 雷山县| 商城县| 宣武区| 桦南县| 大安市| 连城县| 桃源县| 聂拉木县| 平邑县| 杂多县| 囊谦县| 仁布县| 鄂托克前旗| 云和县| 南通市| 和林格尔县| 湟中县| 资源县| 凤阳县| 沙湾县| 平湖市| 双鸭山市| 临漳县| 吴川市| 呼和浩特市| 邵东县| 临漳县| 安达市| 六安市| 防城港市| 沭阳县| 小金县| 乳源| http://444 http://444 http://444 http://444 http://444 http://444