Android 11 中的新功能之一是可以讓應用在對于屏幕上的軟鍵盤打開和關閉的過程創(chuàng)建無縫過渡的動畫效果,這一功能源自 Android 11 中對 windowInsets API 的大量改進。

在 Android 11 上有兩個針對該功能的例子——這個功能已經被集成到 Google Search 應用和 Messages 應用中了:

兩個 Android 11 中軟鍵盤動畫效果的示例: Google Search 應用 (左),Messages (右)

讓我們來看看如何在您的應用中添加這種用戶體驗。總共分為三步:

  • 首先,我們需要做到 "邊到邊" (edge-to-edge);
  • 第二步,應用需要針對邊襯區(qū)動畫做出反應;
  • 最后第三步就是應用在恰當?shù)膱鼍爸锌刂撇⑹褂眠呉r區(qū)動畫。

上面的每一步都環(huán)環(huán)相扣,所以我們會在不同的文章中分別介紹。在這個系列的第一部中,我們會介紹如何實現(xiàn)邊到邊,以及 Android 11 中相關 API 的改動。

實現(xiàn)邊到邊 (edge-to-edge)

去年我們介紹了一個關于實現(xiàn) "邊到邊" 的概念,這個方法可以讓應用深度利用 Android 10 的手勢導航: 開啟全面屏體驗 | 手勢導航 (一)。

簡單回顧一下,實現(xiàn) "邊到邊" 會讓您的應用渲染在系統(tǒng)狀態(tài)欄的后面,如上圖所示。

引用去年我自己的話:

實現(xiàn)從邊到邊的全面屏體驗后,系統(tǒng)欄會覆蓋在應用內容前方。應用也得以通過更大幅面的內容為用戶帶來更具有沖擊力的體驗。

實現(xiàn)邊到邊跟軟鍵盤有什么關系?

其實,實現(xiàn)邊到邊不單單只是在狀態(tài)欄和導航欄之后渲染。應用本身需要開始負責處理那些跟應用重疊的系統(tǒng) UI 的部分。

正如我們前面提到的,兩個最直觀的例子是狀態(tài)欄和導航欄。除此之外還有軟鍵盤,有時候也叫 IME (輸入法編輯器),這是另外一個我們需要了解的系統(tǒng) UI 。

應用如何實現(xiàn)邊到邊?

如果我們回想 去年的介紹,實現(xiàn)邊到邊可以分為三步:

  • 改變系統(tǒng)欄的顏色
  • 設置全屏布局
  • 處理視覺沖突

我們會跳過第一步,因為從去年至今這個部分沒有改動。教程中的第二步和第三步有一些針對 Android 11 的改動,讓我們來看一下。

#2: 設置全屏布局

在以往的第二步中,應用需要使用 systemUiVisibility API 以及一些參數(shù)來設置全屏布局:

view.systemUiVisibility?=? ????//?通知系統(tǒng),視窗希望在極端的情況下該如何布局內容。查看文檔來獲取更具體的信息。 ????View.SYSTEM_UI_FLAG_LAYOUT_stable?or ????//?通知系統(tǒng),視窗希望在導航欄被隱藏的情況下如何布局內容。 ????View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

如果您的項目設置編譯的目標 SDK 版本已經升級為 30 并且使用這個 API ,您會發(fā)現(xiàn)這些 API 都已經被標示為棄用了。

它們已經被 Window 的一個叫作 setDecorFitsSystemWindows() 的函數(shù)替代了:

//?通知視窗,我們(應用)會處理任何系統(tǒng)視窗(而不是?decor) window.setDecorFitsSystemWindows(false) //?或者您可以使用?AndroidX?v1.5.0-alpha02?中的?WindowCompat WindowCom(window,?false)

取代那些參數(shù)的是一個布爾值 false,它的意思是應用會處理任何系統(tǒng)窗口的適配 (換句話說就是全屏)。

在 WindowCompat 中,我們還有一個 Jetpack 版本的該函數(shù),androidx.core 庫的 v1.5.0-alpha02 版本里也包含了這個函數(shù)。

以上就是第二步的改動。

#3: 處理視覺沖突

現(xiàn)在讓我們來看一下第三步: 避免與系統(tǒng) UI 產生重疊,也可以說是使用視窗邊襯區(qū)來決定如何移動應用的內容來避免與系統(tǒng) UI 的沖突。在 Android 系統(tǒng)中,邊襯區(qū)可以通過 WindowInsets 類和 AndroidX 中的 WindowInsetsCompat 來訪問。

