diff --git a/dpadrecyclerview/src/androidTest/kotlin/com/rubensousa/dpadrecyclerview/test/tests/focus/NestedFocusDirectionTest.kt b/dpadrecyclerview/src/androidTest/kotlin/com/rubensousa/dpadrecyclerview/test/tests/focus/NestedFocusDirectionTest.kt index 845bebb5..3448ebaa 100644 --- a/dpadrecyclerview/src/androidTest/kotlin/com/rubensousa/dpadrecyclerview/test/tests/focus/NestedFocusDirectionTest.kt +++ b/dpadrecyclerview/src/androidTest/kotlin/com/rubensousa/dpadrecyclerview/test/tests/focus/NestedFocusDirectionTest.kt @@ -107,6 +107,40 @@ class NestedFocusDirectionTest { } } + @Test + fun testFocusStillLeavesRecyclerViewWhenFocusSearchIsDisabled() = report { + step("Disable focus searches for the first recyclerview") { + Espresso.onView( + allOf( + withId( + com.rubensousa.dpadrecyclerview.test.R.id.nestedRecyclerView + ), + withTagValue(Matchers.`is`(0)) + ) + ).perform(DpadRecyclerViewActions.execute("Disable focus searches") { recyclerView -> + recyclerView.setFocusSearchDisabled(true) + }) + } + + step("Press down") { + KeyEvents.pressDown() + waitForIdleScrollState() + } + + step("Focus should be in second list") { + Espresso.onView( + allOf( + withId( + com.rubensousa.dpadrecyclerview.test.R.id.nestedRecyclerView + ), + withTagValue(Matchers.`is`(1)) + ) + ).check( + DpadRecyclerViewAssertions.isFocused(position = 0) + ) + } + } + private fun launchFragment(): FragmentScenario { return launchFragmentInContainer( themeResId = R.style.DpadRecyclerViewTestTheme diff --git a/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/LayoutConfiguration.kt b/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/LayoutConfiguration.kt index 8d5f203a..4db14e4a 100644 --- a/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/LayoutConfiguration.kt +++ b/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/LayoutConfiguration.kt @@ -90,7 +90,8 @@ internal class LayoutConfiguration(properties: Properties) { var isFocusSearchDisabled = false private set - private var isFocusSearchEnabledDuringAnimations = false + var isFocusSearchEnabledDuringAnimations = false + private set // Number of items to prefetch when first coming on screen with new data var initialPrefetchItemCount = 4 diff --git a/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/focus/FocusDispatcher.kt b/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/focus/FocusDispatcher.kt index 045473e4..f91cf316 100644 --- a/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/focus/FocusDispatcher.kt +++ b/dpadrecyclerview/src/main/java/com/rubensousa/dpadrecyclerview/layoutmanager/focus/FocusDispatcher.kt @@ -130,7 +130,15 @@ internal class FocusDispatcher( ): View? { val currentRecyclerView = recyclerView ?: return focused - if (!isFocusSearchEnabled(currentRecyclerView)) { + // If the parent RecyclerView does not allow focusing children, + // just delegate focus to its parent + if (currentRecyclerView.descendantFocusability == ViewGroup.FOCUS_BLOCK_DESCENDANTS) { + return currentRecyclerView.parent?.focusSearch(focused, direction) + } + + if (!configuration.isFocusSearchEnabledDuringAnimations + && currentRecyclerView.isAnimating + ) { return focused } @@ -175,13 +183,6 @@ internal class FocusDispatcher( } } - - // If the parent RecyclerView does not allow focusing children, - // just delegate focus to its parent - if (currentRecyclerView.descendantFocusability == ViewGroup.FOCUS_BLOCK_DESCENDANTS) { - return currentRecyclerView.parent?.focusSearch(focused, direction) - } - val isScrolling = currentRecyclerView.scrollState != RecyclerView.SCROLL_STATE_IDLE when (focusDirection) { FocusDirection.NEXT_ROW -> {