您好,登錄后才能下訂單哦!
今天小編給大家分享一下Android全面屏適配怎么實現的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
對于Android P,其實也就android 8.0和android 9.0兩個版本,因為是從android 8.0開始流行的,各做各的,然后在9.0的時候google給出了一套規范。
對于Android 9.0也就是28,google推出了DisplayCutout,它統一了android凹凸屏的處理,使用起來也很方便。
WindowManager.LayoutParams wlp = getWindow().getAttributes(); wlp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; getWindow().setAttributes(wlp);
給WindowManager.LayoutParams設置layoutInDisplayCutoutMode就行,是不是很簡單。
它有幾個參數可供選擇
(1)LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:默認值,一般效果和LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER相同。
(2)LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES:內容顯示到凹凸屏區域。
(3)LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:內容不會顯示到凹凸屏區域。
對于Android 28以下的適配
這個比較麻煩,因為在28以下是沒有layoutInDisplayCutoutMode的,所以要單獨去調,網上也有很多說如何去對不同的廠商去做適配,但其實這東西還是要調的。哪怕你是相同的機型,不同的系統版本都可能會產生不同的效果,沒錯,就是這么恐怖。基本都是只能做if-else單獨對不同的機型做適配。要么就是讓28以下的統一不做全面屏的效果,比如說把內容顯示到凹凸屏區域,你就判斷在28的時候不做這種操作,但一般不是你說的算,多多少少還是需要做適配,只能具體情況具體調試。
你覺得你說你就對28做適配,28以下就不管了,我就設置layoutInDisplayCutoutMode一行代碼就行。可事情哪有這么簡單。
系統的Bar主要分為3種,一種是在屏幕上方的狀態欄,一種是在屏幕底端的導航欄,還是一直是仿IOS的底部橫條代替導航欄,這在和導航欄一起分析但會有些許不同。
而這個過程中又會區分為橫屏和豎屏的情況,多少也會又些許差異,當然我也沒辦法把全部特殊的常見列舉出來。不同的手機廠商之間也會存在有不同的情況,還有上面說的android28前后,這里主要是對android28之后進行分析。
假如要實現全屏顯示的效果,我們要如何去對狀態欄做適配。
為了方便調試,我把window的顏色設置為橙色,把布局的顏色設置成綠色
<style name="TestTheme" parent="@android:style/Theme.Material.Light.NoActionBar.Fullscreen" > <item name="android:windowBackground">@android:color/holo_orange_light</item> </style>
<activity android:name=".TestActivity" android:configChanges="orientation|screenSize|keyboardHidden|smallestScreenSize|screenSize|screenLayout" android:theme="@style/TestTheme" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#336655" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用于參考位置" /> </FrameLayout>
然后我們直接運行看看效果
能看到,內容是不會顯示在狀態欄的空間的。根據上面提到的,我們用layoutInDisplayCutoutMode試試
public class TestActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { WindowManager.LayoutParams wlp = getWindow().getAttributes(); wlp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; getWindow().setAttributes(wlp); } } }
看看效果
能看到狀態欄顯示橙色,這說明window的內容已經能覆蓋到狀態欄了,但是顯示的內容還是沒上去。
難道這個屬性不行?當然不是。這個不知道怎么解釋好,你可以簡單理解成窗口是已經能顯示到狀態欄的區域了,但是view因為某些默認的配置導致距離頂部有一定的間距。
相信大家多多少少聽過沉浸模式,我之前寫的軟鍵盤沖突也有涉及到一點這塊,view有一個方法SystemUiVisibility,它可以設置一些屬性,其實這是一個int值的flags,你把它想象成window的flags就好理解多了。
通過setSystemUiVisibility方法,我們對View做一些配置,就按網上寫的,沉浸模式
public class TestActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { WindowManager.LayoutParams wlp = getWindow().getAttributes(); wlp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; getWindow().setAttributes(wlp); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } } }
看看效果
可以看到,內容就正常顯示到上面了。我覺得講得已經挺詳細了,好,那提兩個問題:如果我不設layoutInDisplayCutoutMode,只設View的SystemUiVisibility,能不能顯示到狀態欄的區域?第二個,我設了layoutInDisplayCutoutMode,是不是這個window里面的所有view都必須設置SystemUiVisibility才能把內容顯示到狀態欄區域?
這個是實現一個把內容顯示到狀態欄的效果,還有其它效果比如設置狀態欄顏色或者什么的,這里就不講了,但要注意,如果你在設置某些效果的過程中,沒效果,可以考慮一下是不是手機廠商造成的,多試幾個廠商。
對了,還有橫屏的情況,橫屏的情況下狀態欄還是在頂部,但是劉海區域(凹凸區域)在側邊,layoutInDisplayCutoutMode是對側邊的凹凸區域生效。所以要知道它不是針對狀態欄的,是針對凹凸區域的。
這個就比狀態欄麻煩一些。這里就主要以橫屏的情況去講解。橫屏的情況下導航欄一共有3種顯示情況,例如小米的橫條,就是顯示在底部,其它手機的導航欄就是顯示在側邊,還有一種是側邊的情況下,不管你怎么轉屏,都會固定顯示在右邊。
導航欄沒有凹凸區域,所以不需要用到windoow lp的layoutInDisplayCutoutMode,我們一般都能直接通過view的SystemUiVisibility方法去配置實現它的一個想要的效果。
可以先看看SystemUiVisibility能設置的一些常用的flags
public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 系統UI(狀態欄導航欄)顯示 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001; // 低調模式(就是類似于變暗等效果) public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002; // 隱藏導航欄和橫條 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004; // 全屏模式,系統UI會被隱藏 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100; // 穩定布局 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200; // 對窗口生效SYSTEM_UI_FLAG_HIDE_NAVIGATION public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400; // 對窗口生效SYSTEM_UI_FLAG_FULLSCREEN public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800; // 讓SYSTEM_UI_FLAG_HIDE_NAVIGATION失效 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000; // 同上相反
關于SYSTEM_UI_FLAG_LAYOUT_STABLE穩定布局,官方有一段注釋是這么說的,如果指定SYSTEM_UI_FLAG_LAYOUT_FULLSEEN和SYSTEM_UI-FLAG_LAYOUT _HIDE_NAVIGATION,則可以使用穩定的布局轉換到SYSTEM_UI_FLAG_FULLSCREEN和SYSTEM _UI_FLAG-HIDE_NAVIGATION。(請注意,應避免單獨使用SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION。)如果已將窗口標志WindowManager.LayoutParams.FLAG_FULLSCREEN設置為隱藏狀態欄(而不是使用SYSTEM.UI_FLAG_FULLSCREEN),則隱藏的狀態欄將被視為“穩定”狀態。
這什么意思呢?意思就是這個屬性不是死的,它會受其它東西影響到最終的顯示效果。說人話就是你用它的話實現的效果就很靈活,但同樣會出BUG的概率也更高。
關于SYSTEM_UI_FLAG_IMMERSIVE讓SYSTEM_UI_FLAG_HIDE_NAVIGATION失效,官方有一段注釋是這么說的:由于此標志是SYSTEM_UI_FLAG_HIDE_NAVIGATION的修飾符,因此僅當與該標志結合使用時才具有效果。它所表現出來的效果是SYSTEM_UI_FLAG_HIDE_NAVIGATION會隱藏導航欄,但當你手動拉出導航欄之后,就不會再隱藏了。
但這也涉及到不同的手機廠商可能會出現不同的效果。比如小米,默認的顯示會是這樣
可以看出,橫條是顯示在底部,側邊沒有導航欄,然后我們一個一個flags來調看看效果。首先SYSTEM_UI_FLAG_LAYOUT_STABLE這種情況我是不調了,很難去模擬出來。SYSTEM_UI_FLAG_VISIBLE和SYSTEM_UI_FLAG_LOW_PROFILE效果在這里顯示的應該會和默認情況顯示的一樣。
這里我會模擬兩種場景來說,第一種是純activity的window的view設置的效果,第二種是window.addview的view設置的效果(我后續會稱之為兩層window),它們的效果會有些許差異
先看看SYSTEM_UI_FLAG_HIDE_NAVIGATION,假如我設置了SYSTEM_UI_FLAG_HIDE_NAVIGATION
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
可以看到,底部橫條已經不顯示了。這里可以多說一句,你們猜猜SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION對view管不管用,可以試試
只設置它能明顯看出底部的橫條還是存在的。\但是當用window.addview之后再配置SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION的話,可以看看效果。
代碼是這樣的
public class TestActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); addWindow(); } private void addWindow() { WindowManager wm = getWindowManager(); WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(); wlp.width = ViewGroup.LayoutParams.WRAP_CONTENT; wlp.height = ViewGroup.LayoutParams.WRAP_CONTENT; wlp.gravity = Gravity.START | Gravity.TOP; TextView textView = new TextView(this); textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); textView.setText("上一層"); textView.setBackgroundResource(R.color.blue); wm.addView(textView, wlp); } }
看看效果,看到差異沒有,我們之前設置的話,它的橫條還在,并且是黑色的,現在有一個window然后我們設置之后發現橫條還在,但背景變成透明的了。
看看單獨設置SYSTEM_UI_FLAG_FULLSCREEN的效果
看得到效果也是一樣的。說明SYSTEM_UI_FLAG_FULLSCREEN是不會隱藏底部導航欄的。
但這個屬性是不是就沒用了,并不是,假如我使用兩層window的的情況,不設置這個參數的話,可以看到效果會是這樣的:狀態欄拉下來不會停留,會快速的縮回去
但如果我設置了,代碼寫成這樣
public class TestActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); addWindow(); } private void addWindow() { WindowManager wm = getWindowManager(); WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(); wlp.width = ViewGroup.LayoutParams.WRAP_CONTENT; wlp.height = ViewGroup.LayoutParams.WRAP_CONTENT; wlp.gravity = Gravity.START | Gravity.TOP; TextView textView = new TextView(this); textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); textView.setText("上一層"); textView.setBackgroundResource(R.color.blue); wm.addView(textView, wlp); textView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); } }
能看到效果狀態欄下拉后就能正常的短暫停留才消失
前面說了SYSTEM_UI_FLAG_IMMERSIVE_STICKY是配合SYSTEM_UI_FLAG_HIDE_NAVIGATION的,所以我們這里測試的時候,寫SYSTEM_UI_FLAG_HIDE_NAVIGATION。
直接是單層window去設置的話是看不出明顯效果的,比如代碼這樣
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); // addWindow(); }
我把第二層給注釋掉,然后給第一層設置SYSTEM_UI_FLAG_HIDE_NAVIGATION,不管設不設置SYSTEM_UI_FLAG_IMMERSIVE_STICKY,它在我這臺手機,表現都一樣。我強調“我這臺手機”,是因為可能會不同機型有不同的表現。
然后我們用兩層去做看看效果,代碼這樣
public class TestActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); addWindow(); } private void addWindow() { WindowManager wm = getWindowManager(); WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(); wlp.width = ViewGroup.LayoutParams.WRAP_CONTENT; wlp.height = ViewGroup.LayoutParams.WRAP_CONTENT; wlp.gravity = Gravity.START | Gravity.TOP; TextView textView = new TextView(this); textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); textView.setText("上一層"); textView.setBackgroundResource(R.color.blue); wm.addView(textView, wlp); textView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); } }
不設置SYSTEM_UI_FLAG_IMMERSIVE_STICKY的情況下,我這里沒辦法錄gif(因為點了就會影響),它的效果是,一開始底部橫條是隱藏的,但是當點擊之后會顯示并且顯示之后就不再隱藏。
設置之后
public class TestActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); addWindow(); } private void addWindow() { WindowManager wm = getWindowManager(); WindowManager.LayoutParams wlp = new WindowManager.LayoutParams(); wlp.width = ViewGroup.LayoutParams.WRAP_CONTENT; wlp.height = ViewGroup.LayoutParams.WRAP_CONTENT; wlp.gravity = Gravity.START | Gravity.TOP; TextView textView = new TextView(this); textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); textView.setText("上一層"); textView.setBackgroundResource(R.color.blue); wm.addView(textView, wlp); textView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } }
看到底部橫條會變透明,然后拉出來一段時間之后會自己隱藏起來。PS:看到這里狀態欄縮回去很快,是因為沒設置SYSTEM_UI_FLAG_FULLSCREEN
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN的效果是什么的?
這里我就補貼代碼直接讓你們看看現象吧,如果不設置的話,window會被位移(或者說擠壓)再恢復。但如果設置的話就不會有這種問題。
以上就是“Android全面屏適配怎么實現”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。