如果我們查看 API 30 以前版本的 WindowInsets,最常用的邊襯區(qū)類型是系統(tǒng)視窗邊襯區(qū)。這些邊襯區(qū)包括了狀態(tài)欄、導航欄以及打開時的軟鍵盤。

為了使用 WindowInsets,您通常需要在一個視圖上添加 OnApplyWindowInsetsListener,并且在這個函數(shù)中處理傳進來的邊襯區(qū):

ViewCom(view)?{?v,?insets?-> ????v.updatePadding(bottom?=?in) ????//?返回邊襯區(qū),這樣它們才能夠繼續(xù)在視圖樹中繼續(xù)傳遞下去 ????insets }

在這個例子中,我們獲取到 系統(tǒng)視窗邊襯區(qū),然后更新視圖的內邊距,這是一個常見的應用場景。

還有一些其他類型的邊襯區(qū),比如 Android 10 最近新增的手勢邊襯區(qū):

ViewCom(v)?{?view,?windowInsets?-> ????val?sysWindow?=?windowIn ????val?stable?=?windowIn ????val?systemGestures?=?windowIn ????val?tappableElement?=?windowIn }

和 systemUiVisibility API 類似,許多 WindowInsets API 已經被棄用了,取而代之的一些新函數(shù)來查詢不同類型的邊襯區(qū):

  • getInsets(type: Int) 會返回指定類型的可見邊襯區(qū)。
  • getInsetsIgnoringVisibility(type: Int) 會返回所有邊襯區(qū),無論它們是否可見。
  • isVisible(type: Int) 會返回 true 如果指定的類型是可見的。

我們剛剛多次提到 "類型",它們在 WindowIn 類中被定義為函數(shù),每個函數(shù)都會返回一個整數(shù)標示。我們稍后還會展示如何使用 OR 位運算來查詢結合到一起的類型。

所有這些 API 都已經被添加到 AndroidX Core 中的 WindowInsetsCompat,并且向前兼容到 API 14 (請查看 發(fā)行注記 來獲取更多信息)。

再來看如果我們用新的 API 來更新之前的示例,它們就變成:

ViewCom(...)?{?view,?insets?-> -????val?sysWindow?=?in +????val?sysWindow?=?in()?or?Ty()) -????val?stable?=?in +????val?stable?=?inIgnoringVisibility()) -????val?systemGestures?=?in +????val?systemGestures?=?in()) -????val?tappableElement?=?in +????val?tappableElement?=?in()) }

軟鍵盤類型 ??

這會兒那些敏銳的 可能已經開始盯著這個類型列表,尤其是其中的 軟鍵盤類型。

在姍姍來遲了十年后,我們終于可以回答這個關于如何查看軟鍵盤可見性的 StackOverflow 問題。

  • 在 Android 中如何查看軟鍵盤的可見性?

為了獲取當前軟鍵盤的可見性,我們可以取得根視窗的邊襯區(qū),然后執(zhí)行 isVisible() 函數(shù)并傳入 IME 類型。

同樣地,如果我們想查出高度,我們也可以通過相同的方法實現(xiàn):

val?insets?=?ViewCom(view) val?imeVisible?=?in(Ty()) val?imeHeight?=?in(Ty()).bottom

如果我們需要監(jiān)聽軟鍵盤的改變,我們可以照常使用 OnApplyWindowInsetsListener,并且使用同樣的函數(shù):

ViewCom(view)?{?v,?insets?-> ????val?imeVisible?=?in(Ty()) ????val?imeHeight?=?in(Ty()).bottom }

隱藏或顯示軟鍵盤

既然我們正在回答 StackOverflow 上的問題,來看一下這個 11 年前關于如何關閉軟鍵盤的問題。

  • 如何關閉/隱藏 Android 軟鍵盤?

這一次我們要介紹 Android 11 的一個新 API,它叫 WindowInsetsController。

應用可以從任何視圖獲得一個控制器,然后我們就可以通過傳入 IME 類型,并執(zhí)行 show() 或者 hide() 函數(shù)來實現(xiàn)顯示或隱藏軟鍵盤:

val?controller?=?view.windowInsetsController //?顯示軟鍵盤(?IME?) con(Ty()) //?隱藏軟鍵盤 con(Ty())

然而,這個控制器不單單能控制隱藏和顯示軟鍵盤...

WindowInsetsController

