欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android再探全面屏適配示例詳解

 更新時間:2023年03月01日 16:11:04   作者:流浪漢kylin  
這篇文章主要為大家介紹了Android再探全面屏適配示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

簡單來說,以前是做app的,然后轉去做了終端幾年,現(xiàn)在又做回了app,然后就涉及到了全面屏的適配,但是很多年前做的適配也不記得了,所以來重新再探究一遍。

以前做終端的時候,適配?我不知道什么叫適配,就一個機型,想怎么玩就怎么玩,自己就是爹?,F(xiàn)在做應用,不好意思,手機廠商才是大爹,我們都是孫子。

我簡單的回顧了一下,其實全面屏的適配一開始是因為劉海屏才開始這條路線,然后就出現(xiàn)一大堆奇奇怪怪的東西。幸好谷歌也是做人,在28之后就提出一套規(guī)范。

Android P前后

對于Android P,其實也就android 8.0和android 9.0兩個版本,因為是從android 8.0開始流行的,各做各的,然后在9.0的時候google給出了一套規(guī)范。

對于Android 9.0也就是28,google推出了DisplayCutout,它統(tǒng)一了android凹凸屏的處理,使用起來也很方便。

WindowManager.LayoutParams wlp = getWindow().getAttributes();
wlp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
getWindow().setAttributes(wlp);

給WindowManager.LayoutParams設置layoutInDisplayCutoutMode就行,是不是很簡單。
它有幾個參數(shù)可供選擇

(1)LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:默認值,一般效果和LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER相同。

(2)LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES:內(nèi)容顯示到凹凸屏區(qū)域。

(3)LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:內(nèi)容不會顯示到凹凸屏區(qū)域。

對于Android 28以下的適配

這個比較麻煩,因為在28以下是沒有l(wèi)ayoutInDisplayCutoutMode的,所以要單獨去調,網(wǎng)上也有很多說如何去對不同的廠商去做適配,但其實這東西還是要調的。哪怕你是相同的機型,不同的系統(tǒng)版本都可能會產(chǎn)生不同的效果,沒錯,就是這么恐怖?;径际侵荒茏鰅f-else單獨對不同的機型做適配。要么就是讓28以下的統(tǒng)一不做全面屏的效果,比如說把內(nèi)容顯示到凹凸屏區(qū)域,你就判斷在28的時候不做這種操作,但一般不是你說的算,多多少少還是需要做適配,只能具體情況具體調試。

對不同的場景做適配

你覺得你說你就對28做適配,28以下就不管了,我就設置layoutInDisplayCutoutMode一行代碼就行??墒虑槟挠羞@么簡單。

系統(tǒng)的Bar主要分為3種,一種是在屏幕上方的狀態(tài)欄,一種是在屏幕底端的導航欄,還是一直是仿IOS的底部橫條代替導航欄,這在和導航欄一起分析但會有些許不同。

而這個過程中又會區(qū)分為橫屏和豎屏的情況,多少也會又些許差異,當然我也沒辦法把全部特殊的常見列舉出來。不同的手機廠商之間也會存在有不同的情況,還有上面說的android28前后,這里主要是對android28之后進行分析。

狀態(tài)欄

假如要實現(xiàn)全屏顯示的效果,我們要如何去對狀態(tài)欄做適配。

為了方便調試,我把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>

然后我們直接運行看看效果

上面狀態(tài)欄的顏色其實是我的桌面背景,這里看不太清楚,我放一張我桌面的背景上來

能看到,內(nèi)容是不會顯示在狀態(tài)欄的空間的。根據(jù)上面提到的,我們用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);
        }
    }
}

看看效果

能看到狀態(tài)欄顯示橙色,這說明window的內(nèi)容已經(jīng)能覆蓋到狀態(tài)欄了,但是顯示的內(nèi)容還是沒上去。

難道這個屬性不行?當然不是。這個不知道怎么解釋好,你可以簡單理解成窗口是已經(jīng)能顯示到狀態(tài)欄的區(qū)域了,但是view因為某些默認的配置導致距離頂部有一定的間距。

相信大家多多少少聽過沉浸模式,我之前寫的軟鍵盤沖突也有涉及到一點這塊,view有一個方法SystemUiVisibility,它可以設置一些屬性,其實這是一個int值的flags,你把它想象成window的flags就好理解多了。

通過setSystemUiVisibility方法,我們對View做一些配置,就按網(wǎng)上寫的,沉浸模式

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

看看效果

可以看到,內(nèi)容就正常顯示到上面了。我覺得講得已經(jīng)挺詳細了,好,那提兩個問題:如果我不設layoutInDisplayCutoutMode,只設View的SystemUiVisibility,能不能顯示到狀態(tài)欄的區(qū)域?第二個,我設了layoutInDisplayCutoutMode,是不是這個window里面的所有view都必須設置SystemUiVisibility才能把內(nèi)容顯示到狀態(tài)欄區(qū)域?

這個是實現(xiàn)一個把內(nèi)容顯示到狀態(tài)欄的效果,還有其它效果比如設置狀態(tài)欄顏色或者什么的,這里就不講了,但要注意,如果你在設置某些效果的過程中,沒效果,可以考慮一下是不是手機廠商造成的,多試幾個廠商。

對了,還有橫屏的情況,橫屏的情況下狀態(tài)欄還是在頂部,但是劉海區(qū)域(凹凸區(qū)域)在側邊,layoutInDisplayCutoutMode是對側邊的凹凸區(qū)域生效。所以要知道它不是針對狀態(tài)欄的,是針對凹凸區(qū)域的。

導航欄和底部橫條

