最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android 超詳細講解fitsSystemWindows屬性的使用

 更新時間:2022年03月26日 11:59:22   作者:guolin  
fitsSystemWindows屬性可以讓view根據(jù)系統(tǒng)窗口來調(diào)整自己的布局;簡單點說就是我們在設置應用布局時是否考慮系統(tǒng)窗口布局,這里系統(tǒng)窗口包括系統(tǒng)狀態(tài)欄、導航欄、輸入法等,包括一些手機系統(tǒng)帶有的底部虛擬按鍵

對于android:fitsSystemWindows這個屬性你是否感覺又熟悉又陌生呢?

熟悉是因為大概知道它可以用來實現(xiàn)沉浸式狀態(tài)欄的效果,陌生是因為對它好像又不夠了解,這個屬性經(jīng)常時靈時不靈的。

其實對于android:fitsSystemWindows屬性我也是一知半解,包括我在寫《第一行代碼》的時候?qū)@部分知識的講解也算不上精準。但是由于當時的理解對于我來說已經(jīng)夠用了,所以也就沒再花時間繼續(xù)深入研究。

而最近因為工作的原因,我又碰上了android:fitsSystemWindows這個屬性,并且我之前的那些知識儲備已經(jīng)不夠用了。所以這次趁著這個機會,我把這部分知識又重新學習了一遍,并整理成一篇文章分享給大家。

我們都不會無緣無故去接觸一個屬性。我相信用到android:fitsSystemWindows的朋友基本都是為了去實現(xiàn)沉浸式狀態(tài)欄效果的。

這里我先解釋一下什么是沉浸式狀態(tài)欄效果。

Android手機頂部用于顯示各種通知和狀態(tài)信息的這個欄叫做狀態(tài)欄。

通常情況下,我們應用程序的內(nèi)容都是顯示在狀態(tài)欄下方的。但有時為了實現(xiàn)更好的視覺效果,我們希望將應用程序的內(nèi)容延伸到狀態(tài)欄的背后,這種就可以稱之為沉浸式狀態(tài)欄。

那么借助android:fitsSystemWindows屬性是如何實現(xiàn)沉浸式狀態(tài)欄效果的呢?這個屬性為什么又總是時靈時不靈呢?接下來我們就來一步步學習和揭秘。

我相信按照絕大多數(shù)人的美好設想,android:fitsSystemWindows屬性就應該像是一個開關一樣,設置成true就可以打開沉浸式狀態(tài)欄效果,設置成false就可以關閉沉浸式狀態(tài)欄效果。但現(xiàn)實并非如此。

下面我們通過代碼示例來演示一下。首先為了驗證沉浸式狀態(tài)欄的效果,需要將系統(tǒng)的狀態(tài)欄改成透明色,代碼如下所示:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        window.statusBarColor = Color.TRANSPARENT
    }
    
}

接下來,我們給activity_main.xml的根布局加上android:fitsSystemWindows屬性,并且給該布局設置了一個背景色用于觀察效果:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff66ff"
    android:fitsSystemWindows="true">

</FrameLayout>

運行一下代碼,效果如下圖所示:

通過布局的背景色我們可以看出,該布局的內(nèi)容并沒有延伸到系統(tǒng)狀態(tài)欄的背后。也就是說,即使設置了android:fitsSystemWindows屬性,我們也沒有實現(xiàn)沉浸式狀態(tài)欄效果。

但是不要著急,接下我們只需要做出一點小修改,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff66ff"
    android:fitsSystemWindows="true">

</androidx.coordinatorlayout.widget.CoordinatorLayout>

可以看到,這里只是將根布局從FrameLayout修改成了CoordinatorLayout,其他都沒有任何變化。然后重新運行程序。效果如下圖所示:

這樣就可以成功實現(xiàn)沉浸式狀態(tài)欄效果了。

話說為什么android:fitsSystemWindows屬性,設置在CoordinatorLayout布局上就能生效,設置在FrameLayout布局上就沒有效果呢?