之前我們提到過,有一些 View.SYSTEM_UI_* 標志已經在 Android 11 中被棄用,并且被新的 API 代替。還有一些 View.SYSTEM_UI 標志本來是被用來改變系統(tǒng) UI 的外觀和可見性的,包括:

  • View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
  • View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
  • View.SYSTEM_UI_FLAG_LAYOUT_STABLE
  • View.SYSTEM_UI_FLAG_LOW_PROFILE
  • View.SYSTEM_UI_FLAG_FULLSCREEN
  • View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
  • View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
  • View.SYSTEM_UI_FLAG_IMMERSIVE
  • View.SYSTEM_UI_FLAG_VISIBLE
  • View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
  • View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR

和之前的標志類似,這些也都在 API 30 中被棄用,并被 WindowInsetsController 中的 API 代替。

接下來我們會通過幾個常見的應用場景來介紹如何更新這些標志,而不是一一介紹所有這些標志的改變:

沉浸模式

如圖所示,這個繪圖應用隱藏了系統(tǒng) UI 來讓繪圖區(qū)域最大化:

Markers 應用,展示隱藏系統(tǒng) UI

為了實現(xiàn)這個效果,我們像以前一樣使用 WindowInsetsController 來執(zhí)行 hide() 和 show() 函數(shù),但是這一次我們要傳入系統(tǒng)欄類型:

val?controller?=?view.windowInsetsController //?當我們想隱藏系統(tǒng)欄 con()) //?當我們想顯示系統(tǒng)欄 con())

應用使用 沉浸模式 來讓用戶在系統(tǒng)欄隱藏的時候可以通過滑動來召回系統(tǒng)欄。為了實現(xiàn)這個效果,我們使用 WindowInsetsController 并且改變 setSystemBarsBehavior() 為 BEHAVIOR_SHOW_BARS_BY_SWIPE:

val?controller?=?view.windowInsetsController //?現(xiàn)在開始沉浸式.. con( ????WindowIn ) //?當我們想要隱藏系統(tǒng)欄 con())

類似地,如果您之前使用吸附式的 沉浸模式,這個現(xiàn)在也可以用 BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE 來實現(xiàn):

val?controller?=?view.windowInsetsController //?現(xiàn)在開始吸附式沉浸式體驗?... con( ????BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE ) //?當我們想要隱藏系統(tǒng)欄 con())

狀態(tài)欄內容的顏色

接下來的這個應用場景是圍繞著狀態(tài)欄內容的顏色。您會看到如下兩個應用:

兩個應用,左邊的使用的是深色狀態(tài)欄背景,右邊的使用的是淺色背景

左邊的應用使用的是一個深色的狀態(tài)欄背景,而它的內容用的是淺色,比如時間和圖標。可如果我們想實現(xiàn)一個淺色的狀態(tài)欄背景并且搭配深色的內容,像右邊顯示的一樣,我們也可以使用 WindowInsetsController。

要實現(xiàn)這個效果,我們可以使用 setSystemBarsAppearance() 函數(shù),傳入 APPEARANCE_LIGHT_STATUS_BARS 值:

val?controller?=?view.windowInsetsController //?啟用淺色狀態(tài)欄內容 con( ????APPEARANCE_LIGHT_STATUS_BARS,?//?value ????APPEARANCE_LIGHT_STATUS_BARS?//?mask )

但如果您想設置一個深色的狀態(tài)欄,可以傳入 0,而不是清除那個值。

注意: 您也可以在主題中通過設置 android:windowLightStatusBar 實現(xiàn)上述效果。在您知道這個值不會變動的情況下,這個方式可能更好。

APPEARANCE_LIGHT_NAVIGATION_BARS 標志可以給導航欄提供類似的功能。

AndroidX 中的 WindowInsetsController?

可惜的是這個 API 的 Jetpack 版本還沒有上線,而我們正在加緊準備,敬請關注。

實現(xiàn)邊到邊: ??

我們的第一步完成了。在本系列下一篇文章中,我們會研究第二步: 應用對于邊襯區(qū)的響應式動畫。敬請關注。

1.《如何打開軟鍵盤,電腦鍵盤壞了怎么打開虛擬鍵盤?》援引自互聯(lián)網,旨在傳遞更多網絡信息知識,僅代表作者本人觀點,與本網站無關,侵刪請聯(lián)系頁腳下方聯(lián)系方式。

2.《如何打開軟鍵盤,電腦鍵盤壞了怎么打開虛擬鍵盤?》僅供讀者參考,本網站未對該內容進行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。

3.文章轉載時請保留本站內容來源地址,http://f99ss.com/keji/3210711.html