這個就比狀態(tài)欄麻煩一些。這里就主要以橫屏的情況去講解。橫屏的情況下導航欄一共有3種顯示情況,例如小米的橫條,就是顯示在底部,其它手機的導航欄就是顯示在側邊,還有一種是側邊的情況下,不管你怎么轉屏,都會固定顯示在右邊。

導航欄沒有凹凸區(qū)域,所以不需要用到windoow lp的layoutInDisplayCutoutMode,我們一般都能直接通過view的SystemUiVisibility方法去配置實現(xiàn)它的一個想要的效果。

可以先看看SystemUiVisibility能設置的一些常用的flags

public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 系統(tǒng)UI(狀態(tài)欄導航欄)顯示
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; // 全屏模式,系統(tǒng)UI會被隱藏
public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100; // 穩(wěn)定布局
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穩(wěn)定布局,官方有一段注釋是這么說的,如果指定SYSTEM_UI_FLAG_LAYOUT_FULLSEEN和SYSTEM_UI-FLAG_LAYOUT _HIDE_NAVIGATION,則可以使用穩(wěn)定的布局轉換到SYSTEM_UI_FLAG_FULLSCREEN和SYSTEM _UI_FLAG-HIDE_NAVIGATION。(請注意,應避免單獨使用SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION。)如果已將窗口標志W(wǎng)indowManager.LayoutParams.FLAG_FULLSCREEN設置為隱藏狀態(tài)欄(而不是使用SYSTEM.UI_FLAG_FULLSCREEN),則隱藏的狀態(tài)欄將被視為“穩(wěn)定”狀態(tài)。

這什么意思呢?意思就是這個屬性不是死的,它會受其它東西影響到最終的顯示效果。說人話就是你用它的話實現(xiàn)的效果就很靈活,但同樣會出BUG的概率也更高。

關于SYSTEM_UI_FLAG_IMMERSIVE讓SYSTEM_UI_FLAG_HIDE_NAVIGATION失效,官方有一段注釋是這么說的:由于此標志是SYSTEM_UI_FLAG_HIDE_NAVIGATION的修飾符,因此僅當與該標志結合使用時才具有效果。它所表現(xiàn)出來的效果是SYSTEM_UI_FLAG_HIDE_NAVIGATION會隱藏導航欄,但當你手動拉出導航欄之后,就不會再隱藏了。

但這也涉及到不同的手機廠商可能會出現(xiàn)不同的效果。比如小米,默認的顯示會是這樣

可以看出,橫條是顯示在底部,側邊沒有導航欄,然后我們一個一個flags來調看看效果。首先SYSTEM_UI_FLAG_LAYOUT_STABLE這種情況我是不調了,很難去模擬出來。SYSTEM_UI_FLAG_VISIBLE和SYSTEM_UI_FLAG_LOW_PROFILE效果在這里顯示的應該會和默認情況顯示的一樣。

這里我會模擬兩種場景來說,第一種是純activity的window的view設置的效果,第二種是window.addview的view設置的效果(我后續(xù)會稱之為兩層window),它們的效果會有些許差異

1. SYSTEM_UI_FLAG_HIDE_NAVIGATION

先看看SYSTEM_UI_FLAG_HIDE_NAVIGATION,假如我設置了SYSTEM_UI_FLAG_HIDE_NAVIGATION

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

可以看到,底部橫條已經(jīng)不顯示了。這里可以多說一句,你們猜猜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);
    }
}

看看效果,看到差異沒有,我們之前設置的話,它的橫條還在,并且是黑色的,現(xiàn)在有一個window然后我們設置之后發(fā)現(xiàn)橫條還在,但背景變成透明的了。

2. SYSTEM_UI_FLAG_FULLSCREEN

看看單獨設置SYSTEM_UI_FLAG_FULLSCREEN的效果

看得到效果也是一樣的。說明SYSTEM_UI_FLAG_FULLSCREEN是不會隱藏底部導航欄的。

但這個屬性是不是就沒用了,并不是,假如我使用兩層window的的情況,不設置這個參數(shù)的話,可以看到效果會是這樣的:狀態(tài)欄拉下來不會停留,會快速的縮回去

但如果我設置了,代碼寫成這樣

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

能看到效果狀態(tài)欄下拉后就能正常的短暫停留才消失

3. SYSTEM_UI_FLAG_IMMERSIVE_STICKY

前面說了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,它在我這臺手機,表現(xiàn)都一樣。我強調“我這臺手機”,是因為可能會不同機型有不同的表現(xiàn)。

然后我們用兩層去做看看效果,代碼這樣

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:看到這里狀態(tài)欄縮回去很快,是因為沒設置SYSTEM_UI_FLAG_FULLSCREEN

SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN的效果是什么的?

這里我就補貼代碼直接讓你們看看現(xiàn)象吧,如果不設置的話,表現(xiàn)是這樣的

可以看出我切出去之后,再回來,第二層的window會被位移(或者說擠壓)再恢復。但如果設置的話就不會有這種問題。

總結

做個簡單的總結,這里主要是單獨拆開詳細講了狀態(tài)欄和導航欄的一些適配場景,首先是想讓大家先有個概念,重點是想說,即便google在android28中統(tǒng)一了規(guī)范,但還是會出現(xiàn)不同的廠商甚至不同的型號,不同的系統(tǒng)版本,所體現(xiàn)出的效果不同。

我這里也總結了一些手機的表現(xiàn),因為這里寫得確實有點長,所以就之后單獨再些一篇出來總結。

以上就是Android再探全面屏適配示例詳解的詳細內(nèi)容,更多關于Android全面屏適配的資料請關注腳本之家其它相關文章!

相關文章

最新評論