這是因為,xml中的配置畢竟只是一個標記,如果想要在應用程序當中產(chǎn)生具體的效果,那還是要看代碼中是如何處理這些標記的。

很明顯,F(xiàn)rameLayout對于android:fitsSystemWindows屬性是沒有進行處理的,所以不管設不設置都不會產(chǎn)生什么變化。

而CoordinatorLayout則不同,我們可以觀察它的源碼,如下所示:

private void setupForInsets() {
    if (Build.VERSION.SDK_INT < 21) {
        return;
    }

    if (ViewCompat.getFitsSystemWindows(this)) {
        if (mApplyWindowInsetsListener == null) {
            mApplyWindowInsetsListener =
                    new androidx.core.view.OnApplyWindowInsetsListener() {
                        @Override
                        public WindowInsetsCompat onApplyWindowInsets(View v,
                                WindowInsetsCompat insets) {
                            return setWindowInsets(insets);
                        }
                    };
        }
        // First apply the insets listener
        ViewCompat.setOnApplyWindowInsetsListener(this, mApplyWindowInsetsListener);

        // Now set the sys ui flags to enable us to lay out in the window insets
        setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    } else {
        ViewCompat.setOnApplyWindowInsetsListener(this, null);
    }
}

可以看到,這里當發(fā)現(xiàn)CoordinatorLayout設置了android:fitsSystemWindows屬性時,會對當前布局的insets做一些處理,并且調(diào)用了下面一行代碼:

setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

這行代碼是一切的關鍵所在。準確來講,就是因為執(zhí)行了這行代碼,我們才能將布局的內(nèi)容延伸到系統(tǒng)狀態(tài)欄區(qū)域。

是不是感覺解密了?但事實上CoordinatorLayout所做的事情還遠不止這些。

因為沉浸式狀態(tài)欄其實會帶來很多問題。讓布局的內(nèi)容延伸到狀態(tài)欄的背后,如果一些可交互的控件被狀態(tài)欄遮擋了怎么辦?這樣這些控件可能就無法點擊和交互了。

CoordinatorLayout為了解決這個問題,會對所有內(nèi)部的子View都進行一定程度的偏移,保證它們不會被狀態(tài)欄遮擋住。

比如我們在CoordinatorLayout當中再添加一個按鈕:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff66ff"
    android:fitsSystemWindows="true">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

運行一下程序,效果如下圖所示:

可以看到,雖然CoordinatorLayout延伸到了狀態(tài)欄區(qū)域,但是它所包含的按鈕是不會進入狀態(tài)欄區(qū)域的,這樣就避免了可交互控件被遮擋的情況出現(xiàn)。

但有的朋友會說,如果有些子控件我就是想要讓它也延伸到狀態(tài)欄區(qū)域內(nèi)呢?比如我在CoordinatorLayout內(nèi)放了一張圖片,按照這個規(guī)則,圖片也是不會顯示在狀態(tài)欄背后的,這樣就達不到想要的效果了。

我們可以來試一下這種場景。比如在CoordinatorLayout中再添加一個ImageView,代碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff66ff"
    android:fitsSystemWindows="true">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/bg"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

現(xiàn)在運行一下程序,效果如下圖所示:

確實,圖片是不會進入狀態(tài)欄區(qū)域的,和我們之前所解釋的理論相符合。

但是很明顯,這并不是我們想要的效果,那么有什么辦法可以解決呢?

這里我們可以借助其他布局來實現(xiàn)。在Google提供的諸多布局當中,并不是只有CoordinatorLayout會處理android:fitsSystemWindows屬性,像CollapsingToolbarLayout、DrawerLayout也是會對這個屬性做處理的。

現(xiàn)在對activity_main.xml進行如下修改:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff66ff"
    android:fitsSystemWindows="true">

    <com.google.android.material.appbar.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:src="@drawable/bg"
            android:fitsSystemWindows="true"
            />

    </com.google.android.material.appbar.CollapsingToolbarLayout>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

可以看到,這里我們在ImageView的外面又包裹了一層CollapsingToolbarLayout,并且給CollapsingToolbarLayout也設置了android:fitsSystemWindows屬性,這樣CollapsingToolbarLayout就可以將內(nèi)容延申到狀態(tài)欄區(qū)域了。

