diff options
| -rw-r--r-- | api/current.xml | 17 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 3 | ||||
| -rw-r--r-- | core/java/android/widget/AbsListView.java | 2 | ||||
| -rw-r--r-- | core/java/android/widget/AdapterViewAnimator.java | 104 | ||||
| -rw-r--r-- | core/java/android/widget/RemoteViews.java | 153 | ||||
| -rw-r--r-- | core/java/android/widget/RemoteViewsAdapter.java | 11 | ||||
| -rw-r--r-- | core/java/android/widget/StackView.java | 3 | ||||
| -rw-r--r-- | core/res/res/values/ids.xml | 2 |
8 files changed, 168 insertions, 127 deletions
diff --git a/api/current.xml b/api/current.xml index 54aae7f3e133..8faa3c362e19 100644 --- a/api/current.xml +++ b/api/current.xml @@ -237817,21 +237817,6 @@ <parameter name="value" type="long"> </parameter> </method> -<method name="setOnClickExtras" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="viewId" type="int"> -</parameter> -<parameter name="extras" type="android.os.Bundle"> -</parameter> -</method> <method name="setOnClickFillInIntent" return="void" abstract="false" @@ -245613,7 +245598,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="arg0" type="T"> +<parameter name="t" type="T"> </parameter> </method> </interface> diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index aef13add5197..0f9312c44e08 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -1298,8 +1298,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Returns true if a child view contains the specified point when transformed * into its coordinate space. * Child must not be null. + * @hide */ - private boolean isTransformedTouchPointInView(float x, float y, View child, + protected boolean isTransformedTouchPointInView(float x, float y, View child, PointF outLocalPoint) { float localX = x + mScrollX - child.mLeft; float localY = y + mScrollY - child.mTop; diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 728c2a7978e5..4e90ecdb918d 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -2501,7 +2501,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te deltaY -= mMotionCorrection; int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY; - + // No need to do all this work if we're not going to move anyway boolean atEdge = false; if (incrementalDeltaY != 0) { diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java index 5ac047cecb93..1f98c88c64ef 100644 --- a/core/java/android/widget/AdapterViewAnimator.java +++ b/core/java/android/widget/AdapterViewAnimator.java @@ -24,16 +24,16 @@ import android.animation.ObjectAnimator; import android.content.Context; import android.content.Intent; import android.content.res.TypedArray; +import android.graphics.Rect; import android.os.Handler; import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; /** * Base class for a {@link AdapterView} that will perform animations @@ -141,6 +141,20 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter> ObjectAnimator mInAnimation; ObjectAnimator mOutAnimation; + /** + * Current touch state. + */ + private int mTouchMode = TOUCH_MODE_NONE; + + /** + * Private touch states. + */ + static final int TOUCH_MODE_NONE = 0; + static final int TOUCH_MODE_DOWN_IN_CURRENT_VIEW = 1; + static final int TOUCH_MODE_HANDLED = 2; + + private Runnable mPendingCheckForTap; + private static final int DEFAULT_ANIMATION_DURATION = 200; public AdapterViewAnimator(Context context) { @@ -528,7 +542,6 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter> // above the layout will end up being ignored since we are currently laying out, so // we post a delayed requestLayout and invalidate mMainQueue.post(new Runnable() { - @Override public void run() { requestLayout(); invalidate(); @@ -551,6 +564,89 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter> } } + void showTapFeedback(View v) { + v.setPressed(true); + } + + void hideTapFeedback(View v) { + v.setPressed(false); + } + + void cancelHandleClick() { + View v = getCurrentView(); + if (v != null) { + hideTapFeedback(v); + } + mTouchMode = TOUCH_MODE_NONE; + } + + final class CheckForTap implements Runnable { + public void run() { + if (mTouchMode == TOUCH_MODE_DOWN_IN_CURRENT_VIEW) { + View v = getCurrentView(); + showTapFeedback(v); + } + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + int action = ev.getAction(); + boolean handled = false; + switch (action) { + case MotionEvent.ACTION_DOWN: { + View v = getCurrentView(); + if (v != null) { + if (isTransformedTouchPointInView(ev.getX(), ev.getY(), v, null)) { + if (mPendingCheckForTap == null) { + mPendingCheckForTap = new CheckForTap(); + } + mTouchMode = TOUCH_MODE_DOWN_IN_CURRENT_VIEW; + postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); + } + } + break; + } + case MotionEvent.ACTION_MOVE: break; + case MotionEvent.ACTION_POINTER_UP: break; + case MotionEvent.ACTION_UP: { + if (mTouchMode == TOUCH_MODE_DOWN_IN_CURRENT_VIEW) { + final View v = getCurrentView(); + if (v != null) { + if (isTransformedTouchPointInView(ev.getX(), ev.getY(), v, null)) { + final Handler handler = getHandler(); + if (handler != null) { + handler.removeCallbacks(mPendingCheckForTap); + } + showTapFeedback(v); + postDelayed(new Runnable() { + public void run() { + hideTapFeedback(v); + post(new Runnable() { + public void run() { + performItemClick(v, 0, 0); + } + }); + } + }, ViewConfiguration.getPressedStateDuration()); + handled = true; + } + } + } + mTouchMode = TOUCH_MODE_NONE; + break; + } + case MotionEvent.ACTION_CANCEL: { + View v = getCurrentView(); + if (v != null) { + hideTapFeedback(v); + } + mTouchMode = TOUCH_MODE_NONE; + } + } + return handled; + } + private void measureChildren() { final int count = getChildCount(); final int childWidth = mMeasuredWidth - mPaddingLeft - mPaddingRight; diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 6ba7b44fe1eb..24165aa7f344 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -45,6 +45,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.LayoutInflater.Filter; import android.view.View.OnClickListener; +import android.widget.AdapterView.OnItemClickListener; /** @@ -110,7 +111,7 @@ public class RemoteViews implements Parcelable, Filter { super(message); } } - + /** * Base class for all actions that can be performed on an * inflated view. @@ -216,8 +217,9 @@ public class RemoteViews implements Parcelable, Filter { "only from RemoteViewsFactory (ie. on collection items)."); return; } - - if (target != null && fillInIntent != null) { + if (target == root) { + target.setTagInternal(com.android.internal.R.id.fillInIntent, fillInIntent); + } else if (target != null && fillInIntent != null) { OnClickListener listener = new OnClickListener() { public void onClick(View v) { // Insure that this view is a child of an AdapterView @@ -237,14 +239,14 @@ public class RemoteViews implements Parcelable, Filter { // Insure that a template pending intent has been set on an ancestor if (!(parent.getTag() instanceof PendingIntent)) { Log.e("RemoteViews", "Attempting setOnClickFillInIntent without" + - " calling setPendingIntentTemplate on parent."); + " calling setPendingIntentTemplate on parent."); return; } PendingIntent pendingIntent = (PendingIntent) parent.getTag(); final float appScale = v.getContext().getResources() - .getCompatibilityInfo().applicationScale; + .getCompatibilityInfo().applicationScale; final int[] pos = new int[2]; v.getLocationOnScreen(pos); @@ -269,88 +271,6 @@ public class RemoteViews implements Parcelable, Filter { public final static int TAG = 9; } - private class SetOnClickExtras extends Action { - public SetOnClickExtras(int id, Bundle extras) { - this.viewId = id; - this.extras = extras; - } - - public SetOnClickExtras(Parcel parcel) { - viewId = parcel.readInt(); - extras = Bundle.CREATOR.createFromParcel(parcel); - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(TAG); - dest.writeInt(viewId); - extras.writeToParcel(dest, 0 /* no flags */); - } - - @Override - public void apply(View root) { - final View target = root.findViewById(viewId); - if (target == null) return; - - if (!mIsWidgetCollectionChild) { - Log.e("RemoteViews", "The method setOnClickExtras is available " + - "only from RemoteViewsFactory (ie. on collection items)."); - return; - } - - if (target != null && extras != null) { - OnClickListener listener = new OnClickListener() { - public void onClick(View v) { - // Insure that this view is a child of an AdapterView - View parent = (View) v.getParent(); - while (!(parent instanceof AdapterView<?>) - && !(parent instanceof AppWidgetHostView)) { - parent = (View) parent.getParent(); - } - - if (parent instanceof AppWidgetHostView) { - // Somehow they've managed to get this far without having - // and AdapterView as a parent. - Log.e("RemoteViews", "Collection item doesn't have AdapterView parent"); - return; - } - - // Insure that a template pending intent has been set on an ancestor - if (!(parent.getTag() instanceof PendingIntent)) { - Log.e("RemoteViews", "Attempting setOnClickExtras without calling " + - "setPendingIntentTemplate on parent."); - return; - } - - PendingIntent pendingIntent = (PendingIntent) parent.getTag(); - - final float appScale = v.getContext().getResources() - .getCompatibilityInfo().applicationScale; - final int[] pos = new int[2]; - v.getLocationOnScreen(pos); - - final Rect rect = new Rect(); - rect.left = (int) (pos[0] * appScale + 0.5f); - rect.top = (int) (pos[1] * appScale + 0.5f); - rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f); - rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f); - - final Intent intent = new Intent(); - intent.setSourceBounds(rect); - intent.putExtras(extras); - startIntentSafely(v.getContext(), pendingIntent, intent); - } - - }; - target.setOnClickListener(listener); - } - } - - int viewId; - Bundle extras; - - public final static int TAG = 7; - } - private class SetPendingIntentTemplate extends Action { public SetPendingIntentTemplate(int id, PendingIntent pendingIntentTemplate) { this.viewId = id; @@ -375,8 +295,52 @@ public class RemoteViews implements Parcelable, Filter { // If the view isn't an AdapterView, setting a PendingIntent template doesn't make sense if (target instanceof AdapterView<?>) { + AdapterView<?> av = (AdapterView<?>) target; // The PendingIntent template is stored in the view's tag. - target.setTag(pendingIntentTemplate); + OnItemClickListener listener = new OnItemClickListener() { + public void onItemClick(AdapterView<?> parent, View view, + int position, long id) { + // The view should be a frame layout + if (view instanceof ViewGroup) { + ViewGroup vg = (ViewGroup) view; + + // AdapterViews contain their children in a frame + // so we need to go one layer deeper here. + if (parent instanceof AdapterViewAnimator) { + vg = (ViewGroup) vg.getChildAt(0); + } + if (vg == null) return; + + Intent fillInIntent = null; + int childCount = vg.getChildCount(); + for (int i = 0; i < childCount; i++) { + Object tag = vg.getChildAt(i).getTag(com.android.internal.R.id.fillInIntent); + if (tag instanceof Intent) { + fillInIntent = (Intent) tag; + break; + } + } + if (fillInIntent == null) return; + + final float appScale = view.getContext().getResources() + .getCompatibilityInfo().applicationScale; + final int[] pos = new int[2]; + view.getLocationOnScreen(pos); + + final Rect rect = new Rect(); + rect.left = (int) (pos[0] * appScale + 0.5f); + rect.top = (int) (pos[1] * appScale + 0.5f); + rect.right = (int) ((pos[0] + view.getWidth()) * appScale + 0.5f); + rect.bottom = (int) ((pos[1] + view.getHeight()) * appScale + 0.5f); + + final Intent intent = new Intent(); + intent.setSourceBounds(rect); + startIntentSafely(view.getContext(), pendingIntentTemplate, fillInIntent); + } + } + }; + av.setOnItemClickListener(listener); + av.setTag(pendingIntentTemplate); } else { Log.e("RemoteViews", "Cannot setPendingIntentTemplate on a view which is not" + "an AdapterView (id: " + viewId + ")"); @@ -973,9 +937,6 @@ public class RemoteViews implements Parcelable, Filter { case SetEmptyView.TAG: mActions.add(new SetEmptyView(parcel)); break; - case SetOnClickExtras.TAG: - mActions.add(new SetOnClickExtras(parcel)); - break; case SetPendingIntentTemplate.TAG: mActions.add(new SetPendingIntentTemplate(parcel)); break; @@ -1239,16 +1200,6 @@ public class RemoteViews implements Parcelable, Filter { } /** - * Being deprecated. See {@link RemoteViews#setOnClickFillInIntent(int, Intent)}. - * - * @param viewId - * @param extras - */ - public void setOnClickExtras(int viewId, Bundle extras) { - addAction(new SetOnClickExtras(viewId, extras)); - } - - /** * When using collections (eg. {@link ListView}, {@link StackView} etc.) in widgets, it is very * costly to set PendingIntents on the individual items, and is hence not permitted. Instead * a single PendingIntent template can be set on the collection, see {@link diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index 5c3561feb030..26eb57cf65ae 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -319,7 +319,7 @@ public class RemoteViewsAdapter extends BaseAdapter { if (mUserLoadingView != null) { // A user-specified loading view View loadingView = mUserLoadingView.apply(parent.getContext(), parent); - loadingView.setTag(new Integer(0)); + loadingView.setTagInternal(com.android.internal.R.id.rowTypeId, new Integer(0)); layout.addView(loadingView); } else { // A default loading view @@ -741,8 +741,11 @@ public class RemoteViewsAdapter extends BaseAdapter { */ private int getConvertViewTypeId(View convertView) { int typeId = -1; - if (convertView != null && convertView.getTag() != null) { - typeId = (Integer) convertView.getTag(); + if (convertView != null) { + Object tag = convertView.getTag(com.android.internal.R.id.rowTypeId); + if (tag != null) { + typeId = (Integer) tag; + } } return typeId; } @@ -781,7 +784,7 @@ public class RemoteViewsAdapter extends BaseAdapter { // Otherwise, create a new view to be returned View newView = rv.apply(context, parent); - newView.setTag(new Integer(typeId)); + newView.setTagInternal(com.android.internal.R.id.rowTypeId, new Integer(typeId)); if (convertView != null) { layout.removeAllViews(); } else { diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java index e6d59842059c..a27e1cc52b1c 100644 --- a/core/java/android/widget/StackView.java +++ b/core/java/android/widget/StackView.java @@ -429,11 +429,14 @@ public class StackView extends AdapterViewAnimator { // We only register this gesture if we've made it this far without a problem mSwipeGestureType = swipeGestureType; + cancelHandleClick(); } } @Override public boolean onTouchEvent(MotionEvent ev) { + super.onTouchEvent(ev); + int action = ev.getAction(); int pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex == INVALID_POINTER) { diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index 33cd10034f7a..b7f177f3aa85 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -70,4 +70,6 @@ <item type="id" name="smallIcon" /> <item type="id" name="custom" /> <item type="id" name="home" /> + <item type="id" name="fillInIntent" /> + <item type="id" name="rowTypeId" /> </resources> |