Fix a focus finding bug in RecyclerView
View1 is not a candidate of view2 when finding the next focus
target if:
1. view1 and view2 are the same view, or
2. the coordinates of view1 and view2 are the same
Fixes: 158492287
Test: run FocusSearchNavigationTest manually
Change-Id: I2b709422384712b44e45ab9cbaf90eafd0484a6c
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/FocusSearchNavigationTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/FocusSearchNavigationTest.java
index a9cb7cf..5949186 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/FocusSearchNavigationTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/FocusSearchNavigationTest.java
@@ -177,6 +177,22 @@
assertThat(mAfter, hasFocus());
}
+ @Test
+ public void focusSearchForwardWithSingleItem() throws Throwable {
+ setup(1);
+ requestFocus(mBefore);
+ assertThat(mBefore, hasFocus());
+
+ View focused = mBefore;
+ focusSearchAndGive(focused, View.FOCUS_FORWARD);
+ RecyclerView.ViewHolder viewHolder = mRecyclerView.findViewHolderForAdapterPosition(0);
+ assertThat("The first view holder ", viewHolder, hasFocus());
+
+ focused = viewHolder.itemView;
+ focusSearchAndGive(focused, View.FOCUS_FORWARD);
+ assertThat(mAfter, hasFocus());
+ }
+
private View focusSearchAndGive(final View view, final int focusDir) throws Throwable {
View next = focusSearch(view, focusDir);
if (next != null && next != view) {
diff --git a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
index 387721d..43bf459 100644
--- a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
+++ b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
@@ -2910,7 +2910,7 @@
* same View may still get the focus as a result of that search.
*/
private boolean isPreferredNextFocus(View focused, View next, int direction) {
- if (next == null || next == this) {
+ if (next == null || next == this || next == focused) {
return false;
}
// panic, result view is not a child anymore, maybe workaround b/37864393
@@ -2960,9 +2960,9 @@
case View.FOCUS_DOWN:
return downness > 0;
case View.FOCUS_FORWARD:
- return downness > 0 || (downness == 0 && rightness * rtl >= 0);
+ return downness > 0 || (downness == 0 && rightness * rtl > 0);
case View.FOCUS_BACKWARD:
- return downness < 0 || (downness == 0 && rightness * rtl <= 0);
+ return downness < 0 || (downness == 0 && rightness * rtl < 0);
}
throw new IllegalArgumentException("Invalid direction: " + direction + exceptionLabel());
}