Skip to content

Commit 2dda468

Browse files
committed
Accessibility focus traversal of lists inconsistent.
1. Now the list traversal forward is the exact opposite of the traversal backward. 2. The focus search starts from the view against which the call is made as opposed to the one that has focus. This is now consistent with the rest of the focus search. bug:6537747 Change-Id: Ida6a696636a3099531155fcbff256f71264f5008
1 parent c7f82cc commit 2dda468

File tree

1 file changed

+51
-49
lines changed

1 file changed

+51
-49
lines changed

core/java/android/widget/AbsListView.java

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
import android.view.ViewDebug;
5858
import android.view.ViewGroup;
5959
import android.view.ViewParent;
60-
import android.view.ViewRootImpl;
6160
import android.view.ViewTreeObserver;
6261
import android.view.accessibility.AccessibilityEvent;
6362
import android.view.accessibility.AccessibilityManager;
@@ -1331,43 +1330,42 @@ void invokeOnItemScrollListener() {
13311330

13321331
@Override
13331332
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
1334-
if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY
1335-
&& (direction == ACCESSIBILITY_FOCUS_FORWARD
1336-
|| direction == ACCESSIBILITY_FOCUS_BACKWARD)) {
1337-
if (canTakeAccessibilityFocusFromHover()) {
1338-
views.add(this);
1333+
if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
1334+
switch(direction) {
1335+
case ACCESSIBILITY_FOCUS_BACKWARD: {
1336+
View focusable = (getChildCount() > 0) ? getChildAt(getChildCount() - 1) : this;
1337+
if (focusable.canTakeAccessibilityFocusFromHover()) {
1338+
views.add(focusable);
1339+
}
1340+
} return;
1341+
case ACCESSIBILITY_FOCUS_FORWARD: {
1342+
if (canTakeAccessibilityFocusFromHover()) {
1343+
views.add(this);
1344+
}
1345+
} return;
13391346
}
1340-
} else {
13411347
super.addFocusables(views, direction, focusableMode);
13421348
}
13431349
}
13441350

13451351
@Override
13461352
public View focusSearch(int direction) {
1347-
return focusSearch(null, direction);
1353+
return focusSearch(this, direction);
13481354
}
13491355

13501356
@Override
13511357
public View focusSearch(View focused, int direction) {
13521358
switch (direction) {
13531359
case ACCESSIBILITY_FOCUS_FORWARD: {
1354-
ViewRootImpl viewRootImpl = getViewRootImpl();
1355-
if (viewRootImpl == null) {
1356-
return null;
1357-
}
1358-
View currentFocus = viewRootImpl.getAccessibilityFocusedHost();
1359-
if (currentFocus == null) {
1360-
return super.focusSearch(this, direction);
1361-
}
1362-
// If we have the focus try giving it to the first child.
1363-
if (currentFocus == this) {
1360+
// If we are the focused view try giving it to the first child.
1361+
if (focused == this) {
13641362
if (getChildCount() > 0) {
13651363
return getChildAt(0);
13661364
}
13671365
return super.focusSearch(this, direction);
13681366
}
1369-
// Find the item that has accessibility focus.
1370-
final int currentPosition = getPositionForView(currentFocus);
1367+
// Find the item that has the focused view.
1368+
final int currentPosition = getPositionForView(focused);
13711369
if (currentPosition < 0 || currentPosition >= getCount()) {
13721370
return super.focusSearch(this, direction);
13731371
}
@@ -1376,60 +1374,64 @@ public View focusSearch(View focused, int direction) {
13761374
if (currentItem instanceof ViewGroup) {
13771375
ViewGroup currentItemGroup = (ViewGroup) currentItem;
13781376
View nextFocus = FocusFinder.getInstance().findNextFocus(currentItemGroup,
1379-
currentFocus, direction);
1377+
focused, direction);
13801378
if (nextFocus != null && nextFocus != currentItemGroup
1381-
&& nextFocus != currentFocus) {
1379+
&& nextFocus != focused) {
13821380
return nextFocus;
13831381
}
13841382
}
13851383
// Try to move focus to the next item.
13861384
final int nextPosition = currentPosition - getFirstVisiblePosition() + 1;
13871385
if (nextPosition < getChildCount()) {
13881386
return getChildAt(nextPosition);
1389-
} else {
1390-
return super.focusSearch(this, direction);
13911387
}
1388+
// No next item start searching from the list.
1389+
return super.focusSearch(this, direction);
13921390
}
13931391
case ACCESSIBILITY_FOCUS_BACKWARD: {
1394-
ViewRootImpl viewRootImpl = getViewRootImpl();
1395-
if (viewRootImpl == null) {
1396-
return null;
1397-
}
1398-
View currentFocus = viewRootImpl.getAccessibilityFocusedHost();
1399-
if (currentFocus == null) {
1400-
return super.focusSearch(this, direction);
1401-
}
1402-
// If we have the focus do a generic search.
1403-
if (currentFocus == this) {
1404-
final int lastChildIndex = getChildCount() - 1;
1405-
if (lastChildIndex >= 0) {
1406-
return getChildAt(lastChildIndex);
1392+
// If we are the focused search from the view that is
1393+
// as closer to the bottom as possible.
1394+
if (focused == this) {
1395+
final int childCount = getChildCount();
1396+
if (childCount > 0) {
1397+
return super.focusSearch(getChildAt(childCount - 1), direction);
14071398
}
14081399
return super.focusSearch(this, direction);
14091400
}
1410-
// Find the item that has accessibility focus.
1411-
final int currentPosition = getPositionForView(currentFocus);
1401+
// Find the item that has the focused view.
1402+
final int currentPosition = getPositionForView(focused);
14121403
if (currentPosition < 0 || currentPosition >= getCount()) {
14131404
return super.focusSearch(this, direction);
14141405
}
1415-
// Try to advance focus in the current item.
1406+
14161407
View currentItem = getChildAt(currentPosition - getFirstVisiblePosition());
1408+
1409+
// If a list item is the focused view we try to find a view
1410+
// in the previous item since in reverse the item contents
1411+
// get accessibility focus before the item itself.
1412+
if (currentItem == focused) {
1413+
// This list gets accessibility focus after the last first item.
1414+
final int previoustPosition = currentPosition - getFirstVisiblePosition() - 1;
1415+
if (previoustPosition < 0) {
1416+
return this;
1417+
}
1418+
currentItem = getChildAt(previoustPosition);
1419+
focused = null;
1420+
}
1421+
1422+
// Search for into the item.
14171423
if (currentItem instanceof ViewGroup) {
14181424
ViewGroup currentItemGroup = (ViewGroup) currentItem;
14191425
View nextFocus = FocusFinder.getInstance().findNextFocus(currentItemGroup,
1420-
currentFocus, direction);
1426+
focused, direction);
14211427
if (nextFocus != null && nextFocus != currentItemGroup
1422-
&& nextFocus != currentFocus) {
1428+
&& nextFocus != focused) {
14231429
return nextFocus;
14241430
}
14251431
}
1426-
// Try to move focus to the previous item.
1427-
final int nextPosition = currentPosition - getFirstVisiblePosition() - 1;
1428-
if (nextPosition >= 0) {
1429-
return getChildAt(nextPosition);
1430-
} else {
1431-
return super.focusSearch(this, direction);
1432-
}
1432+
1433+
// If not item content wants focus we give it to the item.
1434+
return currentItem;
14331435
}
14341436
}
14351437
return super.focusSearch(focused, direction);

0 commit comments

Comments
 (0)