diff --git a/build.gradle b/build.gradle index 68caddc8..1e416fd5 100644 --- a/build.gradle +++ b/build.gradle @@ -8,9 +8,9 @@ buildscript { } plugins { - id 'com.android.application' version '8.0.0' apply false - id 'com.android.library' version '8.0.0' apply false - id 'org.jetbrains.kotlin.android' version '1.8.20' apply false + id 'com.android.application' version '8.2.2' apply false + id 'com.android.library' version '8.2.2' apply false + id 'org.jetbrains.kotlin.android' version '1.9.22' apply false id 'org.jetbrains.kotlinx.binary-compatibility-validator' version '0.13.0' } diff --git a/docs/changelog.md b/docs/changelog.md index f90938d2..7c6d065a 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,15 @@ ## Version 1.2.0 +### 1.2.0-beta02 + +2024-01-28 + +#### New Features + +- Added new `RecyclerViewCompositionStrategy.DisposeOnRecycled` for compose interop +to re-use compositions when views are detached and attached from the window again. + ### 1.2.0-beta01 2024-01-17 diff --git a/dpadrecyclerview-compose/api/dpadrecyclerview-compose.api b/dpadrecyclerview-compose/api/dpadrecyclerview-compose.api index d7a38405..be534b34 100644 --- a/dpadrecyclerview-compose/api/dpadrecyclerview-compose.api +++ b/dpadrecyclerview-compose/api/dpadrecyclerview-compose.api @@ -1,7 +1,7 @@ public abstract class com/rubensousa/dpadrecyclerview/compose/DpadAbstractComposeViewHolder : androidx/recyclerview/widget/RecyclerView$ViewHolder, com/rubensousa/dpadrecyclerview/DpadViewHolder { public static final field $stable I - public fun (Landroid/view/ViewGroup;Z)V - public synthetic fun (Landroid/view/ViewGroup;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Landroid/view/ViewGroup;ZLandroidx/compose/ui/platform/ViewCompositionStrategy;)V + public synthetic fun (Landroid/view/ViewGroup;ZLandroidx/compose/ui/platform/ViewCompositionStrategy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public abstract fun Content (Ljava/lang/Object;ZZLandroidx/compose/runtime/Composer;I)V public final fun getItem ()Ljava/lang/Object; public fun getSubPositionAlignments ()Ljava/util/List; @@ -14,8 +14,19 @@ public abstract class com/rubensousa/dpadrecyclerview/compose/DpadAbstractCompos public class com/rubensousa/dpadrecyclerview/compose/DpadComposeViewHolder : com/rubensousa/dpadrecyclerview/compose/DpadAbstractComposeViewHolder { public static final field $stable I - public fun (Landroid/view/ViewGroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function5;)V - public synthetic fun (Landroid/view/ViewGroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function5;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Landroid/view/ViewGroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLandroidx/compose/ui/platform/ViewCompositionStrategy;Lkotlin/jvm/functions/Function5;)V + public synthetic fun (Landroid/view/ViewGroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLandroidx/compose/ui/platform/ViewCompositionStrategy;Lkotlin/jvm/functions/Function5;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun Content (Ljava/lang/Object;ZZLandroidx/compose/runtime/Composer;I)V } +public final class com/rubensousa/dpadrecyclerview/compose/RecyclerViewCompositionStrategy { + public static final field $stable I + public static final field INSTANCE Lcom/rubensousa/dpadrecyclerview/compose/RecyclerViewCompositionStrategy; +} + +public final class com/rubensousa/dpadrecyclerview/compose/RecyclerViewCompositionStrategy$DisposeOnRecycled : androidx/compose/ui/platform/ViewCompositionStrategy { + public static final field $stable I + public static final field INSTANCE Lcom/rubensousa/dpadrecyclerview/compose/RecyclerViewCompositionStrategy$DisposeOnRecycled; + public fun installFor (Landroidx/compose/ui/platform/AbstractComposeView;)Lkotlin/jvm/functions/Function0; +} + diff --git a/dpadrecyclerview-compose/src/androidTest/java/com/rubensousa/dpadrecyclerview/compose/DpadComposeViewHolderTest.kt b/dpadrecyclerview-compose/src/androidTest/java/com/rubensousa/dpadrecyclerview/compose/DpadComposeViewHolderTest.kt index 8c81ec8d..0c09d7d8 100644 --- a/dpadrecyclerview-compose/src/androidTest/java/com/rubensousa/dpadrecyclerview/compose/DpadComposeViewHolderTest.kt +++ b/dpadrecyclerview-compose/src/androidTest/java/com/rubensousa/dpadrecyclerview/compose/DpadComposeViewHolderTest.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.assert import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.assertIsNotDisplayed import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.recyclerview.widget.RecyclerView @@ -28,6 +29,7 @@ import androidx.test.espresso.Espresso.onView import androidx.test.espresso.matcher.ViewMatchers import com.google.common.truth.Truth.assertThat import com.rubensousa.dpadrecyclerview.DpadRecyclerView +import com.rubensousa.dpadrecyclerview.ExtraLayoutSpaceStrategy import com.rubensousa.dpadrecyclerview.testing.KeyEvents import com.rubensousa.dpadrecyclerview.testing.actions.DpadRecyclerViewActions import org.junit.Rule @@ -48,6 +50,15 @@ class DpadComposeViewHolderTest { assertFocus(item = 2, isFocused = false) assertSelection(item = 2, isSelected = false) + + KeyEvents.pressDown() + waitForIdleScroll() + + assertFocus(item = 0, isFocused = false) + assertSelection(item = 0, isSelected = false) + + assertFocus(item = 1, isFocused = true) + assertSelection(item = 1, isSelected = true) } @Test @@ -107,7 +118,7 @@ class DpadComposeViewHolderTest { } @Test - fun testCompositionIsCleared() { + fun testCompositionIsClearedWhenClearingAdapter() { val viewHolders = ArrayList() composeTestRule.activityRule.scenario.onActivity { activity -> viewHolders.addAll(activity.getViewsHolders()) @@ -121,6 +132,41 @@ class DpadComposeViewHolderTest { composeTestRule.onNodeWithText("0").assertDoesNotExist() } + @Test + fun testCompositionIsNotClearedWhenDetachingFromWindow() { + composeTestRule.activityRule.scenario.onActivity { activity -> + activity.getRecyclerView().setExtraLayoutSpaceStrategy(object : ExtraLayoutSpaceStrategy { + override fun calculateStartExtraLayoutSpace(state: RecyclerView.State): Int { + return 1080 + } + }) + } + repeat(3) { + KeyEvents.pressDown() + waitForIdleScroll() + } + + composeTestRule.onNodeWithText("0").assertExists() + composeTestRule.onNodeWithText("0").assertIsNotDisplayed() + } + + @Test + fun testCompositionIsClearedWhenViewHolderIsRecycled() { + repeat(10) { + KeyEvents.pressDown() + waitForIdleScroll() + } + + composeTestRule.onNodeWithText("0").assertDoesNotExist() + + var disposals: List = emptyList() + composeTestRule.activityRule.scenario.onActivity { activity -> + disposals = activity.getDisposals() + } + + assertThat(disposals).contains(0) + } + private fun waitForIdleScroll() { onView(ViewMatchers.isAssignableFrom(DpadRecyclerView::class.java)) .perform(DpadRecyclerViewActions.waitForIdleScroll()) diff --git a/dpadrecyclerview-compose/src/debug/java/com/rubensousa/dpadrecyclerview/compose/TestActivity.kt b/dpadrecyclerview-compose/src/debug/java/com/rubensousa/dpadrecyclerview/compose/TestActivity.kt index f75412df..d47452d9 100644 --- a/dpadrecyclerview-compose/src/debug/java/com/rubensousa/dpadrecyclerview/compose/TestActivity.kt +++ b/dpadrecyclerview-compose/src/debug/java/com/rubensousa/dpadrecyclerview/compose/TestActivity.kt @@ -32,12 +32,18 @@ class TestActivity : AppCompatActivity() { private lateinit var recyclerView: DpadRecyclerView private val clicks = ArrayList() + private val disposals = ArrayList() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.compose_test) recyclerView = findViewById(R.id.recyclerView) - recyclerView.adapter = Adapter(List(100) { it }) + recyclerView.adapter = Adapter( + items = List(100) { it }, + onDispose = { item -> + disposals.add(item) + } + ) recyclerView.requestFocus() } @@ -53,10 +59,16 @@ class TestActivity : AppCompatActivity() { return clicks } + fun getDisposals(): List { + return disposals + } + fun removeAdapter() { recyclerView.adapter = null } + fun getRecyclerView(): DpadRecyclerView = recyclerView + fun getViewsHolders(): List { val viewHolders = ArrayList() recyclerView.children.forEach { child -> @@ -65,14 +77,17 @@ class TestActivity : AppCompatActivity() { return viewHolders } - inner class Adapter(private val items: List) : - RecyclerView.Adapter>() { + inner class Adapter( + private val items: List, + private val onDispose: (item: Int) -> Unit, + ) : RecyclerView.Adapter>() { override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): DpadComposeViewHolder { - return DpadComposeViewHolder(parent, + return DpadComposeViewHolder( + parent, composable = { item, isFocused, isSelected -> TestComposable( modifier = Modifier @@ -80,13 +95,17 @@ class TestActivity : AppCompatActivity() { .height(150.dp), item = item, isFocused = isFocused, - isSelected = isSelected + isSelected = isSelected, + onDispose = { + onDispose(item) + } ) }, onClick = { clicks.add(it) }, - isFocusable = true) + isFocusable = true + ) } override fun getItemCount(): Int = items.size diff --git a/dpadrecyclerview-compose/src/debug/java/com/rubensousa/dpadrecyclerview/compose/TestComposable.kt b/dpadrecyclerview-compose/src/debug/java/com/rubensousa/dpadrecyclerview/compose/TestComposable.kt index 2f1c3ef0..868071dc 100644 --- a/dpadrecyclerview-compose/src/debug/java/com/rubensousa/dpadrecyclerview/compose/TestComposable.kt +++ b/dpadrecyclerview-compose/src/debug/java/com/rubensousa/dpadrecyclerview/compose/TestComposable.kt @@ -18,8 +18,10 @@ package com.rubensousa.dpadrecyclerview.compose import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -37,7 +39,8 @@ fun TestComposable( modifier: Modifier = Modifier, item: Int, isFocused: Boolean, - isSelected: Boolean + isSelected: Boolean, + onDispose: () -> Unit = {}, ) { val backgroundColor = if (isFocused) { Color.White @@ -51,10 +54,24 @@ fun TestComposable( .background(backgroundColor), contentAlignment = Alignment.Center, ) { - Text(modifier = Modifier.semantics { - set(TestComposable.focusedKey, isFocused) - set(TestComposable.selectedKey, isSelected) - }, text = item.toString()) + Text( + modifier = Modifier.semantics { + set(TestComposable.focusedKey, isFocused) + set(TestComposable.selectedKey, isSelected) + }, + text = item.toString(), + style = MaterialTheme.typography.headlineLarge, + color = if(isFocused) { + Color.Black + } else { + Color.White + } + ) + } + DisposableEffect(key1 = item) { + onDispose { + onDispose() + } } } diff --git a/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/DpadAbstractComposeViewHolder.kt b/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/DpadAbstractComposeViewHolder.kt index c8d4c68f..9173ee9b 100644 --- a/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/DpadAbstractComposeViewHolder.kt +++ b/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/DpadAbstractComposeViewHolder.kt @@ -20,6 +20,7 @@ import android.view.ViewGroup import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.recyclerview.widget.RecyclerView import com.rubensousa.dpadrecyclerview.DpadViewHolder @@ -41,7 +42,8 @@ import com.rubensousa.dpadrecyclerview.DpadViewHolder */ abstract class DpadAbstractComposeViewHolder( parent: ViewGroup, - isFocusable: Boolean = true + isFocusable: Boolean = true, + compositionStrategy: ViewCompositionStrategy = RecyclerViewCompositionStrategy.DisposeOnRecycled ) : RecyclerView.ViewHolder(ComposeView(parent.context)), DpadViewHolder { private val itemState = mutableStateOf(null) @@ -50,6 +52,7 @@ abstract class DpadAbstractComposeViewHolder( init { val composeView = itemView as ComposeView + composeView.setViewCompositionStrategy(compositionStrategy) composeView.isFocusable = isFocusable composeView.isFocusableInTouchMode = isFocusable composeView.descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS diff --git a/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/DpadComposeViewHolder.kt b/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/DpadComposeViewHolder.kt index aeefe18b..0fb88789 100644 --- a/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/DpadComposeViewHolder.kt +++ b/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/DpadComposeViewHolder.kt @@ -17,6 +17,7 @@ package com.rubensousa.dpadrecyclerview.compose import android.view.ViewGroup import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.ViewCompositionStrategy /** * A basic implementation of [DpadAbstractComposeViewHolder] @@ -44,8 +45,9 @@ open class DpadComposeViewHolder( onClick: ((item: T) -> Unit)? = null, onLongClick: ((item: T) -> Boolean)? = null, isFocusable: Boolean = true, + compositionStrategy: ViewCompositionStrategy = RecyclerViewCompositionStrategy.DisposeOnRecycled, private val composable: DpadComposable, -) : DpadAbstractComposeViewHolder(parent, isFocusable) { +) : DpadAbstractComposeViewHolder(parent, isFocusable, compositionStrategy) { init { if (onClick != null) { diff --git a/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/RecyclerViewCompositionStrategy.kt b/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/RecyclerViewCompositionStrategy.kt new file mode 100644 index 00000000..21a41668 --- /dev/null +++ b/dpadrecyclerview-compose/src/main/java/com/rubensousa/dpadrecyclerview/compose/RecyclerViewCompositionStrategy.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2024 RĂºben Sousa + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.rubensousa.dpadrecyclerview.compose + +import androidx.compose.ui.platform.AbstractComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.customview.poolingcontainer.PoolingContainerListener +import androidx.customview.poolingcontainer.addPoolingContainerListener +import androidx.customview.poolingcontainer.removePoolingContainerListener +import com.rubensousa.dpadrecyclerview.DpadRecyclerView + +object RecyclerViewCompositionStrategy { + + /** + * Similar to [ViewCompositionStrategy.DisposeOnDetachedFromWindowOrReleasedFromPool] but skips + * releasing compositions when detached from window. This is useful for re-using compositions + * a lot more often when scrolling a RecyclerView. + * + * If you use [DpadRecyclerView.setRecycleChildrenOnDetach], + * this will behave exactly the same as [ViewCompositionStrategy.DisposeOnDetachedFromWindowOrReleasedFromPool]. + * + * If you use [DpadRecyclerView.setExtraLayoutSpaceStrategy], + * please profile the compositions before considering using this strategy. + */ + object DisposeOnRecycled : ViewCompositionStrategy { + override fun installFor(view: AbstractComposeView): () -> Unit { + val poolingContainerListener = PoolingContainerListener { + view.disposeComposition() + } + view.addPoolingContainerListener(poolingContainerListener) + return { + view.removePoolingContainerListener(poolingContainerListener) + } + } + } + +} diff --git a/dpadrecyclerview/api/dpadrecyclerview.api b/dpadrecyclerview/api/dpadrecyclerview.api index c5ed1b85..5a419b53 100644 --- a/dpadrecyclerview/api/dpadrecyclerview.api +++ b/dpadrecyclerview/api/dpadrecyclerview.api @@ -34,6 +34,7 @@ public final class com/rubensousa/dpadrecyclerview/DpadLoopDirection : java/lang public static final field MAX Lcom/rubensousa/dpadrecyclerview/DpadLoopDirection; public static final field MIN_MAX Lcom/rubensousa/dpadrecyclerview/DpadLoopDirection; public static final field NONE Lcom/rubensousa/dpadrecyclerview/DpadLoopDirection; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/rubensousa/dpadrecyclerview/DpadLoopDirection; public static fun values ()[Lcom/rubensousa/dpadrecyclerview/DpadLoopDirection; } @@ -237,6 +238,7 @@ public final class com/rubensousa/dpadrecyclerview/FocusableDirection : java/lan public static final field CIRCULAR Lcom/rubensousa/dpadrecyclerview/FocusableDirection; public static final field CONTINUOUS Lcom/rubensousa/dpadrecyclerview/FocusableDirection; public static final field STANDARD Lcom/rubensousa/dpadrecyclerview/FocusableDirection; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/rubensousa/dpadrecyclerview/FocusableDirection; public static fun values ()[Lcom/rubensousa/dpadrecyclerview/FocusableDirection; } @@ -292,6 +294,7 @@ public final class com/rubensousa/dpadrecyclerview/ParentAlignment$Edge : java/l public static final field MIN Lcom/rubensousa/dpadrecyclerview/ParentAlignment$Edge; public static final field MIN_MAX Lcom/rubensousa/dpadrecyclerview/ParentAlignment$Edge; public static final field NONE Lcom/rubensousa/dpadrecyclerview/ParentAlignment$Edge; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/rubensousa/dpadrecyclerview/ParentAlignment$Edge; public static fun values ()[Lcom/rubensousa/dpadrecyclerview/ParentAlignment$Edge; } diff --git a/dpadrecyclerview/src/androidTest/kotlin/com/rubensousa/dpadrecyclerview/test/tests/recycling/RecyclingTest.kt b/dpadrecyclerview/src/androidTest/kotlin/com/rubensousa/dpadrecyclerview/test/tests/recycling/RecyclingTest.kt index 31542b1c..1ccfd337 100644 --- a/dpadrecyclerview/src/androidTest/kotlin/com/rubensousa/dpadrecyclerview/test/tests/recycling/RecyclingTest.kt +++ b/dpadrecyclerview/src/androidTest/kotlin/com/rubensousa/dpadrecyclerview/test/tests/recycling/RecyclingTest.kt @@ -25,6 +25,7 @@ import com.rubensousa.dpadrecyclerview.UnboundViewPool import com.rubensousa.dpadrecyclerview.test.TestAdapterConfiguration import com.rubensousa.dpadrecyclerview.test.TestGridFragment import com.rubensousa.dpadrecyclerview.test.TestLayoutConfiguration +import com.rubensousa.dpadrecyclerview.test.helpers.assertSelectedPosition import com.rubensousa.dpadrecyclerview.test.helpers.onRecyclerView import com.rubensousa.dpadrecyclerview.test.helpers.waitForCondition import com.rubensousa.dpadrecyclerview.test.tests.DpadRecyclerViewTest @@ -112,5 +113,34 @@ class RecyclingTest : DpadRecyclerViewTest() { assertThat(viewPool.getRecycledViewCount(0)).isEqualTo(0) } + @Test + fun testViewsAreRecreatedOnAttachedFromWindowAgain() { + launchFragment( + getDefaultLayoutConfiguration().copy( + recycleChildrenOnDetach = true + ) + ) + + waitForCondition("Waiting for RecyclerView layout") { recyclerView -> + recyclerView.layoutManager!!.childCount > 0 && !recyclerView.isLayoutRequested + } + + val childBounds = getChildrenBounds() + + onRecyclerView("Detach RecyclerView from window") { view -> + view.detachFromWindow() + } + + onRecyclerView("Attach RecyclerView to window") { view -> + view.attachToWindow() + } + + waitForCondition("Waiting for RecyclerView layout") { recyclerView -> + recyclerView.childCount > 0 && !recyclerView.isLayoutRequested + } + + assertSelectedPosition(0) + assertChildrenPositions(childBounds) + } } diff --git a/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/DpadRecyclerView.kt b/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/DpadRecyclerView.kt index 5e1e6342..8c2aa358 100644 --- a/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/DpadRecyclerView.kt +++ b/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/DpadRecyclerView.kt @@ -28,6 +28,7 @@ import android.view.View import android.view.ViewGroup import android.view.animation.Interpolator import androidx.annotation.Px +import androidx.annotation.VisibleForTesting import androidx.core.view.ViewCompat import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -1218,6 +1219,16 @@ open class DpadRecyclerView @JvmOverloads constructor( */ fun getOnMotionInterceptListener(): OnMotionInterceptListener? = motionInterceptListener + @VisibleForTesting + internal fun detachFromWindow() { + onDetachedFromWindow() + } + + @VisibleForTesting + internal fun attachToWindow() { + onAttachedToWindow() + } + private fun removeSelectionForRecycledViewHolders() { addRecyclerListener { holder -> val position = holder.absoluteAdapterPosition diff --git a/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/PivotLayoutManager.kt b/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/PivotLayoutManager.kt index cceeb955..7b68c5e4 100644 --- a/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/PivotLayoutManager.kt +++ b/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/PivotLayoutManager.kt @@ -228,7 +228,7 @@ class PivotLayoutManager(properties: Properties) : RecyclerView.LayoutManager() if (childCount == 0) { return 0 } - return DpadScrollbarHelper.computeScrollRange( + return DpadScrollbarHelper.computeScrollRange( state = state, orientationHelper = layoutInfo.orientationHelper, startChild = layoutInfo.findFirstVisibleChild(), @@ -334,6 +334,9 @@ class PivotLayoutManager(properties: Properties) : RecyclerView.LayoutManager() override fun onAttachedToWindow(view: RecyclerView) { super.onAttachedToWindow(view) focusDispatcher.updateParentRecyclerView(view) + if (configuration.recycleChildrenOnDetach) { + requestLayout() + } } override fun onDetachedFromWindow(view: RecyclerView, recycler: RecyclerView.Recycler) { diff --git a/gradle.properties b/gradle.properties index bf1b7b27..69b9df37 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,4 +22,4 @@ kotlin.code.style=official # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true android.enableR8.fullMode=true -LIBRARY_VERSION=1.2.0-beta01 \ No newline at end of file +LIBRARY_VERSION=1.2.0-beta02 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cafc282b..4e1474ee 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Jan 24 12:52:07 CET 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/mkdocs.yml b/mkdocs.yml index 11cee319..4eb664f3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -24,7 +24,7 @@ theme: extra: dpadrecyclerview: - version: '1.2.0-beta01' + version: '1.2.0-beta02' social: - icon: 'fontawesome/brands/github' link: 'https://github.com/rubensousa/DpadRecyclerView' diff --git a/versions.gradle b/versions.gradle index 5a642acb..d9581297 100644 --- a/versions.gradle +++ b/versions.gradle @@ -1,7 +1,7 @@ def versions = [:] versions.minSdkVersion = 21 -versions.targetSdkVersion = 33 -versions.compileSdkVersion = 33 +versions.targetSdkVersion = 34 +versions.compileSdkVersion = 34 versions.recyclerview = '1.3.2' versions.collection = '1.3.0' versions.constraintLayout = '2.1.4' @@ -13,10 +13,10 @@ versions.poolingContainer = '1.0.0' versions.paging = '3.1.1' def composeVersions = [:] -composeVersions.runtime = '1.4.2' -composeVersions.ui = '1.4.2' -composeVersions.material3 = '1.0.1' -composeVersions.compiler = '1.4.6' +composeVersions.runtime = '1.6.0' +composeVersions.ui = '1.6.0' +composeVersions.material3 = '1.2.0-rc01' +composeVersions.compiler = '1.5.8' def testVersions = [:] testVersions.junit = '4.13.2'