Modifier.clickable
kullanan etkileşimli bileşenlerin bileşim performansını iyileştirmek için yeni API'leri kullanıma sunduk. Bu API'ler, dalgalar gibi daha verimli Indication
uygulamalarına olanak tanır.
androidx.compose.foundation:foundation:1.7.0+
ve
androidx.compose.material:material-ripple:1.7.0+
aşağıdaki API değişikliklerini içeriyor:
Kullanımdan kaldırıldı |
Vekil |
---|---|
|
|
|
Bunun yerine Materyal kitaplıklarında yeni Not: Bu bağlamda "Malzeme kitaplıkları", |
|
Şu iki yöntemden birini kullanın:
|
Bu sayfada, davranış değişikliğinin etkisi ve yeni API'lere geçiş talimatları açıklanmaktadır.
Davranış değişikliği
Aşağıdaki kitaplık sürümleri dalga davranışı değişikliği içerir:
androidx.compose.material:material:1.7.0+
androidx.compose.material3:material3:1.3.0+
androidx.wear.compose:compose-material:1.4.0+
Materyal kitaplıklarının bu sürümlerinde artık rememberRipple()
kullanılmaz; bunun yerine yeni Ripple API'leri kullanılır. Dolayısıyla bu kullanıcı LocalRippleTheme
sorgusunu sorgulamaz.
Dolayısıyla, uygulamanızda LocalRippleTheme
değerini ayarlarsanız Materyal bileşenleri bu değerleri kullanmaz.
Aşağıdaki bölümde, geçiş yapmadan geçici olarak eski davranışı nasıl geri alabileceğiniz açıklanmaktadır. Ancak yeni API'lere geçiş yapmanızı öneririz. Taşıma talimatları için rememberRipple
'den ripple
'e taşıma başlıklı makaleye ve sonraki bölümlere göz atın.
Taşıma yapmadan Materyal Kitaplığı sürümünü yükseltme
Kitaplık sürümlerinin yükseltilmesini engellemek için geçici LocalUseFallbackRippleImplementation CompositionLocal
API'sini kullanarak Materyal bileşenlerini eski davranışa geri dönecek şekilde yapılandırabilirsiniz:
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
Eski dalgaların LocalIndication
aracılığıyla sağlanabilmesi için bunu MaterialTheme
öğesinin dışında sağladığınızdan emin olun.
Aşağıdaki bölümlerde yeni API'lere nasıl geçiş yapılacağı açıklanmaktadır.
rememberRipple
'den ripple
'a taşıyın
Materyal kitaplığını kullanma
Malzeme kitaplığı kullanıyorsanız rememberRipple()
kısmını doğrudan ilgili kitaplıktan ripple()
çağrısıyla değiştirin. Bu API, Materyal tema API'lerinden türetilen değerleri kullanarak bir dalga oluşturur. Daha sonra, döndürülen nesneyi Modifier.clickable
ve/veya diğer bileşenlere geçirin.
Örneğin, aşağıdaki snippet'te kullanımdan kaldırılmış API'ler kullanılmaktadır:
Box( Modifier.clickable( onClick = {}, interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple() ) ) { // ... }
Yukarıdaki snippet'i şu şekilde değiştirmelisiniz:
@Composable private fun RippleExample() { Box( Modifier.clickable( onClick = {}, interactionSource = remember { MutableInteractionSource() }, indication = ripple() ) ) { // ... } }
ripple()
işlevinin artık composable bir işlev olmadığını ve hatırlanması gerekmediğini unutmayın. Ayrıca, değiştiricilere benzer şekilde birden çok bileşende de yeniden kullanılabilir. Bu nedenle, ayırmaları kaydetmek için dalga oluşumunu üst düzey bir değere çıkarmanız önerilir.
Özel tasarım sistemini uygulama
Kendi tasarım sisteminizi uyguluyorsanız ve daha önce dalgayı yapılandırmak için özel bir RippleTheme
ile birlikte rememberRipple()
kullanıyorduysanız bunun yerine, material-ripple
içinde sunulan dalga düğümü API'lerine yetki veren kendi Ripple API'nizi sağlamanız gerekir. Daha sonra bileşenleriniz, tema değerlerinizi doğrudan tüketen kendi dalganızı kullanabilir. Daha fazla bilgi için Taşıma kaynağı:RippleTheme
bölümüne bakın.
RippleTheme
sürümünden taşıma
Davranış değişikliğini geçici olarak devre dışı bırakma
Malzeme kitaplıklarında, tüm Materyal bileşenlerini rememberRipple
kullanmaya geri dönecek şekilde yapılandırmak için kullanabileceğiniz geçici bir CompositionLocal
(LocalUseFallbackRippleImplementation
) bulunur. Bu şekilde, rememberRipple
, LocalRippleTheme
sorgusunu sorgulamaya devam eder.
Aşağıdaki kod snippet'i, LocalUseFallbackRippleImplementation CompositionLocal
API'nin nasıl kullanılacağını gösterir:
CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme { App() } }
Materyal üzerine inşa edilmiş özel bir uygulama teması kullanıyorsanız, kompozisyonu uygulamanızın temasının bir parçası olarak güvenle sağlayabilirsiniz:
@OptIn(ExperimentalMaterialApi::class) @Composable fun MyAppTheme(content: @Composable () -> Unit) { CompositionLocalProvider(LocalUseFallbackRippleImplementation provides true) { MaterialTheme(content = content) } }
Daha fazla bilgi için Taşımadan Materyal Kitaplığı sürümünü yükseltme bölümüne bakın.
Belirli bir bileşende dalgayı devre dışı bırakmak için RippleTheme
kullanma
material
ve material3
kitaplıkları, bir alt ağaç içindeki dalgaların görünümünü yapılandırmanıza olanak tanıyan RippleConfiguration
ve LocalRippleConfiguration
öğelerini kullanıma sunar. RippleConfiguration
ve LocalRippleConfiguration
öğelerinin deneysel olduğunu ve yalnızca bileşen başına özelleştirme için tasarlandığını unutmayın. Bu API'lerle genel/tema genelinde özelleştirme desteklenmez. Bu API'ler hakkında daha fazla bilgi edinmek için Bir uygulamadaki tüm dalgaları genel olarak değiştirmek için RippleTheme
kullanma bölümüne bakın.
Örneğin, aşağıdaki snippet'te kullanımdan kaldırılmış API'ler kullanılmaktadır:
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 { // ... } }
Yukarıdaki snippet'i şu şekilde değiştirmelisiniz:
@OptIn(ExperimentalMaterialApi::class) private val DisabledRippleConfiguration = RippleConfiguration(isEnabled = false) // ... CompositionLocalProvider(LocalRippleConfiguration provides DisabledRippleConfiguration) { Button { // ... } }
Belirli bir bileşen için bir dalganın rengini/alfasını değiştirmek üzere RippleTheme
kullanma
Önceki bölümde açıklandığı gibi RippleConfiguration
ve LocalRippleConfiguration
, deneysel API'lerdir ve yalnızca bileşen başına özelleştirmeye yöneliktir.
Örneğin, aşağıdaki snippet'te kullanımdan kaldırılmış API'ler kullanılmaktadır:
private object DisabledRippleThemeColorAndAlpha : RippleTheme { @Composable override fun defaultColor(): Color = Color.Red @Composable override fun rippleAlpha(): RippleAlpha = MyRippleAlpha } // ... CompositionLocalProvider(LocalRippleTheme provides DisabledRippleThemeColorAndAlpha) { Button { // ... } }
Yukarıdaki snippet'i şu şekilde değiştirmelisiniz:
@OptIn(ExperimentalMaterialApi::class) private val MyRippleConfiguration = RippleConfiguration(color = Color.Red, rippleAlpha = MyRippleAlpha) // ... CompositionLocalProvider(LocalRippleConfiguration provides MyRippleConfiguration) { Button { // ... } }
Bir uygulamadaki tüm dalgaları genel olarak değiştirmek için RippleTheme
kullanma
Önceden, dalga davranışını tema genelinde tanımlamak için LocalRippleTheme
kullanılabiliyordu. Bu, temelde özel tasarım sistemi bileşimi yerelleri ile
Ripple arasındaki entegrasyon noktasıydı. Genel bir temel tema oluşturmak yerine, material-ripple
artık bir createRippleModifierNode()
işlevini kullanıma sunuyor. Bu işlev, tasarım sistemi kitaplıklarının tema değerlerini sorgulayan ve ardından dalga uygulamasını bu işlev tarafından oluşturulan düğüme atayan daha üst düzey wrapper
uygulaması oluşturmasına olanak tanır.
Bu, tasarım sistemlerinin ihtiyaç duydukları şeyi doğrudan sorgulamasına ve material-ripple
katmanında sağlananlara uyum sağlamak zorunda kalmadan, kullanıcı tarafından yapılandırılabilen gerekli tema katmanlarını en üstte açığa çıkarmasına olanak tanır. Bu değişiklik, dolaylı bir şekilde temadan türetilmek yerine, söz konusu sözleşmeyi tanımlayan Dalga API'sı olduğu için, dalganın hangi temaya/spesifikasyona uyduğunu daha açık bir şekilde ortaya koyar.
Yol gösterici olarak Materyal kitaplıklarındaki dalga API uygulamasına bakın ve kendi tasarım sisteminiz için gereken şekilde Malzeme bileşimi yerellerine yapılan çağrıları değiştirin.
Indication
'den IndicationNodeFactory
'a taşıyın
Indication
çevresinden geçiyor
Yalnızca geçiş için bir Indication
oluşturuyorsanız (örneğin, Modifier.clickable
veya Modifier.indication
öğesine geçirmek için dalga oluşturmak) herhangi bir değişiklik yapmanız gerekmez. IndicationNodeFactory
öğesi, Indication
öğesinden devralınır. Dolayısıyla her şey derlemeye ve çalışmaya devam eder.
Indication
oluşturuluyor
Kendi Indication
uygulamanızı oluşturuyorsanız taşıma işlemi çoğu durumda kolay olacaktır. Örneğin, basına ölçek efekti uygulayan bir Indication
düşünün:
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() } } }
Bunu iki adımda taşıyabilirsiniz:
ScaleIndicationInstance
hesabınıDrawModifierNode
taşımak için taşıyın.DrawModifierNode
API yüzeyiIndicationInstance
ile çok benzerdir:IndicationInstance#drawContent()
ile işlevsel olarak eşdeğer olan birContentDrawScope#draw()
işlevi sunar. Bu işlevi değiştirmeniz ve daha sonra,Indication
yerine doğrudan düğümün içindecollectLatest
mantığını uygulamanız gerekir.Örneğin, aşağıdaki snippet'te kullanımdan kaldırılmış API'ler kullanılmaktadır:
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() } } }
Yukarıdaki snippet'i şu şekilde değiştirmelisiniz:
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() } } }
IndicationNodeFactory
uygulamasını uygulamak içinScaleIndication
taşıyın. Toplama mantığı artık düğüme taşındığı için bu, tek sorumluluğu düğüm örneği oluşturmak olan çok basit bir fabrika nesnesidir.Örneğin, aşağıdaki snippet'te kullanımdan kaldırılmış API'ler kullanılmaktadır:
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 } }
Yukarıdaki snippet'i şu şekilde değiştirmelisiniz:
object ScaleIndicationNodeFactory : IndicationNodeFactory { override fun create(interactionSource: InteractionSource): DelegatableNode { return ScaleIndicationNode(interactionSource) } override fun hashCode(): Int = -1 override fun equals(other: Any?) = other === this }
IndicationInstance
oluşturmak için Indication
kullanılıyor
Çoğu durumda, bir bileşen için Indication
öğesini görüntülemek üzere Modifier.indication
kullanmanız gerekir. Bununla birlikte, rememberUpdatedInstance
kullanarak manuel olarak IndicationInstance
oluşturduğunuz bazı nadir durumlarda, daha basit bir uygulama kullanabilmeniz için Indication
öğesinin IndicationNodeFactory
olup olmadığını kontrol etmek üzere uygulamanızı güncellemeniz gerekir. Örneğin Modifier.indication
, oluşturulan düğüm IndicationNodeFactory
ise dahili olarak bu düğüme yetki verir. Aksi takdirde rememberUpdatedInstance
işlemini çağırmak için Modifier.composed
kullanılır.