private android.view.View findNextFocus(android.view.ViewGroup root, android.view.View focused, android.graphics.Rect focusedRect, int direction) { java.util.ArrayList <android.view.View> focusables = root.getFocusables(direction); if (focusables.isEmpty()) { // The focus cannot change. return(null); } if (direction == android.view.View.FOCUS_FORWARD || direction == android.view.View .FOCUS_BACKWARD) { if (focused != null && !focusables.contains(focused)) { // Add the currently focused view to the list to have it sorted // along with the other views. focusables.add(focused); } try { // Note: This sort is stable. mSequentialFocusComparator.setRoot(root); java.util.Collections.sort(focusables, mSequentialFocusComparator); } finally { mSequentialFocusComparator.recycle(); } int count = focusables.size(); switch (direction) { case android.view.View.FOCUS_FORWARD: { if (focused != null) { int position = focusables.lastIndexOf(focused); if (position >= 0 && position + 1 < count) { return(focusables.get(position + 1)); } } return(focusables.get(0)); } case android.view.View.FOCUS_BACKWARD: { if (focused != null) { int position = focusables.indexOf(focused); if (position > 0) { return(focusables.get(position - 1)); } } return(focusables.get(count - 1)); } } return(null); } // initialize the best candidate to something impossible // (so the first plausible view will become the best choice) mBestCandidateRect.set(focusedRect); switch (direction) { case android.view.View.FOCUS_LEFT: { mBestCandidateRect.offset(focusedRect.width() + 1, 0); break; } case android.view.View.FOCUS_RIGHT: { mBestCandidateRect.offset(-(focusedRect.width() + 1), 0); break; } case android.view.View.FOCUS_UP: { mBestCandidateRect.offset(0, focusedRect.height() + 1); break; } case android.view.View.FOCUS_DOWN: { mBestCandidateRect.offset(0, -(focusedRect.height() + 1)); break; } } android.view.View closest = null; int numFocusables = focusables.size(); { for (int i = 0; i < numFocusables; i++) { android.view.View focusable = focusables.get(i); // only interested in other non-root views if (focusable == focused || focusable == root) { continue; } // get visible bounds of other view in same coordinate system focusable.getDrawingRect(mOtherRect); root.offsetDescendantRectToMyCoords(focusable, mOtherRect); if (isBetterCandidate(direction, focusedRect, mOtherRect, mBestCandidateRect)) { mBestCandidateRect.set(mOtherRect); closest = focusable; } } } return(closest); }