在 Android 中啟動動畫時,螢幕通常會提升至最高更新率,確保提供流暢的體驗。對於進度列和音訊視覺化工具等小型動畫,不需要這麼高的更新率,反而會導致耗電量增加。
自 Android 15 起,啟用 ARR 功能的裝置可從兩方面減少高更新率的駐留時間:
- 透過全新的平台畫面更新率管理最佳化功能,應用程式預設可以較低的畫面更新率算繪,並僅在必要時提升至高畫面更新率。
- 螢幕刷新率會動態配合內容的算繪率,不會出現延遲。
大多數應用程式都應能從 ARR 受益,不需進行任何修改,但您也可以視需要覆寫預設影格速率行為。
本頁面說明下列事項:
- 每個 View 的影格速率決定方式。
- ARR 決定影格速率的一般政策。
- 如何手動覆寫預設影格速率行為。
View 投票機制
在 Android 的 View 系統中,UI 階層中的每個 View 都可以表示偏好的影格速率。系統會收集並合併這些偏好設定,為每個影格決定最終影格速率。這是透過投票機制達成,每個 View 會根據自己的影格速率屬性 (可以是類別或特定速率) 投票。檢視區塊通常會在繪製或更新時投票。這些票數會合併,以決定最終影格速率,然後傳送至較低層級的圖層,做為算繪提示。
目前大多數 Views 預設為「一般」影格速率,通常設為 60 Hz。如要提高影格速率,可以使用特定 API 自訂偏好設定,系統通常會選取最高影格速率。如要進一步瞭解如何使用這些 API,請參閱「設定影格速率或類別」一節。如要瞭解有關影格速率的一般政策,請參閱「一般 ARR 政策」一節。
影格速率類別
在 View
類別中,有不同幀率類別可用於投票。各類別的說明如下:
REQUESTED_FRAME_RATE_CATEGORY_DEFAULT
:這個值可以設為還原預設行為,表示這個 View 沒有影格速率的資料。REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE
:View 不會明確影響影格速率。也就是說,即使 View 處於啟用狀態,架構也不會在判斷影格速率時考量該 ViewREQUESTED_FRAME_RATE_CATEGORY_NORMAL
:表示適合動畫的中等畫面更新率,這類動畫不需要更高的畫面更新率,或高流暢度不會帶來好處。通常為 60 Hz 或接近 60 Hz。REQUESTED_FRAME_RATE_CATEGORY_HIGH
:表示適合高影格速率動畫的影格速率,可提升流暢度,但可能會增加耗電量。
只有在需要重新繪製時,View 才會投票。最終影格速率取決於最高票數。舉例來說,如果所有票數都投給「Normal」,則會選取「Normal」。如果同時出現「正常」和「高」票數,系統會選擇「高」。
畫面更新率
除了影格速率類別,View 也可以指定偏好的影格速率,例如 30、60 或 120 Hz。如果有多個影格速率投票,最終影格速率會依下列規則決定:
- 互為倍數:如果投票的影格速率互為倍數,系統會選擇最高值。舉例來說,如果投票結果為 30 Hz 和 90 Hz,則最終幀率會選取 90 Hz。
- 彼此不是倍數:
- 如果任何一項投票結果超過 60 Hz,就會計為「高」票。
- 如果所有票數都是 60 Hz 以下,則視為「正常」票數。
此外,如果同時有影格速率值和影格速率類別,通常會以較高的值決定最終顯示速率。舉例來說,如果投票結果是 60 Hz 和「高」的組合,或是 120 Hz 和「正常」的組合,通常會將算繪率設為 120 Hz。
除了應用程式的投票結果,同一影格內的不同元件也可能會將其他提示傳送至較低層級的層。其中許多項目都可能來自系統 UI 元件,例如通知匣、狀態列、導覽列等。最終影格速率值會根據多個元件的投票結果決定。
設定影格速率或類別
在某些情況下,您可能會偏好 View 的特定畫面更新率。舉例來說,如果動畫顯示不流暢,您可以將 View 的偏好影格速率設為「高」,藉此提高影格速率。此外,如果影片有緩慢或靜態的動畫 (通常以 24 或 30 Hz 播放),您可能會希望動畫以低於「正常」的速率播放,以減少耗電量。
您可以使用 setRequestedFrameRate()
和 getRequestedFrameRate()
API,指定特定 View 的偏好影格速率或類別。
Kotlin
// Set the preferred frame rate category to a View // set the frame rate category to NORMAL view.requestedFrameRate = View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL // set the frame rate category to HIGH view.requestedFrameRate = View.REQUESTED_FRAME_RATE_CATEGORY_HIGH // reset the frame rate category view.requestedFrameRate = View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT // Set the preferred frame rate to a View // set the frame rate to 30 view.requestedFrameRate = 30f // set the frame rate to 60 view.requestedFrameRate = 60f // set the frame rate to 120 view.requestedFrameRate = 120f
Java
// Set the preferred frame rate category to a View // set the frame rate category to NORMAL view.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL); // set the frame rate category to HIGH view.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_HIGH); // reset the frame rate category view.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT); // Set the preferred frame rate to a View // set the frame rate to 30 view.setRequestedFrameRate(30); // set the frame rate to 60 view.setRequestedFrameRate(60); // set the frame rate to 120 view.setRequestedFrameRate(120);
如需使用範例,請參閱 TextureView
。
一般 ARR 政策
在前一節中,我們討論過大多數動畫預設會以 60 Hz 顯示,因為每個 View 都將「Normal」設為偏好的影格速率。不過,為確保動畫更流暢,影格速率有時會提高至「高」。
一般 ARR 政策如下:
- 觸控加速:偵測到觸控事件 (
MotionEvent.ACTION_DOWN
) 時,系統會在放開觸控後的一段時間內,將螢幕更新率提升至「高」,以維持回應速度。 - 滑動手勢:滑動手勢的處理方式不同,重新整理頻率會隨著滑動速度減緩而逐漸降低。詳情請參閱「捲動改善」一節。
- 應用程式啟動和視窗轉場:在應用程式啟動、視窗初始化和視窗轉場期間,系統也會在一段時間內提高螢幕更新率,確保視覺體驗流暢。
- 動畫:如果動畫涉及移動或大小變化,當 View 的位置或大小變更時,系統會自動提高重新整理率,以提升流暢度。
SurfaceView
和TextureView
:系統會遵守並套用為TextureView
和SurfaceView
明確設定的畫面更新率。
啟用及停用觸控增強功能
您可以在 Window
層級啟用和/或停用觸控加速功能。根據預設,使用者觸碰螢幕並將手指移開時,算繪速率會暫時提高。setFrameRateBoostOnTouchEnabled()
和 getFrameRateBoostOnTouchEnabled()
API 可讓您在觸控特定 Window
時,避免算繪速率增加。
Kotlin
// disable touch boost on a Window window.isFrameRateBoostOnTouchEnabled = false // enable touch boost on a Window window.isFrameRateBoostOnTouchEnabled = true // check if touch boost is enabled on a Window val isTouchBoostEnabled = window.isFrameRateBoostOnTouchEnabled
Java
// disable touch boost on a Window window.setFrameRateBoostOnTouchEnabled(false) // enable touch boost on a Window window.setFrameRateBoostOnTouchEnabled(true) // check if touch boost is enabled on a Window window.getFrameRateBoostOnTouchEnabled()
捲動功能改善
動態最佳化影格率的主要用途之一,是提升捲動 (滑動) 體驗。許多應用程式都非常依賴使用者向上滑動來查看新內容。ARR 捲動強化功能會隨著甩動手勢減緩,動態調整重新整理頻率,逐步降低影格速率。這樣一來,就能在維持流暢捲動的同時,更有效率地算繪畫面。
這項改善功能特別適用於可捲動的 UI 元件,包括 ScrollView
、ListView
和 GridView
,可能不適用於所有自訂實作項目。
ARR 捲動功能適用於 RecyclerView
和 NestedScrollView
。如要在應用程式中啟用這項功能,請升級至最新版本的 AndroidX.recyclerview
和 AndroidX.core
。詳情請參閱下表。
媒體庫 |
版本 |
|
1.4.0 |
|
1.15.0 |
設定速度資訊
如果您有自訂可捲動元件,並想善用捲動功能,請在流暢捲動或快速滑過時,對每個影格呼叫 setFrameContentVelocity()
。請參考以下程式碼片段:
Kotlin
// set the velocity to a View (1000 pixels/Second) view.frameContentVelocity = 1000f // get the velocity of a View val velocity = view.frameContentVelocity
Java
// set the velocity to a View view.setFrameContentVelocity(velocity); // get the velocity of a View final float velocity = view.getFrameContentVelocity()
如需更多範例,請參閱 RecyclerView
和 ScrollView
。如要正確設定速度,請手動計算內容速度 (每秒像素數),前提是無法從 Scroller
或 OverScroller
取得必要資訊。
請注意,如果對不可捲動的元件呼叫 setFrameContentVelocity()
和 getFrameContentVelocity()
,這些呼叫就不會產生任何作用,因為系統會根據目前的政策,在移動時自動觸發更高的影格速率。
速度資訊對於調整算繪率至關重要。舉例來說,請考慮輕拂手勢。一開始,甩動速度可能很快,因此需要較高的算繪速率,才能確保流暢度。隨著手勢進展,速度會降低,因此可降低算繪率。
啟用及停用 ARR
ARR 預設為啟用,可提升電源效率。雖然可以停用這項功能,但我們不建議這麼做,因為這樣應用程式會消耗更多電量。只有在遇到嚴重影響使用者體驗的問題時,才考慮停用這項功能。
如要啟用或停用 ARR,請在 Window
上使用 setFrameRatePowerSavingsBalanced()
API,或透過 styles.xml
檔案使用 isFrameRatePowerSavingsBalanced()
API。
下列程式碼片段說明如何在 Window
上啟用或停用 ARR:
Kotlin
// disable ARR on a Window window.isFrameRatePowerSavingsBalanced = false // enable ARR on a Window window.isFrameRatePowerSavingsBalanced = true // check if ARR is enabled on a Window val isAdaptiveRefreshRateEnabled = window.isFrameRatePowerSavingsBalanced
Java
// disable ARR on a Window window.setFrameRatePowerSavingsBalanced(false) // enable ARR on a Window window.setFrameRatePowerSavingsBalanced(true) // check if ARR is enabled on a Window window.isFrameRatePowerSavingsBalanced()
如要透過 styles.xml
檔案停用 ARR,請將下列項目新增至 res/values/styles.xml
中的樣式:
<style name="frameRatePowerSavingsBalancedDisabled">
<item name="android:windowIsFrameRatePowerSavingsBalanced">false</item>
</style>
Compose 的 ARR
Compose 1.9 也支援自動調整刷新率。
在 View 系統中,您可以使用 setRequestedFrameRate()
方法,為 View 要求特定影格速率。在 Compose 中,您可以使用新的修飾符指定可組合項的影格速率。這個修飾符函式與 setRequestedFrameRate()
類似,可接受正影格速率值 (以 Hz 為單位) 或預先定義的影格速率類別 FrameRateCategory
。
API 的簽章如下:
Modifier.preferredFrameRate(frameRate: Float)
Modifier.preferredFrameRate(frameRateCategory: FrameRateCategory)
在下列程式碼片段中,新的影格速率修飾符 (Modifier.requestedFrameRate(120f))
會套用至 Text
可組合函式。這個修飾符會導致 Text
可組合函式在繪製或製作動畫時 (例如不透明度變化),要求偏好的影格速率為 120:
var targetAlpha by remember { mutableFloatStateOf(1f) }
val alpha by
animateFloatAsState(
targetValue = targetAlpha,
animationSpec = tween(durationMillis = 1000)
)
Button(
onClick = { targetAlpha = if (targetAlpha == 1f) 0.2f else 1f },
modifier =
Modifier.background(LocalContentColor.current.copy(alpha = alpha))
) {
Text(
text = "Click",
color = LocalContentColor.current.copy(alpha = alpha),
modifier = Modifier.preferredFrameRate(120f)
// You can also pass frame rate category such as FrameRateCategory.High to increase the frame rate
)
}
接著,系統會收集並整合所有可組合項目的偏好影格速率,以決定每個影格的最終影格速率。詳情請參閱 SetFrameRateSample
和 SetFrameRateCategorySample
。