インタラクティブ コンポーネントのコンポーズのパフォーマンスを向上させるため、
Modifier.clickable
さん、新しい API を導入しました。これらの API を使用すると、
効率的な Indication
の実装(リップルなど)。
androidx.compose.foundation:foundation:1.7.0+
、
androidx.compose.material:material-ripple:1.7.0+
には次の API が含まれます
変更点:
非推奨 |
置き換え |
---|---|
|
|
|
代わりにマテリアル ライブラリで新しい 注: ここでは「マテリアル ライブラリ」、 |
|
Either:
|
このページでは、動作変更による影響と、 説明します。
動作の変更
次のライブラリ バージョンでは、リップルの動作が変更されています。
androidx.compose.material:material:1.7.0+
androidx.compose.material3:material3:1.3.0+
androidx.wear.compose:compose-material:1.4.0+
これらのバージョンのマテリアル ライブラリでは rememberRipple()
が使用されなくなりました。使用する代わりに、
新しい Ripple API を使用していますそのため、LocalRippleTheme
はクエリされません。
そのため、アプリで LocalRippleTheme
を設定すると、Material
これらの値は使用されません。
次のセクションでは、以前の動作に一時的にフォールバックする方法について説明します。
できます。新しい API に移行することをおすすめします。対象
移行手順については、rememberRipple
から ripple
への移行をご覧ください。
説明します。
移行せずにマテリアル ライブラリのバージョンをアップグレードする
ライブラリ バージョンのアップグレードのブロックを解除するには、一時的な
構成する LocalUseFallbackRippleImplementation CompositionLocal
API
以前の動作にフォールバックするためのマテリアル コンポーネント:
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
古いさざ波が残るように、必ず MaterialTheme
の外に配置してください
LocalIndication
を介して提供されます。
以降のセクションでは、新しい API に移行する方法について説明します。
rememberRipple
から ripple
に移行する
マテリアル ライブラリの使用
マテリアル ライブラリを使用している場合は、rememberRipple()
を直接
対応するライブラリから ripple()
を呼び出します。この API はさまざまな
Material Theme 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。コンポーネントは独自のリップルを使用して
テーマ値を直接消費します詳細については、Migrate to Migrate
RippleTheme
から。
RippleTheme
から移行する
動作変更を一時的にオプトアウトする
マテリアル ライブラリには一時的な CompositionLocal
があります。
LocalUseFallbackRippleImplementation
: これを使用して、
rememberRipple
を使用するようフォールバックするマテリアル コンポーネント。このように
rememberRipple
は LocalRippleTheme
のクエリを続行します。
次のコード スニペットは、LocalUseFallbackRippleImplementation CompositionLocal
API の使用方法を示しています。
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
マテリアルを基に構築されたカスタムアプリテーマを使用している場合は、次のことができます。 アプリのテーマの一部としてコンポジション ローカルを安全に提供します。
@OptIn(ExperimentalMaterialApi::class) @Composable fun MyAppTheme(content: @Composable () -> Unit) { CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme(content = content) } }
詳しくは、Android Vitals を使用せずにマテリアル ライブラリ バージョンをアップグレードするには、 移行セクションを参照してください。
RippleTheme
を使用して特定のコンポーネントのリップルを無効にする
material
ライブラリと material3
ライブラリは、RippleConfiguration
と
LocalRippleConfiguration
を使用すると、アプリのデザインを
影響します。RippleConfiguration
と
LocalRippleConfiguration
は試験運用版で、コンポーネントごとの
カスタマイズが可能です。これらのプロダクトでは、グローバル/テーマ全体のカスタマイズはサポートされていません
APIRippleTheme
を使用してすべてのリップルをグローバルに変更する
をご覧ください。
たとえば、次のスニペットでは非推奨の 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
を使用して特定のコンポーネントのリップルの色/アルファを変更する
前のセクションで説明したように、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
を使用して、特定の時点での波紋効果を定義して
できます。これは基本的に、カスタム
システム コンポジションのローカルとリップルを設計します。汎用の API を公開するのではなく、
テーマ設定プリミティブの material-ripple
が createRippleModifierNode()
を公開するようになりました
使用します。この関数を使用すると、デザイン システム ライブラリでより高度な
テーマ値をクエリしてデリゲートする wrapper
実装を順序付けする
リップル実装を、この関数で作成されたノードに送ります。
これにより、設計システムは必要なものを直接クエリして、
ユーザー設定が可能なテーマ設定レイヤを一番上に置いておく必要があります。
material-ripple
レイヤで提供されます。この変更により
その波形がどのテーマ/仕様に準拠しているかを明示する
暗黙的にではなく、コントラクトを定義する
作成します。
詳しくは、マテリアルの Ripple API の実装をご覧ください 必要に応じてマテリアル コンポジション ローカルの呼び出しを 独自のデザイン システムを作成できます。
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() } } }
これは次の 2 つのステップで移行できます。
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
を
説明します。ただし、まれなケースですが、サービス アカウントを
IndicationInstance
が rememberUpdatedInstance
を使用しています。更新する必要があります
Indication
が IndicationNodeFactory
であるかどうかをチェックし、
より軽量な実装を使用できます。たとえば、Modifier.indication
は、
作成されたノードが IndicationNodeFactory
の場合、内部で委任します。条件
そうでない場合は、Modifier.composed
を使用して rememberUpdatedInstance
を呼び出します。