am 06dc03f2: Let RemoteViews nest children, allow ViewFlipper.

Merge commit '06dc03f2cf98862717ba1aa0e858897363abc369' into eclair-mr2-plus-aosp

* commit '06dc03f2cf98862717ba1aa0e858897363abc369':
  Let RemoteViews nest children, allow ViewFlipper.
This commit is contained in:
Jeff Sharkey
2009-11-09 12:03:40 -08:00
committed by Android Git Automerger
5 changed files with 239 additions and 17 deletions

View File

@@ -1967,6 +1967,17 @@
visibility="public"
>
</field>
<field name="autoStart"
type="int"
transient="false"
volatile="false"
value="16843446"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="autoText"
type="int"
transient="false"
@@ -190341,6 +190352,21 @@
<parameter name="parcel" type="android.os.Parcel">
</parameter>
</constructor>
<method name="addView"
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="nestedView" type="android.widget.RemoteViews">
</parameter>
</method>
<method name="apply"
return="android.view.View"
abstract="false"
@@ -190417,6 +190443,19 @@
<parameter name="v" type="android.view.View">
</parameter>
</method>
<method name="removeAllViews"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="viewId" type="int">
</parameter>
</method>
<method name="setBitmap"
return="void"
abstract="false"
@@ -197002,6 +197041,17 @@
<parameter name="attrs" type="android.util.AttributeSet">
</parameter>
</constructor>
<method name="isAutoStart"
return="boolean"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="isFlipping"
return="boolean"
abstract="false"
@@ -197013,6 +197063,19 @@
visibility="public"
>
</method>
<method name="setAutoStart"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="autoStart" type="boolean">
</parameter>
</method>
<method name="setFlipInterval"
return="void"
abstract="false"

View File

