今天的文章要來聊一下關於Android手機中橫/豎屏再切換時會遇到的一些大小事
老實說,這個項目就像是一隻等級999的可愛怪物一樣
看著很可愛,然後打你一下一發入魂(゜ロ゜)
...好啦我知道這個比喻超級爛的( ̄ー ̄;
其實我想表達的是~其實在手機開發者的世界中,螢幕旋轉算是個坑
因為明明只是個小動作而已,卻動不動就會害你螢幕閃退ORZ
所以今天的主題就如大標題一樣
"關於Android手機螢幕旋轉的一些大小事"
然後副標題
"那些年手機旋轉時踩到的坑"
今天文章簡單,所以沒有Github
開始:D
科普一下原理
在講關於螢幕旋轉的話題前
我們要先來講一下Android的生命週期
什麼是生命週期?其實就跟人生要經過生老病死一樣
生命週期的意義就是"一個App畫面從出現到消失的一個過程"
那麼在基礎的生命週期中,總共有以下幾個狀態
1. onCreate
2. onStart
3. onResume
4. onPause
5. onStop
6. onDestroy
總共六個狀態
如果對應到人生的話,可以這樣比喻
1. onCreate->出生
2. onStart->開始有記憶了
3. onResume->健康地長大中
4. onPause->感冒了(有可能會恢復,恢復的話回到onResume)
5. onStop->快死翹翹了
6. onDestroy->你已經屎了( ・ὢ・ )
那麼APP的話,當你的手機畫面旋轉時會走以下程序
onPause → onStop → onDestroy → onCreate → onSrart → onResume
對應人生的話那就是你異世界轉生了(???)
好啦講正經的,總之就是其實螢幕旋轉轉後系統會把你的畫面重置一遍
也就是說如果你不做任何的存檔機制的話,你在這一頁所變更過的內容都會回最原本的樣貌
如下範例
請注意中間那行字,我按下按鈕後中間的字串會有些改變
剛開始螢幕中間的字是Hello World!
後來按下按鈕後變成"被設定一串字"
再來螢幕翻轉後你會發現又變回了Hello world! 了
而這又是我們今天要解決的問題
因為其實在真正的專案中,很多時候其實橫屏跟豎屏的UI畫面是不一樣的
這部分稍後也會講到~那我們就繼續往下看吧(´∀`)
方法一 AndroidManifset.xml 加入configChanges
這個方法還挺簡單的
請打開AndroidManifest.xml
然後找出你不想要被旋轉畫面的Activity
加下
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jetec.rotatescreen"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity2" android:configChanges="orientation|screenSize"> </activity> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
而該檔案就是這個MainActivity2.java
這行的用意在於"被加入這行的Activity,畫面旋轉的時候並不會跑上述的生命週期,而是直接旋轉"
也因此,呈現出來的畫面就會變成這樣
Okay,看起來問題是有解決了(・ω・)b
不過我前面有說過在實際的開發中很常出現直向跟橫向畫面不一樣的事情發生
打個比方,像是這個畫面
我在畫面中又多放了一個TextView
那麼這時候我們要怎麼解決呢?(╥_╥)
方法二 儲存螢幕旋轉前的狀態
首先這是目前的狀況
可以看到,在畫面旋轉之後出現了另外一個TextView(-‿◦)
而這個TextView我希望在旋轉後取得控制權
那我們可以怎麼做呢?
首先複習一下螢幕旋轉會出現的事
onPause → onStop → onDestroy → onCreate → onSrart → onResume
換言之,我們的程式就必須在onDestroy前先儲存現在畫面的狀況
那麼這個東西Google其實已經幫你寫好了(・ωー)~☆
首先請在編輯器中按下control+O
並找到onSaceIntanceState
然後填入以下內容
@Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); String s = tvShow.getText().toString(); outState.putString("SAVE",s); }
如此一來就完成儲存了(┼д┼;)
再來就是取出
取出的部分他放在了一個你每次都會看見但從來不知道他在幹嘛的地方
就是onCreate的粉底白字部分
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... }
這個部分就是給螢幕旋轉用的XDDDDDD
我當時第一次知道了時候也是超級驚訝啊โ๏∀๏ใ
最後我給出完整的程式,各位自己試看看吧!
public class MainActivity extends AppCompatActivity { TextView tvShow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Configuration configuration = getResources().getConfiguration(); Button btSetText = findViewById(R.id.button); tvShow = findViewById(R.id.textView); if (savedInstanceState != null && configuration.orientation == Configuration.ORIENTATION_LANDSCAPE){ TextView tvSecondRow = findViewById(R.id.textView2); tvSecondRow.setText("Hi,我是橫向時才會出現的喔!"); tvShow.setText(savedInstanceState.getString("SAVE")); }else if (savedInstanceState != null && configuration.orientation == Configuration.ORIENTATION_PORTRAIT){ tvShow.setText(savedInstanceState.getString("SAVE")); } btSetText.setOnClickListener(v->{ tvShow.setText("被設定一串字"); }); } @Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); String saveWord = tvShow.getText().toString(); outState.putString("SAVE",saveWord); } }
其中,粉底白字就是我所述說寫入與取出的部分
再來藍底白字則是判斷螢幕目前的方向要做不同的事
最後是紫底白字的部分,這部分是儲存資料的索引,前後不能不一樣哦:D
那麼執行出來就會變成這樣了
(請注意,"Hi,我是橫向時才會出現的喔!"這一串字是在程式內寫的,並非一開始就寫死喔)
其他補充
最後我再補充幾個重要的
有時候你不想要讓螢幕轉向,想要鎖死
兩種做法
第一種 在AndroidManifest.xml加入指令
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jetec.rotatescreen"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity2" android:configChanges="orientation|screenSize"> </activity> <activity android:name=".MainActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <!-- android:screenOrientation="portrait" (強制豎屏)--> <!-- android:screenOrientation="landscape" (強制橫屏)--> </manifest>
第二種 在onCreate內加入指令
public class MainActivity extends AppCompatActivity { TextView tvShow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); }
再來要再補充如何加入自定義的橫向介面
請打開想要有橫向版本的介面
找到左上有個手機圖案旋轉的Icon
再來點選Create Landscape Veriation
就可以新增一個橫向畫面落囉
結語
最近我常常被說"感覺寫程式的工程師都很聰明"(;´д`)ゞ
其實我也是在聽到這句話後突然很想寫這篇文章
主要是因為我常覺得寫軟體並不是很聰明才寫,而是很細心才寫
像是今天的例子,如果我不講又誰知道我們每天螢幕旋轉看影片時背後程式的東西這麼複雜
而這些東西雖然看起來很複雜,但是為什麼Google那些頂尖工程師又非得這樣設計呢?
當我們覺得一件事情,一個工具,一個套件操作很複雜的時候
有時候可以想想看為何設計者要這樣做?為何產諞社這個樣子的?
我覺得這件事不論你是不是寫程式的的可以想想看噢(・ω・)b
那麼今天的文到這邊哦!謝謝各位:D
留言列表