/// <summary>Find the nearest touchable view to the specified view.</summary> /// <remarks>Find the nearest touchable view to the specified view.</remarks> /// <param name="root">The root of the tree in which to search</param> /// <param name="x">X coordinate from which to start the search</param> /// <param name="y">Y coordinate from which to start the search</param> /// <param name="direction">Direction to look</param> /// <param name="deltas"> /// Offset from the <x, y> to the edge of the nearest view. Note that this array /// may already be populated with values. /// </param> /// <returns>The nearest touchable view, or null if none exists.</returns> public virtual android.view.View findNearestTouchable(android.view.ViewGroup root , int x, int y, int direction, int[] deltas) { java.util.ArrayList <android.view.View> touchables = root.getTouchables(); int minDistance = int.MaxValue; android.view.View closest = null; int numTouchables = touchables.size(); int edgeSlop = android.view.ViewConfiguration.get(root.mContext).getScaledEdgeSlop (); android.graphics.Rect closestBounds = new android.graphics.Rect(); android.graphics.Rect touchableBounds = mOtherRect; { for (int i = 0; i < numTouchables; i++) { android.view.View touchable = touchables.get(i); // get visible bounds of other view in same coordinate system touchable.getDrawingRect(touchableBounds); root.offsetRectBetweenParentAndChild(touchable, touchableBounds, true, true); if (!isTouchCandidate(x, y, touchableBounds, direction)) { continue; } int distance = int.MaxValue; switch (direction) { case android.view.View.FOCUS_LEFT: { distance = x - touchableBounds.right + 1; break; } case android.view.View.FOCUS_RIGHT: { distance = touchableBounds.left; break; } case android.view.View.FOCUS_UP: { distance = y - touchableBounds.bottom + 1; break; } case android.view.View.FOCUS_DOWN: { distance = touchableBounds.top; break; } } if (distance < edgeSlop) { // Give preference to innermost views if (closest == null || closestBounds.contains(touchableBounds) || (!touchableBounds .contains(closestBounds) && distance < minDistance)) { minDistance = distance; closest = touchable; closestBounds.set(touchableBounds); switch (direction) { case android.view.View.FOCUS_LEFT: { deltas[0] = -distance; break; } case android.view.View.FOCUS_RIGHT: { deltas[0] = distance; break; } case android.view.View.FOCUS_UP: { deltas[1] = -distance; break; } case android.view.View.FOCUS_DOWN: { deltas[1] = distance; break; } } } } } } return(closest); }
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); }