summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.xml17
-rw-r--r--core/java/android/view/ViewGroup.java3
-rw-r--r--core/java/android/widget/AbsListView.java2
-rw-r--r--core/java/android/widget/AdapterViewAnimator.java104
-rw-r--r--core/java/android/widget/RemoteViews.java153
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java11
-rw-r--r--core/java/android/widget/StackView.java3
-rw-r--r--core/res/res/values/ids.xml2
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>