接著我們給ImageView同樣設置了android:fitsSystemWindows屬性,如此一來,就可以讓圖片顯示在狀態(tài)欄的背后了。

重新運行一下程序,效果如下圖所示:

需要注意的是,CollapsingToolbarLayout一定要結合著CoordinatorLayout一起使用,而不能單獨使用。因為CollapsingToolbarLayout只會對內(nèi)部控件的偏移距離做出調(diào)整,而不會像CoordinatorLayout那樣調(diào)用setSystemUiVisibility()函數(shù)來開啟沉浸式狀態(tài)欄。

看到這里,相信大家都已經(jīng)知道應該如何去實現(xiàn)沉浸式狀態(tài)欄效果了。但是可能有的朋友會說,由于項目限制的原因,他們無法使用CoordinatorLayout或CollapsingToolbarLayout,而是只能使用像FrameLayout或LinearLayout這樣的傳統(tǒng)布局,這種情況怎么辦呢?

其實我們知道CoordinatorLayout實現(xiàn)沉浸式狀態(tài)欄的原理之后,自然也就知道如何自己手動實現(xiàn)了,因為本質(zhì)就是調(diào)用setSystemUiVisibility()函數(shù)。

現(xiàn)在我們將activity_main.xml改成用傳統(tǒng)FrameLayout布局的寫法:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff66ff">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/bg"
        />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        />

</FrameLayout>

為了實現(xiàn)沉浸式狀態(tài)欄的效果,我們手動在MainActivity當中調(diào)用setSystemUiVisibility()函數(shù),來將FrameLayout的內(nèi)容延伸到狀態(tài)欄區(qū)域:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        window.statusBarColor = Color.TRANSPARENT
        val frameLayout = findViewById<FrameLayout>(R.id.root_layout)
        frameLayout.systemUiVisibility = (SYSTEM_UI_FLAG_LAYOUT_STABLE
                or SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
    }

}

這里提醒一點,setSystemUiVisibility()函數(shù)其實已經(jīng)被廢棄了。從Android 11開始,Google提供了一個新的API WindowInsetsController來實現(xiàn)同樣的功能,不過本篇文章就不往這方面展開了。

現(xiàn)在重新運行一下程序,效果如下圖所示:

可以看到,現(xiàn)在我們?nèi)匀粚崿F(xiàn)了沉浸式狀態(tài)欄的效果,但問題是FrameLayout中的按鈕也延伸到狀態(tài)欄區(qū)域了,這就是前面所說的可交互控件被狀態(tài)欄遮擋的問題。

出現(xiàn)這個問題的原因也很好理解,因為之前我們是使用的CoordinatorLayout嘛,它已經(jīng)幫我們考慮好到這些事情,自動會將內(nèi)部的控件進行偏移。而現(xiàn)在FrameLayout顯然是不會幫我們做這些事情的,所以我們得想辦法自己解決。

這里其實可以借助setOnApplyWindowInsetsListener()函數(shù)去監(jiān)聽WindowInsets發(fā)生變化的事件,當有監(jiān)聽到發(fā)生變化時,我們可以讀取頂部Insets的大小,然后對控件進行相應距離的偏移。

修改MainActivity中的代碼,如下所示:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        window.statusBarColor = Color.TRANSPARENT
        val frameLayout = findViewById<FrameLayout>(R.id.root_layout)
        frameLayout.systemUiVisibility = (SYSTEM_UI_FLAG_LAYOUT_STABLE
                or SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)

        val button = findViewById<Button>(R.id.button)
        ViewCompat.setOnApplyWindowInsetsListener(button) { view, insets ->
            val params = view.layoutParams as FrameLayout.LayoutParams
            params.topMargin = insets.systemWindowInsetTop
            insets
        }
    }

}

可以看到,當監(jiān)聽到WindowInsets發(fā)生變化時,我們調(diào)用systemWindowInsetTop即可獲取到狀態(tài)欄的高度,然后對不需要延伸到狀態(tài)欄區(qū)域的控件進行相應的偏移即可。

