為了針對使用
Modifier.clickable
,我們推出了新的 API。這些 API
高效率的 Indication
實作方式,例如漣漪效果。
「androidx.compose.foundation:foundation:1.7.0+
」和
androidx.compose.material:material-ripple:1.7.0+
包含下列 API
變更:
已淘汰 |
取代選項 |
---|---|
|
|
|
請改為在 Material 程式庫中提供新的 注意:在本文中,「Material Library」涵蓋 |
|
:
|
本頁面說明行為變更的影響,以及遷移至 BigQuery 的操作說明。 新的 API
行為變更
下列程式庫版本包含漣漪效果變更:
androidx.compose.material:material:1.7.0+
androidx.compose.material3:material3:1.3.0+
androidx.wear.compose:compose-material:1.4.0+
這些 Material 程式庫版本已不再使用 rememberRipple()
;
就會使用新的分享關係圖 API因此,它們不會查詢 LocalRippleTheme
。
因此,如果您在應用程式中設定 LocalRippleTheme
,Material
元件不會使用這些值。
下一節將說明如何暫時改回使用舊行為
而不進行遷移不過,建議您改用新的 API。適用對象
遷移操作說明,請參閱從 rememberRipple
遷移至 ripple
以及後續章節
升級不遷移的 Material 程式庫版本
如要解除封鎖升級程式庫版本,您可以使用
要設定 LocalUseFallbackRippleImplementation CompositionLocal
個 API
要改回使用舊行為的 Material 元件:
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
請務必提供 MaterialTheme
「外部」,這樣舊的分享關係圖才能正常運作
透過 LocalIndication
提供
以下各節說明如何遷移至新版 API。
從「rememberRipple
」遷移至「ripple
」
使用 Material 程式庫
如果您使用 Material 程式庫,請直接將 rememberRipple()
替換為
呼叫 ripple()
的對應程式庫。這個 API
透過 Material Design 主題 API 衍生的值然後,將傳回的
新增至 Modifier.clickable
和/或其他元件
舉例來說,下列程式碼片段使用已淘汰的 API:
Box( Modifier.clickable( onClick = {}, interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple() ) ) { // ... }
建議您將上述程式碼片段修改為:
@Composable private fun RippleExample() { Box( Modifier.clickable( onClick = {}, interactionSource = remember { MutableInteractionSource() }, indication = ripple() ) ) { // ... } }
請注意,ripple()
不再是可組合函式,不一定
可以記住。此類別也可重複用於多個元件,類似於
因此,請考慮將建立關係圖擷取為頂層值,
儲存分配作業
導入自訂設計系統
如果您要採用自己的設計系統,而您先前是使用
rememberRipple()
以及自訂 RippleTheme
來設定漣漪效果,
建議您改為提供自己的分享關係圖 API,以便委派給漣漪效果節點
在 material-ripple
中公開的 API。然後,您的元件就能使用自己的分享關係圖
會直接消耗主題值。詳情請參閱遷移
寄件者RippleTheme
。
從「RippleTheme
」遷移
暫時停用行為變更
Material 程式庫具有臨時的 CompositionLocal
。
LocalUseFallbackRippleImplementation
,可用於設定
改回使用 rememberRipple
的 Material 元件。如此一來
「rememberRipple
」繼續查詢「LocalRippleTheme
」。
下列程式碼片段說明如何使用
LocalUseFallbackRippleImplementation CompositionLocal
API:
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
如果您使用以 Material 為基礎的自訂應用程式主題,可以 為應用程式主題提供本機組合:
@OptIn(ExperimentalMaterialApi::class) @Composable fun MyAppTheme(content: @Composable () -> Unit) { CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme(content = content) } }
詳情請參閱在以下情況中升級 Material Design 程式庫版本: 遷移一節。
使用 RippleTheme
停用特定元件的漣漪效果
material
和 material3
程式庫會公開 RippleConfiguration
和
LocalRippleConfiguration
,可讓您設定
子樹狀結構中的漣漪。請注意,RippleConfiguration
和
LocalRippleConfiguration
屬於實驗功能,僅適用於個別元件
。全域/主題自訂功能不適用於以下項目
API;請參閱使用 RippleTheme
全面變更
應用程式。
舉例來說,下列程式碼片段使用已淘汰的 API:
private object DisabledRippleTheme : RippleTheme { @Composable override fun defaultColor(): Color = Color.Transparent @Composable override fun rippleAlpha(): RippleAlpha = RippleAlpha(0f, 0f, 0f, 0f) } // ... CompositionLocalProvider(LocalRippleTheme provides DisabledRippleTheme) { Button { // ... } }
建議您將上述程式碼片段修改為:
CompositionLocalProvider(LocalRippleConfiguration provides null) { Button { // ... } }
使用 RippleTheme
變更特定元件的漣漪效果顏色/Alpha 版
如上一節所述,RippleConfiguration
以及
LocalRippleConfiguration
是實驗性 API,僅適用於
針對個別元件自訂
舉例來說,下列程式碼片段使用已淘汰的 API:
private object DisabledRippleThemeColorAndAlpha : RippleTheme { @Composable override fun defaultColor(): Color = Color.Red @Composable override fun rippleAlpha(): RippleAlpha = MyRippleAlpha } // ... CompositionLocalProvider(LocalRippleTheme provides DisabledRippleThemeColorAndAlpha) { Button { // ... } }
建議您將上述程式碼片段修改為:
@OptIn(ExperimentalMaterialApi::class) private val MyRippleConfiguration = RippleConfiguration(color = Color.Red, rippleAlpha = MyRippleAlpha) // ... CompositionLocalProvider(LocalRippleConfiguration provides MyRippleConfiguration) { Button { // ... } }
使用 RippleTheme
全面變更應用程式的所有漣漪效果
您之前可以使用 LocalRippleTheme
,在
以及能套用至整個主題層級的機構基本上,這是一種整合
設計系統組合本機值和漣漪效果。與其顯示
主題設定基元,material-ripple
現在會顯示 createRippleModifierNode()
函式。這個函式讓設計系統程式庫可建立更高的
排序 wrapper
實作,然後查詢主題值,然後委派
才會對由這個函式建立的節點使用漣漪效果。
這樣一來,設計系統就能直接查詢所需內容,
使用者可自行設定的主題設定層
而不需遵循
material-ripple
層的作用範圍這項變更也帶來
明確地呈現漣漪效果的主題/規格,因為
則會定義該合約,而不是隱含
如需相關指南,請參閱 Material Design 中的 漣漪 API 實作 程式庫,並視需要取代對 Material 組合本機元件的呼叫 您打造自己的設計系統
從「Indication
」遷移至「IndicationNodeFactory
」
繞過Indication
如果您只是建立要傳遞的 Indication
(例如建立
用來傳遞到 Modifier.clickable
或 Modifier.indication
的漣漪效果,
不需要進行任何變更IndicationNodeFactory
沿用自 Indication
,
確保所有內容都會繼續編譯和運作
正在建立「Indication
」
如果您要建立自己的 Indication
實作項目,則遷移作業
通常用起來最簡單舉例來說,假設 Indication
會套用
縮放時效果:
object ScaleIndication : Indication { @Composable override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { // key the remember against interactionSource, so if it changes we create a new instance val instance = remember(interactionSource) { ScaleIndicationInstance() } LaunchedEffect(interactionSource) { interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> instance.animateToPressed(interaction.pressPosition) is PressInteraction.Release -> instance.animateToResting() is PressInteraction.Cancel -> instance.animateToResting() } } } return instance } } private class ScaleIndicationInstance : IndicationInstance { var currentPressPosition: Offset = Offset.Zero val animatedScalePercent = Animatable(1f) suspend fun animateToPressed(pressPosition: Offset) { currentPressPosition = pressPosition animatedScalePercent.animateTo(0.9f, spring()) } suspend fun animateToResting() { animatedScalePercent.animateTo(1f, spring()) } override fun ContentDrawScope.drawIndication() { scale( scale = animatedScalePercent.value, pivot = currentPressPosition ) { this@drawIndication.drawContent() } } }
您可以透過兩個步驟來遷移這項設定:
將
ScaleIndicationInstance
遷移至DrawModifierNode
。API 介面DrawModifierNode
與IndicationInstance
非常相似,其會顯示ContentDrawScope#draw()
函式,其功能等同於IndicationInstance#drawContent()
。您必須變更函式,然後 請直接在節點內實作collectLatest
邏輯,不要使用Indication
。舉例來說,下列程式碼片段使用已淘汰的 API:
private class ScaleIndicationInstance : IndicationInstance { var currentPressPosition: Offset = Offset.Zero val animatedScalePercent = Animatable(1f) suspend fun animateToPressed(pressPosition: Offset) { currentPressPosition = pressPosition animatedScalePercent.animateTo(0.9f, spring()) } suspend fun animateToResting() { animatedScalePercent.animateTo(1f, spring()) } override fun ContentDrawScope.drawIndication() { scale( scale = animatedScalePercent.value, pivot = currentPressPosition ) { this@drawIndication.drawContent() } } }
建議您將上述程式碼片段修改為:
private class ScaleIndicationNode( private val interactionSource: InteractionSource ) : Modifier.Node(), DrawModifierNode { var currentPressPosition: Offset = Offset.Zero val animatedScalePercent = Animatable(1f) private suspend fun animateToPressed(pressPosition: Offset) { currentPressPosition = pressPosition animatedScalePercent.animateTo(0.9f, spring()) } private suspend fun animateToResting() { animatedScalePercent.animateTo(1f, spring()) } override fun onAttach() { coroutineScope.launch { interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> animateToPressed(interaction.pressPosition) is PressInteraction.Release -> animateToResting() is PressInteraction.Cancel -> animateToResting() } } } } override fun ContentDrawScope.draw() { scale( scale = animatedScalePercent.value, pivot = currentPressPosition ) { this@draw.drawContent() } } }
遷移
ScaleIndication
以實作IndicationNodeFactory
。由於 集合邏輯現已移至節點,這是非常簡單的工廠 物件,這個物件唯一的責任是建立節點執行個體。舉例來說,下列程式碼片段使用已淘汰的 API:
object ScaleIndication : Indication { @Composable override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { // key the remember against interactionSource, so if it changes we create a new instance val instance = remember(interactionSource) { ScaleIndicationInstance() } LaunchedEffect(interactionSource) { interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> instance.animateToPressed(interaction.pressPosition) is PressInteraction.Release -> instance.animateToResting() is PressInteraction.Cancel -> instance.animateToResting() } } } return instance } }
建議您將上述程式碼片段修改為:
object ScaleIndicationNodeFactory : IndicationNodeFactory { override fun create(interactionSource: InteractionSource): DelegatableNode { return ScaleIndicationNode(interactionSource) } override fun hashCode(): Int = -1 override fun equals(other: Any?) = other === this }
使用 Indication
建立 IndicationInstance
在多數情況下,您應使用 Modifier.indication
顯示 Indication
元件。不過,在極少數的情況下,您必須手動建立
使用 rememberUpdatedInstance
的IndicationInstance
,請更新您的
可以檢查 Indication
是否為 IndicationNodeFactory
,因此您可以
較簡單的實作程序舉例來說,Modifier.indication
會
如果節點是 IndicationNodeFactory
,則會在內部委派給已建立的節點。如果
而不是,它會使用 Modifier.composed
呼叫 rememberUpdatedInstance
。