為了針對使用
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
。