diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/view/View.java | 82 | ||||
-rw-r--r-- | core/java/android/view/ViewGroup.java | 18 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 2 |
3 files changed, 88 insertions, 14 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a0e6924..073e8bd 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -57,6 +57,7 @@ import android.util.FloatProperty; import android.util.LayoutDirection; import android.util.Log; import android.util.LongSparseLongArray; +import android.util.MathUtils; import android.util.Pools.SynchronizedPool; import android.util.Property; import android.util.SparseArray; @@ -86,6 +87,7 @@ import static java.lang.Math.max; import com.android.internal.R; import com.android.internal.util.Predicate; import com.android.internal.view.menu.MenuBuilder; + import com.google.android.collect.Lists; import com.google.android.collect.Maps; @@ -4748,12 +4750,43 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this); } + manageFocusHotspot(true, oldFocus); onFocusChanged(true, direction, previouslyFocusedRect); refreshDrawableState(); } } /** + * Forwards focus information to the background drawable, if necessary. When + * the view is gaining focus, <code>v</code> is the previous focus holder. + * When the view is losing focus, <code>v</code> is the next focus holder. + * + * @param focused whether this view is focused + * @param v previous or the next focus holder, or null if none + */ + private void manageFocusHotspot(boolean focused, View v) { + if (mBackground != null && mBackground.supportsHotspots()) { + final Rect r = new Rect(); + if (v != null) { + v.getBoundsOnScreen(r); + final int[] location = new int[2]; + getLocationOnScreen(location); + r.offset(-location[0], -location[1]); + } else { + r.set(mLeft, mTop, mRight, mBottom); + } + + final float x = r.exactCenterX(); + final float y = r.exactCenterY(); + mBackground.setHotspot(Drawable.HOTSPOT_FOCUS, x, y); + + if (!focused) { + mBackground.removeHotspot(Drawable.HOTSPOT_FOCUS); + } + } + } + + /** * Request that a rectangle of this view be visible on the screen, * scrolling if necessary just enough. * @@ -4839,7 +4872,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, System.out.println(this + " clearFocus()"); } - clearFocusInternal(true, true); + clearFocusInternal(null, true, true); } /** @@ -4851,10 +4884,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param refocus when propagate is true, specifies whether to request the * root view place new focus */ - void clearFocusInternal(boolean propagate, boolean refocus) { + void clearFocusInternal(View focused, boolean propagate, boolean refocus) { if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { mPrivateFlags &= ~PFLAG_FOCUSED; + if (hasFocus()) { + manageFocusHotspot(false, focused); + } + if (propagate && mParent != null) { mParent.clearChildFocus(this); } @@ -4888,12 +4925,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * after calling this method. Otherwise, the view hierarchy may be left in * an inconstent state. */ - void unFocus() { + void unFocus(View focused) { if (DBG) { System.out.println(this + " unFocus()"); } - clearFocusInternal(false, false); + clearFocusInternal(focused, false, false); } /** @@ -8909,12 +8946,49 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } break; } + + if (mBackground != null && mBackground.supportsHotspots()) { + manageTouchHotspot(event); + } + return true; } return false; } + private void manageTouchHotspot(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_POINTER_DOWN: { + final int index = event.getActionIndex(); + setPointerHotspot(event, index); + } break; + case MotionEvent.ACTION_MOVE: { + final int count = event.getPointerCount(); + for (int index = 0; index < count; index++) { + setPointerHotspot(event, index); + } + } break; + case MotionEvent.ACTION_POINTER_UP: { + final int actionIndex = event.getActionIndex(); + final int pointerId = event.getPointerId(actionIndex); + mBackground.removeHotspot(pointerId); + } break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mBackground.clearHotspots(); + break; + } + } + + private void setPointerHotspot(MotionEvent event, int index) { + final int id = event.getPointerId(index); + final float x = event.getX(index); + final float y = event.getY(index); + mBackground.setHotspot(id, x, y); + } + /** * @hide */ diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index a1b7ef6..3ee3057 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -598,7 +598,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager @Override void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) { if (mFocused != null) { - mFocused.unFocus(); + mFocused.unFocus(this); mFocused = null; } super.handleFocusGainInternal(direction, previouslyFocusedRect); @@ -616,12 +616,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } // Unfocus us, if necessary - super.unFocus(); + super.unFocus(focused); // We had a previous notion of who had focus. Clear it. if (mFocused != child) { if (mFocused != null) { - mFocused.unFocus(); + mFocused.unFocus(focused); } mFocused = child; @@ -812,14 +812,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * {@inheritDoc} */ @Override - void unFocus() { + void unFocus(View focused) { if (DBG) { System.out.println(this + " unFocus()"); } if (mFocused == null) { - super.unFocus(); + super.unFocus(focused); } else { - mFocused.unFocus(); + mFocused.unFocus(focused); mFocused = null; } } @@ -3827,7 +3827,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager boolean clearChildFocus = false; if (view == mFocused) { - view.unFocus(); + view.unFocus(null); clearChildFocus = true; } @@ -3922,7 +3922,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } if (view == focused) { - view.unFocus(); + view.unFocus(null); clearChildFocus = true; } @@ -4009,7 +4009,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } if (view == focused) { - view.unFocus(); + view.unFocus(null); clearChildFocus = true; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 22c0336..41b0c67 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3331,7 +3331,7 @@ public final class ViewRootImpl implements ViewParent, } else { // There's nothing to focus. Clear and propagate through the // hierarchy, but don't attempt to place new focus. - focused.clearFocusInternal(true, false); + focused.clearFocusInternal(null, true, false); return true; } } |