@@ -457,6 +457,46 @@ public class RemoteViews implements Parcelable, Filter {
}
}
/**
* Equivalent to calling {@link ViewGroup#addView(View)} after inflating the
* given {@link RemoteViews}, or calling {@link ViewGroup#removeAllViews()}
* when null. This allows users to build "nested" {@link RemoteViews}.
*/
private class ViewGroupAction extends Action {
public ViewGroupAction(int viewId, RemoteViews nestedViews) {
this.viewId = viewId;
this.nestedViews = nestedViews;
}
public ViewGroupAction(Parcel parcel) {
viewId = parcel.readInt();
nestedViews = parcel.readParcelable(null);
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(TAG);
dest.writeInt(viewId);
dest.writeParcelable(nestedViews, 0 /* no flags */);
}
@Override
public void apply(View root) {
final Context context = root.getContext();
final ViewGroup target = (ViewGroup) root.findViewById(viewId);
if (nestedViews != null) {
// Inflate nested views and add as children
target.addView(nestedViews.apply(context, target));
} else if (target != null) {
// Clear all children when nested views omitted
target.removeAllViews();
}
}
int viewId;
RemoteViews nestedViews;
public final static int TAG = 4;
}
/**
* Create a new RemoteViews object that will display the views contained
@@ -493,6 +533,9 @@ public class RemoteViews implements Parcelable, Filter {
case ReflectionAction.TAG:
mActions.add(new ReflectionAction(parcel));
break;
case ViewGroupAction.TAG:
mActions.add(new ViewGroupAction(parcel));
break;
default:
throw new ActionException("Tag " + tag + " not found");
}
@@ -519,7 +562,31 @@ public class RemoteViews implements Parcelable, Filter {
}
mActions.add(a);
}
/**
* Equivalent to calling {@link ViewGroup#addView(View)} after inflating the
* given {@link RemoteViews}. This allows users to build "nested"
* {@link RemoteViews}. In cases where consumers of {@link RemoteViews} may
* recycle layouts, use {@link #removeAllViews(int)} to clear any existing
* children.
*
* @param viewId The id of the parent {@link ViewGroup} to add child into.
* @param nestedView {@link RemoteViews} that describes the child.
*/
public void addView(int viewId, RemoteViews nestedView) {
addAction(new ViewGroupAction(viewId, nestedView));
}
/**
* Equivalent to calling {@link ViewGroup#removeAllViews()}.
*
* @param viewId The id of the parent {@link ViewGroup} to remove all
* children from.
*/
public void removeAllViews(int viewId) {
addAction(new ViewGroupAction(viewId, null));
}
/**
* Equivalent to calling View.setVisibility
*

View File

@@ -16,8 +16,10 @@
package android.widget;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
@@ -30,10 +32,19 @@ import android.widget.RemoteViews.RemoteView;
* requested, can automatically flip between each child at a regular interval.
*
* @attr ref android.R.styleable#ViewFlipper_flipInterval
* @attr ref android.R.styleable#ViewFlipper_autoStart
*/
@RemoteView
public class ViewFlipper extends ViewAnimator {
private int mFlipInterval = 3000;
private boolean mKeepFlipping = false;
private static final int DEFAULT_INTERVAL = 3000;
private int mFlipInterval = DEFAULT_INTERVAL;
private boolean mAutoStart = false;
private boolean mRunning = false;
private boolean mStarted = false;
private boolean mVisible = false;
private boolean mUserPresent = true;
public ViewFlipper(Context context) {
super(context);
@@ -44,14 +55,62 @@ public class ViewFlipper extends ViewAnimator {
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.ViewFlipper);
mFlipInterval = a.getInt(com.android.internal.R.styleable.ViewFlipper_flipInterval,
3000);
mFlipInterval = a.getInt(
com.android.internal.R.styleable.ViewFlipper_flipInterval, DEFAULT_INTERVAL);
mAutoStart = a.getBoolean(
com.android.internal.R.styleable.ViewFlipper_autoStart, false);
a.recycle();
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mUserPresent = false;
updateRunning();
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
mUserPresent = true;
updateRunning();
}
}
};
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
// Listen for broadcasts related to user-presence
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
getContext().registerReceiver(mReceiver, filter);
if (mAutoStart) {
// Automatically start when requested
startFlipping();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mVisible = false;
getContext().unregisterReceiver(mReceiver);
updateRunning();
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
mVisible = visibility == VISIBLE;
updateRunning();
}
/**
* How long to wait before flipping to the next view
*
*
* @param milliseconds
* time in milliseconds
*/
@@ -64,26 +123,57 @@ public class ViewFlipper extends ViewAnimator {
* Start a timer to cycle through child views
*/
public void startFlipping() {
if (!mKeepFlipping) {
mKeepFlipping = true;
showOnly(mWhichChild);
Message msg = mHandler.obtainMessage(FLIP_MSG);
mHandler.sendMessageDelayed(msg, mFlipInterval);
}
mStarted = true;
updateRunning();
}
/**
* No more flips
*/
public void stopFlipping() {
mKeepFlipping = false;
mStarted = false;
updateRunning();
}
/**
* Internal method to start or stop dispatching flip {@link Message} based
* on {@link #mRunning} and {@link #mVisible} state.
*/
private void updateRunning() {
boolean running = mVisible && mStarted && mUserPresent;
if (running != mRunning) {
if (running) {
showOnly(mWhichChild);
Message msg = mHandler.obtainMessage(FLIP_MSG);
mHandler.sendMessageDelayed(msg, mFlipInterval);
} else {
mHandler.removeMessages(FLIP_MSG);
}
mRunning = running;
}
}
/**
* Returns true if the child views are flipping.
*/
public boolean isFlipping() {
return mKeepFlipping;
return mStarted;
}
/**
* Set if this view automatically calls {@link #startFlipping()} when it
* becomes attached to a window.
*/
public void setAutoStart(boolean autoStart) {
mAutoStart = autoStart;
}
/**
* Returns true if this view automatically calls {@link #startFlipping()}
* when it becomes attached to a window.
*/
public boolean isAutoStart() {
return mAutoStart;
}
private final int FLIP_MSG = 1;
@@ -92,7 +182,7 @@ public class ViewFlipper extends ViewAnimator {
@Override
public void handleMessage(Message msg) {
if (msg.what == FLIP_MSG) {
if (mKeepFlipping) {
if (mRunning) {
showNext();
msg = obtainMessage(FLIP_MSG);
sendMessageDelayed(msg, mFlipInterval);

View File

@@ -2138,6 +2138,8 @@
</declare-styleable>
<declare-styleable name="ViewFlipper">
<attr name="flipInterval" format="integer" min="0" />
<!-- When true, automatically start animating -->
<attr name="autoStart" format="boolean" />
</declare-styleable>
<declare-styleable name="ViewSwitcher">
</declare-styleable>

View File

@@ -1201,8 +1201,8 @@
<public type="attr" name="quickContactBadgeStyleSmallWindowSmall" />
<public type="attr" name="quickContactBadgeStyleSmallWindowMedium" />
<public type="attr" name="quickContactBadgeStyleSmallWindowLarge" />
<public type="attr" name="wallpaperAuthor" />
<public type="attr" name="wallpaperDescription" />
<public type="attr" name="autoStart" />
</resources>