android中Activity橫豎屏切換的那些事
講解之前需要說(shuō)明的是
- 旋轉(zhuǎn)屏幕:在系統(tǒng)的自動(dòng)旋轉(zhuǎn)屏幕開(kāi)啟的情況下,我們旋轉(zhuǎn)屏幕
- 手動(dòng)設(shè)置屏幕:我們自己去調(diào)用Activity的 setRequestedOrientation 方法。
設(shè)置屏幕的方向
簡(jiǎn)介
值 | 描述 |
---|---|
unspecified | 默認(rèn)值。系統(tǒng)自動(dòng)選擇屏幕方向 |
behind | 跟activity堆棧中的下面一個(gè)activity的方向一致 |
landscape | 橫屏方向,顯示的寬比高長(zhǎng) |
portrait | 豎屏方向,顯示的高比寬長(zhǎng) |
sensor | 由設(shè)備的物理方向傳感器決定,如果用戶旋轉(zhuǎn)設(shè)備,這屏幕就會(huì)橫豎屏切換 |
nosensor | 忽略物理方向傳感器,這樣就不會(huì)隨著用戶旋轉(zhuǎn)設(shè)備而橫豎屏切換了("unspecified"設(shè)置除外) |
user | 用戶當(dāng)前首選的方向 |
reverseLandscape | API 9 以上,反向橫屏 |
reversePortrait | API 9 以上,反向豎屏 |
sensorLandscape | API 9 以上,橫屏,但是可以根據(jù) 物理方向傳感器來(lái)切換正反向橫屏 |
sensorPortrait | API 9 以上,豎屏,但是可以根據(jù) 物理方向傳感器來(lái)切換正反向豎屏 |
fullSensor | API 9 以上,上下左右四個(gè)方向,由物理方向傳感器決定 |
locked | API 18 以上,鎖死當(dāng)前屏幕的方向 |
第一種
我們可以在AndroidManifest 清單文件里面制定Activity的方向
<activity android:name=".view.main.MainActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity>
這樣橫豎屏切換的時(shí)候不會(huì)重新創(chuàng)建Activity
第二種
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Android:android:configChanges
如果我們不配置configuration ,當(dāng) configuration 發(fā)生變化的時(shí)候,activity會(huì)自動(dòng)處理它。反之,如果我們配置了相應(yīng)的 configuration,當(dāng)新的 configuration 發(fā)生變化的時(shí)候,會(huì)回調(diào) Activity 的 onConfigurationChanged() 方法。
下面我們一起來(lái)看一下幾個(gè)常用的值得介紹,其他不常用的hi請(qǐng)自行查閱文檔。官網(wǎng)地址:
值 | 描述 |
---|---|
keyboardHidden | 鍵盤(pán)的可訪問(wèn)性發(fā)生變化——例如:用戶發(fā)現(xiàn)了硬件鍵盤(pán)。 |
orientation | 屏幕方向發(fā)生變化——用戶旋轉(zhuǎn)了屏幕。注意:如果應(yīng)用程序的目標(biāo)API級(jí)別是13或更高(通過(guò)屬性minSdkVersion和屬性targetSdkVersion聲明),你也需要聲明配置項(xiàng)screenSize,因?yàn)檫@將在設(shè)備選擇肖像和屏幕方向時(shí)發(fā)生改變。 |
screenLayout | 屏幕布局發(fā)生變化——這個(gè)會(huì)導(dǎo)致顯示不同的Activity。屏幕方向發(fā)生變化——用戶旋轉(zhuǎn)了屏幕。注意:如果應(yīng)用程序的目標(biāo)API級(jí)別是13或更高(通過(guò)屬性minSdkVersion和屬性targetSdkVersion聲明),你也需要聲明配置項(xiàng)screenSize,因?yàn)檫@將在設(shè)備選擇肖像和屏幕方向時(shí)發(fā)生改變。 |
screenSize | 當(dāng)前可用屏幕大小發(fā)生變化。這代表一個(gè)當(dāng)前可用大小的變化,和當(dāng)前的比率相關(guān),因此當(dāng)用戶選擇不同的畫(huà)面和圖像,會(huì)發(fā)生變化。然而,如果你的程序目標(biāo)API級(jí)別是12或更低,你的Activity總是會(huì)自己處理這個(gè)配置變化(這個(gè)變化不會(huì)引起Activity的重啟,甚至在Android 3.2或更新的設(shè)備上)。在API級(jí)別13里加入的。 |
android:configChanges 常用配置
在Android 3.2以后,如果我們進(jìn)行下列的配置 ,這樣的話橫豎屏不會(huì)重新創(chuàng)建Activity,但是會(huì)調(diào)用 onConfigurationChanged()方法
<activity android:name=".view.main.MainActivity" android:configChanges="keyboardHidden|orientation|screenSize" > <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> 在api 3.2 以前,我們只需這樣配置即可,android:configChanges="keyboardHidden|orientation"。 <activity android:name=".view.main.MainActivity" android:configChanges="keyboardHidden|orientation" > <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity>
小結(jié)
當(dāng)我們進(jìn)行了上述的配置,
- 豎屏 》 橫屏 onConfigurationChanged()方法會(huì)調(diào)用一次
- 橫屏 》 豎屏 onConfigurationChanged()方法也會(huì)調(diào)用一次
因此我們通??梢赃M(jìn)行相應(yīng)的處理
public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { // 加入橫屏要處理的代碼 } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { // 加入豎屏要處理的代碼 } }
如果我們同時(shí)設(shè)置了 android:configChanges="keyboardHidden|orientation|screenSize" 和 android:screenOrientation="portrait",那又會(huì)是怎樣的呢?
如果我們打開(kāi)系統(tǒng)的自動(dòng)旋轉(zhuǎn)屏幕,旋轉(zhuǎn)屏幕,系統(tǒng)不會(huì)發(fā)生變化,也不會(huì)調(diào)用 Activity 的 onConfigurationChanged 方法。
當(dāng)我們手動(dòng)調(diào)用 setRequestedOrientation() 方法去改變屏幕的方向的時(shí)候,還是會(huì)調(diào)用 onConfigurationChanged 方法的
擴(kuò)展
設(shè)置全屏模式
// 去掉ActionBar requestWindowFeature(Window.FEATURE_NO_TITLE); // 設(shè)置全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
在實(shí)際項(xiàng)目中,我們通常會(huì)固定我們應(yīng)用的屏幕方向,只對(duì)一些特定的需要切換屏幕的Activity做處理,那我們?nèi)绾谓y(tǒng)一設(shè)置屏幕的方向呢?
第一種方法,復(fù)制張貼,在AndroidManifest清單文件里面的每一個(gè)Activity標(biāo)簽增加如下標(biāo)簽。
<activity android:name=".MainActivity" android:screenOrientation="portrait" > </activity>
第二種方法,剛開(kāi)始我直接在 AppTheme 里面 設(shè)置 android:screenOrientation,但是沒(méi)有效果,剛開(kāi)始我也很納悶,后面查閱了官網(wǎng)文檔,描述如下,才解決了疑問(wèn).
Specify the orientation an activity should be run in. If not specified, it will run in the current preferred orientation of the screen. This attribute is supported by the <activity> element.
<!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="android:screenOrientation">portrait</item> </style>
即這種方法不可取
第三種方法,在BaseActivity里面動(dòng)態(tài)設(shè)置
public class BaseActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } }
同時(shí)列出這三種方法,最主要的目的不是為了告訴大家有這幾種方法可以統(tǒng)一設(shè)置屏幕的方向,最重要的是告訴大家一種思想吧。通常在xml 文件可以設(shè)置的,在java 代碼也可以設(shè)置。
利用系統(tǒng)的加載機(jī)制自動(dòng)幫我們加載相應(yīng)的布局
如果大家在資源目錄res 中添加了 layout-land(橫向布局文件夾) 和 layout-port (豎想布局文件夾),重啟Activity模式的橫豎屏切換,
可能有人會(huì)有這樣的疑問(wèn),當(dāng)我們?cè)O(shè)置了Activity的方向?yàn)樨Q屏或者橫屏的時(shí)候,旋轉(zhuǎn)屏幕并不會(huì)重新調(diào)用Activity的各個(gè)生命周期,那我們要怎樣檢測(cè)呢?
其實(shí)很簡(jiǎn)單,那就是利用我們的傳感器,然后根據(jù)旋轉(zhuǎn)的方向做相應(yīng)的處理
//注冊(cè)重力感應(yīng)器 屏幕旋轉(zhuǎn) mSm = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mSensor = mSm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mSm.registerListener(mOrientationSensorListener, mSensor, SensorManager.SENSOR_DELAY_UI);
public class OrientationSensorListener implements SensorEventListener { private static final int _DATA_X = 0; private static final int _DATA_Y = 1; private static final int _DATA_Z = 2; public static final int ORIENTATION_UNKNOWN = -1; private boolean sensor_flag = true; public static final String TAG = "xujun"; int mLastAngle=-1; AngleChangleListener mAngleChangleListener; public OrientationSensorListener(AngleChangleListener angleChangleListener){ mAngleChangleListener=angleChangleListener; } @Override public void onAccuracyChanged(Sensor arg0, int arg1) { // TODO Auto-generated method stub } @Override public void onSensorChanged(SensorEvent event) { float[] values = event.values; int orientation = ORIENTATION_UNKNOWN; float X = -values[_DATA_X]; float Y = -values[_DATA_Y]; float Z = -values[_DATA_Z]; /** * 這一段據(jù)說(shuō)是 android源碼里面拿出來(lái)的計(jì)算 屏幕旋轉(zhuǎn)的 不懂 先留著 萬(wàn)一以后懂了呢 */ float magnitude = X * X + Y * Y; // Don't trust the angle if the magnitude is small compared to the y value if (magnitude * 4 >= Z * Z) { //屏幕旋轉(zhuǎn)時(shí) float OneEightyOverPi = 57.29577957855f; float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi; orientation = 90 - (int) Math.round(angle); // normalize to 0 - 359 range while (orientation >= 360) { orientation -= 360; } while (orientation < 0) { orientation += 360; } } if (orientation > 225 && orientation < 315) { //橫屏 sensor_flag = false; } else if ((orientation > 315 && orientation < 360) || (orientation > 0 && orientation < 45)) { //豎屏 sensor_flag = true; } // Log.i(TAG, "onSensorChanged: orientation=" + orientation+" mLastAngle="+mLastAngle); if(mLastAngle!=orientation && mAngleChangleListener!=null){ mAngleChangleListener.onChange(orientation); mLastAngle=orientation; } } }
設(shè)備旋轉(zhuǎn)時(shí)保存Activity的交互狀態(tài)
大家先看一下Activity的生命周期,我們知道如果我們不配置Activity的方向或者Activity的 android:configchang 屬性的時(shí)候,每次旋轉(zhuǎn)屏幕,Activity都會(huì)重新被創(chuàng)建出來(lái)。那我們要如何保存我們當(dāng)前的狀態(tài)呢。
其實(shí)我們可以考慮在 onPause() 或者在 onStop() 里面保存我們相應(yīng)的數(shù)據(jù),再在onCreate() 方法里面判斷 savedInstanceState 是否有緩存我們的數(shù)據(jù)即可。 至于選擇在onPause() 還是 onStop() 保存數(shù)據(jù),得看具體的需求分析。 onPause() 在界面失去焦點(diǎn)的時(shí)候會(huì)回調(diào), onStop() 方法在界面完全不可見(jiàn)的時(shí)候會(huì)回調(diào)。
private static final String KEY_INDEX = "index"; private int mCurrentIndex = 0; @Override protected void onCreate(Bundle savedInstanceState) { if (savedInstanceState != null) { mCurrentIndex = savedInstanceState.getInt(KEY_INDEX, 0); } } @Override protected void onPause(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(KEY_INDEX, mCurrentIndex); }
Demo 下載地址:ScreenDemo_jb51.rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android橫豎屏切換不重啟activity解決方案
- android橫豎屏切換時(shí)候Activity的生命周期
- android實(shí)現(xiàn)在橫豎屏切換時(shí)頁(yè)面信息不被重置的示例分享
- Android Activity 橫豎屏切換的生命周期
- 解析Android橫豎屏切換的問(wèn)題
- Android橫豎屏幕切換小結(jié)
- Android編程實(shí)現(xiàn)橫豎屏切換時(shí)不銷毀當(dāng)前activity和鎖定屏幕的方法
- 解決Android橫豎屏切換數(shù)據(jù)丟失問(wèn)題的方法
- Android實(shí)現(xiàn)橫豎屏切換的實(shí)例代碼
- Android橫豎屏切換及其對(duì)應(yīng)布局加載問(wèn)題詳解
相關(guān)文章
Android IntentService詳解及使用實(shí)例
這篇文章主要介紹了Android IntentService詳解及使用實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03Android中findViewById獲取控件返回為空問(wèn)題怎么解決
這篇文章主要介紹了Android中findViewById獲取控件返回為空問(wèn)題怎么解決的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06在Flutter中讓文字Text換行的實(shí)現(xiàn)步驟
在Flutter中,Text小部件默認(rèn)會(huì)嘗試在其父小部件的約束內(nèi)顯示所有文本內(nèi)容,如果父小部件沒(méi)有提供足夠的空間或沒(méi)有設(shè)置約束限制,Text小部件可能無(wú)法正確換行,本文給大家介紹了在Flutter中如何讓文字Text換行,需要的朋友可以參考下2024-07-07Android中使用ZXing生成二維碼(支持添加Logo圖案)
ZXing是谷歌的一個(gè)開(kāi)源庫(kù),可以用來(lái)生成二維碼、掃描二維碼。接下來(lái)通過(guò)本文給大家介紹Android中使用ZXing生成二維碼(支持添加Logo圖案),需要的朋友參考下2017-01-01Android性能優(yōu)化之弱網(wǎng)優(yōu)化詳解
這篇文章主要為大家介紹了Android性能優(yōu)化之弱網(wǎng)優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Android中SurfaceView用法簡(jiǎn)單實(shí)例
這篇文章主要介紹了Android中SurfaceView用法,以一個(gè)簡(jiǎn)單的圖形繪制及改變位置實(shí)現(xiàn)方法分析了SurfaceView的使用技巧,需要的朋友可以參考下2015-10-10Android學(xué)習(xí)教程之2D繪圖基礎(chǔ)及繪制太極圖
這篇文章主要給大家介紹了Android中2D繪圖基礎(chǔ)的相關(guān)資料,文中介紹了繪圖的基礎(chǔ)內(nèi)容,以及通過(guò)Canvas和Paint實(shí)現(xiàn)繪制太極圖的詳細(xì)過(guò)程,對(duì)各位Android新手開(kāi)發(fā)者們具有一定的參考價(jià)值,需要的朋友下面來(lái)一起看看吧。2017-04-04