原文地址:http://www.jianshu.com/p/19393bb08e4f
在手機APP開發的時候,一般預設會適配豎屏,遊戲開發除外。但是在Android平板電腦開發中,螢幕旋轉的問題比較退出,可以這樣說,平板電腦的最初用意就是橫屏使用的,比較方便,使用者會經常旋轉我們的螢幕。
這裡主要針對平板開發中的一些問題做一些總結。
###1、防止螢幕旋轉之後,Activity的銷燬問題。
為了適配螢幕,Activity預設在螢幕旋轉之後會銷燬並且重建,但是這種情況會造成使用者輸入資料的丟失(需要開發者手動去儲存和恢復,會帶來一定的工作量),Activity畢竟是重量級的元件,它的銷燬和重建會使得效能的下降,因此我們需要防止Activity的銷燬和重建。
####做法
在清單檔案中為Activity新增一些配置,configChanges屬性新增orientation|screenSize:
<activity
android:name=".ui.activity.MainActivity"
android:configChanges="orientation|screenSize"
android:launchMode="singleTask"
android:windowSoftInputMode="stateAlwaysHidden">
複製程式碼
通過上述的配置可以防止Activity的銷燬和重建。
###2、View螢幕旋轉適配
除了製作橫屏和豎屏兩份佈局檔案的方法之外,如果我們的View是動態新增到Window的,螢幕旋轉之後,我們的介面以及View需要做一些變動以適應螢幕。
我們可以複寫Activity的onConfigurationChanged方法,並且在裡面修改一些東西。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//一些適配操作
}
複製程式碼
這裡舉個例子,如說我們的ListView右邊有一個字母索引控制元件,這個控制元件是直接new出來並且是直接覆蓋在ListView上面的。當螢幕旋轉之後,這個字母索引控制元件的位置需要重新整理(重新佈局以及繪製)。因為這個控制元件是在我們的ListView的右側,並且豎直方向居中。這時候我們就需要動態獲取螢幕上的ListView的寬高,然後才能計算出字母控制元件應該佈局的位置。
####但是這裡我們會遇到一些坑
直接通過View的getWidth方法或者先measure然後通過getMeasuredWidth方法獲取到的寬都是錯誤的,獲取到的是螢幕旋轉之前的值,如下面的程式碼所示。但是我需要的是ListView實時的寬高值,這時候我們只能手動去計算。例如我們要獲取ListView的高度,那麼我們可以先拿到Window的總高度,然後減去狀態列、Toolbar的高度來獲取(這裡只是一個例子,具體做法需要具體分析)。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//一些適配操作
WindowManager wm = getWindowManager();//Activity可以直接獲取WindowManager
// WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
final int windowWidth = wm.getDefaultDisplay().getWidth();
final int windowHeight = wm.getDefaultDisplay().getHeight();
//手動去計算ListView的寬高
final int mListViewWidth = windowWidth;
final int mListViewHeight = windowHeight - statusbarHeight - toolbarHeight;
//下面獲取ListView的寬高是有問題的
// mListView.measure(0, 0);
// mListView.getMeasuredWidth();
// mListView.getMeasuredHeight();
// mListView.getWidth();
// mListView.getHeight();
// 。。。其他適配操作
}
複製程式碼
###螢幕旋轉的不確定性問題
最近又遇到螢幕旋轉相關的新的問題,因此記錄下來。我們知道,在Activity、View、Fragment等旋轉的時候,如果你在清單檔案中配置不重新建立的話,就會呼叫onConfigurationChanged方法。
但是問題來了,這個問題有一些不確定性因素,比如說當你的頁面或者View被遮擋住(Stop)的時候就不會回撥onConfigurationChanged這個方法。這比較略坑,會帶來一些UI的偶發性問題。
解決辦法就是我們自定義一個廣播接受者專門用來接受onConfigurationChanged這個廣播,這樣子就可以確保,無論什麼情況下,系統ConfigurationChanged的時候你的程式碼都會被執行。
自定義的ConfigurationChangeReceiver如下,這裡提供一個靜態方法方便註冊。
public abstract class ConfigurationChangeReceiver extends BroadcastReceiver {
private static final String TAG = ConfigurationChangeReceiver.class.getSimpleName();
public static IntentFilter getIntentFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.CONFIGURATION_CHANGED");
return filter;
}
}
複製程式碼
接下類在Activity或者Fragment中的正確位置註冊(onAttachedToWindow、onDetachedFromWindow):
private void initConfigurationChangeReceiver() {
mConfigurationChangeReceiver = new ConfigurationChangeReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//你的螢幕適配程式碼
}
};
this.registerReceiver(mConfigurationChangeReceiver, ConfigurationChangeReceiver.getIntentFilter());
}
複製程式碼
記得反註冊,防止記憶體洩漏哦。
private void unRegisterConfigurationChangeReceiver() {
if (mConfigurationChangeReceiver != null) {
this.unregisterReceiver(mConfigurationChangeReceiver);
}
}
複製程式碼
如果覺得我的文字對你有所幫助的話,歡迎關注我的公眾號:
我的群歡迎大家進來探討各種技術與非技術的話題,有興趣的朋友們加我私人微信huannan88,我拉你進群交(♂)流(♀)。