重新運行程序,效果如下圖所示:

好了,到這里為止,我們就將實現(xiàn)沉浸式狀態(tài)欄背后的原理,以及具體的多種實現(xiàn)方式都介紹完了。

這次你學懂a(chǎn)ndroid:fitsSystemWindows屬性了嗎?

到此這篇關于Android 超詳細講解fitsSystemWindows屬性的使用的文章就介紹到這了,更多相關Android fitsSystemWindows屬性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • android AlertDialog多種使用方法詳解

    android AlertDialog多種使用方法詳解

    這篇文章主要為大家詳細介紹了android AlertDialog多種使用方法,包括普通對話框、單選對話框、多選對話框等,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android中Listview點擊item不變顏色及設置listselector 無效的解決方案

    Android中Listview點擊item不變顏色及設置listselector 無效的解決方案

    這篇文章主要介紹了Android中Listview點擊item不變顏色及設置listselector 無效的原因及解決方案,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • Android Walker登錄記住密碼頁面功能實現(xiàn)

    Android Walker登錄記住密碼頁面功能實現(xiàn)

    這篇文章主要為大家詳細介紹了Android Walker登錄記住密碼頁面功能的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • Android實現(xiàn)歡迎頁快速啟動的方法

    Android實現(xiàn)歡迎頁快速啟動的方法

    這篇文章主要給大家介紹了Android實現(xiàn)歡迎頁快速啟動的方法,文中給出了詳細的方法介紹,對大家具有一定的參考價值,需要的朋友們可以一起來學習學習。
    2017-02-02
  • Android自定義ViewFlipper實現(xiàn)滾動效果

    Android自定義ViewFlipper實現(xiàn)滾動效果

    這篇文章主要為大家詳細介紹了Android自定義ViewFlipper實現(xiàn)滾動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Android架構發(fā)展進化詳解

    Android架構發(fā)展進化詳解

    Android系統(tǒng)架構從上到下分為五層:應用層、應用框架層、系統(tǒng)運行庫層、硬件抽象層、Linux內(nèi)核層,Android架構也經(jīng)歷了多次演進,下面我們來詳細了解一下
    2022-08-08
  • 淺談Android Classloader動態(tài)加載分析

    淺談Android Classloader動態(tài)加載分析

    這篇文章主要介紹了淺談Android Classloader動態(tài)加載分析,詳細的介紹了ClassLoader概念、分類,具有一定的參考價值,有興趣的可以了解一下
    2018-03-03
  • Android布局技巧之include、merge與ViewStub標簽的巧用

    Android布局技巧之include、merge與ViewStub標簽的巧用

    Android 官方提供了三個用來優(yōu)化布局的標簽,分別是include、merge與ViewStub,下面這篇文章主要給大家介紹了關于Android布局技巧之include、merge與ViewStub標簽巧用的相關資料,需要的朋友可以參考下
    2018-06-06
  • 文件緩存(配合JSON數(shù)組)

    文件緩存(配合JSON數(shù)組)

    這篇文章主要介紹了文件緩存(配合JSON數(shù)組)的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-11-11
  • Android編程之圖片相關代碼集錦

    Android編程之圖片相關代碼集錦

    這篇文章主要介紹了Android編程之圖片相關代碼集錦,實例總結了大量Android圖片操作相關代碼,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11

最新評論

伊川县| 汽车| 嘉荫县| 湖州市| 吉木萨尔县| 海安县| 武宁县| 措勤县| 甘南县| 梅州市| 紫云| 吴江市| 新津县| 三亚市| 东乡族自治县| 文登市| 雅江县| 屯昌县| 芜湖县| 乐清市| 嵊泗县| 刚察县| 抚州市| 仙游县| 日土县| 潜山县| 乐山市| 黄平县| 讷河市| 全州县| 盐边县| 秦皇岛市| 房产| 清涧县| 郧西县| 石门县| 沭阳县| 新和县| 铜鼓县| 锦屏县| 德阳市|