summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/view/View.java82
-rw-r--r--core/java/android/view/ViewGroup.java18
-rw-r--r--core/java/android/view/ViewRootImpl.java2
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;
}
}