AppWidgetHostViewpublic class AppWidgetHostView extends android.widget.FrameLayout Provides the glue to show AppWidget views. This class offers automatic animation
between updates, and will try recycling old views for each incoming
{@link RemoteViews}. |
Fields Summary |
---|
static final String | TAG | static final boolean | LOGD | static final boolean | CROSSFADE | static final int | VIEW_MODE_NOINIT | static final int | VIEW_MODE_CONTENT | static final int | VIEW_MODE_ERROR | static final int | VIEW_MODE_DEFAULT | static final int | FADE_DURATION | static final LayoutInflater.Filter | sInflaterFilter | android.content.Context | mContext | int | mAppWidgetId | AppWidgetProviderInfo | mInfo | android.view.View | mView | int | mViewMode | int | mLayoutId | long | mFadeStartTime | android.graphics.Bitmap | mOld | android.graphics.Paint | mOldPaint |
Constructors Summary |
---|
public AppWidgetHostView(android.content.Context context)Create a host view. Uses default fade animations.
this(context, android.R.anim.fade_in, android.R.anim.fade_out);
| public AppWidgetHostView(android.content.Context context, int animationIn, int animationOut)Create a host view. Uses specified animations when pushing
{@link #updateAppWidget(RemoteViews)}.
super(context);
mContext = context;
|
Methods Summary |
---|
protected boolean | drawChild(android.graphics.Canvas canvas, android.view.View child, long drawingTime)
if (CROSSFADE) {
int alpha;
int l = child.getLeft();
int t = child.getTop();
if (mFadeStartTime > 0) {
alpha = (int)(((drawingTime-mFadeStartTime)*255)/FADE_DURATION);
if (alpha > 255) {
alpha = 255;
}
Log.d(TAG, "drawChild alpha=" + alpha + " l=" + l + " t=" + t
+ " w=" + child.getWidth());
if (alpha != 255 && mOld != null) {
mOldPaint.setAlpha(255-alpha);
//canvas.drawBitmap(mOld, l, t, mOldPaint);
}
} else {
alpha = 255;
}
int restoreTo = canvas.saveLayerAlpha(l, t, child.getWidth(), child.getHeight(), alpha,
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
boolean rv = super.drawChild(canvas, child, drawingTime);
canvas.restoreToCount(restoreTo);
if (alpha < 255) {
invalidate();
} else {
mFadeStartTime = -1;
if (mOld != null) {
mOld.recycle();
mOld = null;
}
}
return rv;
} else {
return super.drawChild(canvas, child, drawingTime);
}
| public int | getAppWidgetId()
return mAppWidgetId;
| public AppWidgetProviderInfo | getAppWidgetInfo()
return mInfo;
| protected android.view.View | getDefaultView()Inflate and return the default layout requested by AppWidget provider.
View defaultView = null;
Exception exception = null;
try {
if (mInfo != null) {
Context theirContext = mContext.createPackageContext(
mInfo.provider.getPackageName(), 0 /* no flags */);
LayoutInflater inflater = (LayoutInflater)
theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater = inflater.cloneInContext(theirContext);
inflater.setFilter(sInflaterFilter);
defaultView = inflater.inflate(mInfo.initialLayout, this, false);
} else {
Log.w(TAG, "can't inflate defaultView because mInfo is missing");
}
} catch (PackageManager.NameNotFoundException e) {
exception = e;
} catch (RuntimeException e) {
exception = e;
}
if (exception != null && LOGD) {
Log.w(TAG, "Error inflating AppWidget " + mInfo, exception);
}
if (defaultView == null) {
if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error");
defaultView = getErrorView();
}
return defaultView;
| protected android.view.View | getErrorView()Inflate and return a view that represents an error state.
TextView tv = new TextView(mContext);
tv.setText(com.android.internal.R.string.gadget_host_error_inflating);
// TODO: get this color from somewhere.
tv.setBackgroundColor(Color.argb(127, 0, 0, 0));
return tv;
| protected void | prepareView(android.view.View view)Prepare the given view to be shown. This might include adjusting
{@link FrameLayout.LayoutParams} before inserting.
// Take requested dimensions from parent, but apply default gravity.
ViewGroup.LayoutParams requested = view.getLayoutParams();
if (requested == null) {
requested = new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
}
FrameLayout.LayoutParams params =
new FrameLayout.LayoutParams(requested.width, requested.height);
params.gravity = Gravity.CENTER;
view.setLayoutParams(params);
| public void | setAppWidget(int appWidgetId, AppWidgetProviderInfo info)Set the AppWidget that will be displayed by this view.
mAppWidgetId = appWidgetId;
mInfo = info;
| public void | updateAppWidget(android.widget.RemoteViews remoteViews)Process a set of {@link RemoteViews} coming in as an update from the
AppWidget provider. Will animate into these new views as needed.
if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
boolean recycled = false;
View content = null;
Exception exception = null;
// Capture the old view into a bitmap so we can do the crossfade.
if (CROSSFADE) {
if (mFadeStartTime < 0) {
if (mView != null) {
final int width = mView.getWidth();
final int height = mView.getHeight();
try {
mOld = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError e) {
// we just won't do the fade
mOld = null;
}
if (mOld != null) {
//mView.drawIntoBitmap(mOld);
}
}
}
}
if (remoteViews == null) {
if (mViewMode == VIEW_MODE_DEFAULT) {
// We've already done this -- nothing to do.
return;
}
content = getDefaultView();
mLayoutId = -1;
mViewMode = VIEW_MODE_DEFAULT;
} else {
int layoutId = remoteViews.getLayoutId();
// If our stale view has been prepared to match active, and the new
// layout matches, try recycling it
if (content == null && layoutId == mLayoutId) {
try {
remoteViews.reapply(mContext, mView);
content = mView;
recycled = true;
if (LOGD) Log.d(TAG, "was able to recycled existing layout");
} catch (RuntimeException e) {
exception = e;
}
}
// Try normal RemoteView inflation
if (content == null) {
try {
content = remoteViews.apply(mContext, this);
if (LOGD) Log.d(TAG, "had to inflate new layout");
} catch (RuntimeException e) {
exception = e;
}
}
mLayoutId = layoutId;
mViewMode = VIEW_MODE_CONTENT;
}
if (content == null) {
if (mViewMode == VIEW_MODE_ERROR) {
// We've already done this -- nothing to do.
return ;
}
Log.w(TAG, "updateAppWidget couldn't find any view, using error view", exception);
content = getErrorView();
mViewMode = VIEW_MODE_ERROR;
}
if (!recycled) {
prepareView(content);
addView(content);
}
if (mView != content) {
removeView(mView);
mView = content;
}
if (CROSSFADE) {
if (mFadeStartTime < 0) {
// if there is already an animation in progress, don't do anything --
// the new view will pop in on top of the old one during the cross fade,
// and that looks okay.
mFadeStartTime = SystemClock.uptimeMillis();
invalidate();
}
}
|
|