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

API處理Android安全距離詳情

 更新時間:2022年06月15日 11:29:54   作者:? de得得de?  ?  
這篇文章主要介紹了API處理Android安全距離詳情,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的朋友可以參考一下

前言

在Android屏幕的空間中,大部分的區(qū)域我們都是可以隨意繪制,只有一部分區(qū)域是顯示的固定內容:

  • 狀態(tài)欄
  • 標題欄(ActionBar)
  • 頁面內容(Content)
  • 導航欄

其中標題欄是可選的,除了Material風格的應用應用的并不多,頁面內容就是android.R.id.content是Activity的主要內容。

而我們主要需要討論的就是 狀態(tài)欄和導航欄,因為這兩個區(qū)域在不同設備類型,不同的Android版本和不同的廠商下大小和效果是不同的,等等。這些差異無疑增加了我們做頁面適配的復雜程度,也更容易出現兼容問題。

在2017年下半年iPhone X的發(fā)布,引入了劉海屏設備,導致了藍綠大廠爭相效仿,同時又自成一派,頗有一番百家爭鳴之象。 這也導致了一個新的問題 劉海區(qū)域適配 ,那時候Android才8.1,并沒有API來支持這屏幕上這多出來的一塊區(qū)域,不過好在大部分設備在定制時劉海和狀態(tài)欄高度是一致的

終于在2018年發(fā)布的Android 9中Google正式支持了劉海屏,定制了規(guī)范約束了設備廠商,減輕了劉海屏適配的差異問題,但是根源問題并沒有解決。因為劉海區(qū)域的存在,可能會出現頁面內容被遮擋,比如:啟用頁廣告跳過按鈕被遮擋的問題,導致被應用商店拒掉的風險。

不過好在Android 9中要求劉海設備必須有以下行為:

  • 一條邊緣最多只能包含一個劉海。
  • 一臺設備不能有兩個以上的劉海。
  • 設備的兩條較長邊緣上不能有劉海。
  • 在未設置特殊標志的豎屏模式下,狀態(tài)欄的高度必須與劉海的高度持平。
  • 默認情況下,在全屏模式或橫屏模式下,整個劉海區(qū)域必須顯示黑邊。

劉海高度默認是和狀態(tài)欄高度一致依舊沒有變,所以問題又回到了狀態(tài)欄區(qū)域的處理。

描述

所以肯定有同學說了:直接獲取狀態(tài)欄高度不就可以了適配劉海屏了。像這樣:

val top = context.getStatusBarHeight()
titleBar.setPadding(0, top, 0, 0)

這么說也沒有錯,大部分情況下是沒有問題的。但是既然官方已經適配劉海屏了,也為我們提供了新的API為什么不用呢:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    window.decorView.post {
        val top = window.decorView.rootWindowInsets?.displayCutout?.safeInsetTop ?: 0
        // val bottom = window.decorView.rootWindowInsets?.displayCutout?.safeInsetBottom ?: 0
        titleBar.setPadding(0, top, 0, 0)
    }
}

上面的方案實際上可以獲取上下左右四個方向的安全距離,但大部分情況我們只需要處理頂部就可以了。實際上這已經可以解決我們的問題了,但是還有更好的解決方案方案:

添加依賴:

implementation 'androidx.core:core:1.7.0'

// 老版本也可以,但是getInsets() API 還沒添加
// implementation 'androidx.core:core:1.3.0'

使用ViewCompat工具:

ViewCompat.setOnApplyWindowInsetsListener(titleBar) { view: View, insets: WindowInsetsCompat ->
    //val top = insets.systemWindowInsetTop // 高版本已經過時,可以用下面的api替換
    val stableInsets = insets.getInsets(
    WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
    titleBar.setPadding(0, stableInsets.top, 0, 0)
    return@setOnApplyWindowInsetsListener insets
}

實際上屏幕安全距離,基本上全部圍繞這一個API,Google也推薦我們這么做,在很多系統(tǒng)控件都能看到它的影子,比如:AppBarLayout、DrawerLayout、NavigationBarView等等都有用到,內部都是來處理系統(tǒng)安全距離的。

系統(tǒng)欄適配

上面提到了手機有各種系統(tǒng)欄(狀態(tài)欄、導航欄),如果一個全屏+劉海屏+透明系統(tǒng)欄+屏幕旋轉的頁面處理這些安全距離就更復雜,比如短視頻頁,這里先給大家列幾條可能出現的問題:

  • 沒有導航欄或者可以動態(tài)隱藏導航欄的設備
  • 導航欄不會旋轉的設備(就是導航欄一直在屏幕的一個邊,不會跟隨屏幕旋轉)
  • 導航欄跟隨屏幕旋轉的設備(主要是手勢導航的設備和一些平板上)
  • 劉海在屏幕底部的設備(開發(fā)者選項可以開啟雙劉海模式,設備兩個短邊都有劉海)
  • 底部劉海+導航欄一起顯示的設備
  • ... ...

這些所有的問題通過 ViewCompat.setOnApplyWindowInsetsListener() 來優(yōu)雅處理, 通過 WindowInsetsCompat.getInsets(type) 可以獲取系統(tǒng)的各個欄的大小, 我們也可以同時獲取多個系統(tǒng)欄的高度,各個距離內部會進行累加,返回一個類似Rect的對象,對應屏幕的左上右下需要插入的距離:

val stableInsets = insets.getInsets(
    WindowInsetsCompat.Type.statusBars() or
    WindowInsetsCompat.Type.navigationBars() or
    WindowInsetsCompat.Type.displayCutout())

然后在對不同位置的控件添加對應的邊距。除了上面提到的三種類型的安全距離,還有一些其他的類型,有興趣的可以自己了解。

其他適配

ViewCompat.setOnApplyWindowInsetsListener()能解決大部分安全距離的問題,但是有一點它是處理不了的,就是 屏幕圓角,這些安全距離的計算是不處理屏幕圓角的,所以如果有圓角要處理那我們就要另辟蹊徑了。

好在Android 12中官方添加了對圓角的支持:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    val roundedCorner = insets.toWindowInsets()
        ?.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT)
    roundedCorner?.center
}

我用了Pixel4真機發(fā)現能獲取到數據,但是模擬器獲取不到。

除了圓角支持,還有對隱私指示器提供了支持:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    val rect = insets.toWindowInsets()?.privacyIndicatorBounds
    // 頁面控件需要避開這個區(qū)域,不然可能會被遮擋
}

隱私指示器的范圍,主要是 攝像頭和麥克風 使用中狀態(tài)的指示器邊界,如果是錄制直播或者相機的頁面需要處理這個區(qū)域。

除了圓角以外,好像沒有找到官方對打孔屏的支持,可能后面會加入對打孔屏的支持吧。

到此這篇關于API處理Android安全距離詳情的文章就介紹到這了,更多相關 Android安全距離內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

横山县| 江永县| 通城县| 广丰县| 广汉市| 舟山市| 嘉黎县| 米泉市| 淅川县| 松阳县| 宜章县| 开阳县| 洪湖市| 贵定县| 吉首市| 伊金霍洛旗| 安吉县| 漾濞| 乌拉特前旗| 东方市| 江陵县| 河南省| 赤壁市| 虞城县| 阳泉市| 志丹县| 江安县| 平和县| 康保县| 安阳市| 和硕县| 灵武市| 乌恰县| 阿城市| 中宁县| 天水市| 威远县| 宜丰县| 裕民县| 周至县| 甘南县|