diff options
author | Daniel Sandler <dsandler@android.com> | 2012-03-29 06:09:02 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-03-29 06:09:02 -0700 |
commit | 970de33c8d4e234f65aaf2088531ac4b526be43a (patch) | |
tree | 18593ac8f99b7a44b781273461df16e86e345451 | |
parent | f3fda6962a4bf0d9defebb648065e502b0c10737 (diff) | |
parent | f3b7343246bf20a8024853abe9c8eeef767d26da (diff) | |
download | frameworks_base-970de33c8d4e234f65aaf2088531ac4b526be43a.zip frameworks_base-970de33c8d4e234f65aaf2088531ac4b526be43a.tar.gz frameworks_base-970de33c8d4e234f65aaf2088531ac4b526be43a.tar.bz2 |
Merge "The beginning of expanded notifications."
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | core/java/android/app/Notification.java | 181 | ||||
-rw-r--r-- | core/res/res/layout/notification_template_big_picture.xml | 17 | ||||
-rw-r--r-- | core/res/res/layout/status_bar_latest_event_content.xml | 2 | ||||
-rw-r--r-- | core/res/res/layout/status_bar_latest_event_content_large_icon.xml | 11 | ||||
-rw-r--r-- | core/res/res/values/public.xml | 3 | ||||
-rw-r--r-- | packages/SystemUI/res/layout/status_bar_notification_row.xml | 26 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java | 35 |
8 files changed, 205 insertions, 71 deletions
diff --git a/api/current.txt b/api/current.txt index d6a17e6..8273d23 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3724,6 +3724,7 @@ package android.app { method public android.app.Notification.Builder setSmallIcon(int, int); method public android.app.Notification.Builder setSound(android.net.Uri); method public android.app.Notification.Builder setSound(android.net.Uri, int); + method public android.app.Notification.Builder setSubText(java.lang.CharSequence); method public android.app.Notification.Builder setTicker(java.lang.CharSequence); method public android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews); method public android.app.Notification.Builder setUsesIntruderAlert(boolean); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index bbb6a4e..1356801 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -187,7 +187,6 @@ public class Notification implements Parcelable */ public RemoteViews contentView; - /** * The view that will represent this notification in the pop-up "intruder alert" dialog. * @hide @@ -195,6 +194,14 @@ public class Notification implements Parcelable public RemoteViews intruderView; /** + * A larger version of {@link #contentView}, giving the Notification an + * opportunity to show more detail. The system UI may choose to show this + * instead of the normal content view at its discretion. + * @hide + */ + public RemoteViews bigContentView; + + /** * The bitmap that may escape the bounds of the panel and bar. */ public Bitmap largeIcon; @@ -584,6 +591,9 @@ public class Notification implements Parcelable if (parcel.readInt() != 0) { intruderView = RemoteViews.CREATOR.createFromParcel(parcel); } + if (parcel.readInt() != 0) { + bigContentView = RemoteViews.CREATOR.createFromParcel(parcel); + } } @Override @@ -650,6 +660,9 @@ public class Notification implements Parcelable if (this.intruderView != null) { that.intruderView = this.intruderView.clone(); } + if (this.bigContentView != null) { + that.bigContentView = this.bigContentView.clone(); + } return that; } @@ -747,6 +760,13 @@ public class Notification implements Parcelable } else { parcel.writeInt(0); } + + if (bigContentView != null) { + parcel.writeInt(1); + bigContentView.writeToParcel(parcel, 0); + } else { + parcel.writeInt(0); + } } /** @@ -896,6 +916,7 @@ public class Notification implements Parcelable private CharSequence mContentTitle; private CharSequence mContentText; private CharSequence mContentInfo; + private CharSequence mSubText; private PendingIntent mContentIntent; private RemoteViews mContentView; private PendingIntent mDeleteIntent; @@ -1013,6 +1034,15 @@ public class Notification implements Parcelable } /** + * Set the third line of text in the platform notification template. + * Don't use if you're also using {@link #setProgress(int, int, boolean)}; they occupy the same location in the standard template. + */ + public Builder setSubText(CharSequence text) { + mSubText = text; + return this; + } + + /** * Set the large number at the right-hand side of the notification. This is * equivalent to setContentInfo, although it might show the number in a different * font size for readability. @@ -1025,7 +1055,6 @@ public class Notification implements Parcelable /** * A small piece of additional information pertaining to this notification. * - * The platform template will draw this on the last line of the notification, at the far * right (to the right of a smallIcon if it has been placed there). */ @@ -1037,7 +1066,6 @@ public class Notification implements Parcelable /** * Set the progress this notification represents. * - * The platform template will represent this using a {@link ProgressBar}. */ public Builder setProgress(int max, int progress, boolean indeterminate) { @@ -1050,7 +1078,6 @@ public class Notification implements Parcelable /** * Supply a custom RemoteViews to use instead of the platform template. * - * @see Notification#contentView */ public Builder setContent(RemoteViews views) { @@ -1061,17 +1088,12 @@ public class Notification implements Parcelable /** * Supply a {@link PendingIntent} to be sent when the notification is clicked. * - * As of {@link android.os.Build.VERSION_CODES#HONEYCOMB}, if this field is unset and you * have specified a custom RemoteViews with {@link #setContent(RemoteViews)}, you can use * {@link RemoteViews#setOnClickPendingIntent RemoteViews.setOnClickPendingIntent(int,PendingIntent)} - * to assign PendingIntents to individual views in that custom layout (i.e., to create - - * clickable buttons inside the - * notification view). + * clickable buttons inside the notification view). * - * @see Notification#contentIntent Notification.contentIntent */ public Builder setContentIntent(PendingIntent intent) { @@ -1082,7 +1104,6 @@ public class Notification implements Parcelable /** * Supply a {@link PendingIntent} to send when the notification is cleared explicitly by the user. * - * @see Notification#deleteIntent */ public Builder setDeleteIntent(PendingIntent intent) { @@ -1115,7 +1136,6 @@ public class Notification implements Parcelable * Set the "ticker" text which is displayed in the status bar when the notification first * arrives. * - * @see Notification#tickerText */ public Builder setTicker(CharSequence tickerText) { @@ -1355,20 +1375,28 @@ public class Notification implements Parcelable } } - private RemoteViews makeRemoteViews(int resId) { + private RemoteViews applyStandardTemplate(int resId) { RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId); boolean hasLine3 = false; + boolean hasLine2 = false; + int smallIconImageViewId = R.id.icon; + if (mLargeIcon != null) { + contentView.setImageViewBitmap(R.id.icon, mLargeIcon); + smallIconImageViewId = R.id.right_icon; + } if (mSmallIcon != 0) { - contentView.setImageViewResource(R.id.icon, mSmallIcon); - contentView.setViewVisibility(R.id.icon, View.VISIBLE); + contentView.setImageViewResource(smallIconImageViewId, mSmallIcon); + contentView.setViewVisibility(smallIconImageViewId, View.VISIBLE); } else { - contentView.setViewVisibility(R.id.icon, View.GONE); + contentView.setViewVisibility(smallIconImageViewId, View.GONE); } if (mContentTitle != null) { contentView.setTextViewText(R.id.title, mContentTitle); } if (mContentText != null) { - contentView.setTextViewText(R.id.text, mContentText); + contentView.setTextViewText( + (mSubText != null) ? R.id.text2 : R.id.text, + mContentText); hasLine3 = true; } if (mContentInfo != null) { @@ -1390,12 +1418,19 @@ public class Notification implements Parcelable } else { contentView.setViewVisibility(R.id.info, View.GONE); } - if (mProgressMax != 0 || mProgressIndeterminate) { - contentView.setProgressBar( - R.id.progress, mProgressMax, mProgress, mProgressIndeterminate); - contentView.setViewVisibility(R.id.progress, View.VISIBLE); + + if (mSubText != null) { + contentView.setTextViewText(R.id.text, mSubText); + contentView.setViewVisibility(R.id.text2, View.VISIBLE); } else { - contentView.setViewVisibility(R.id.progress, View.GONE); + contentView.setViewVisibility(R.id.text2, View.GONE); + if (mProgressMax != 0 || mProgressIndeterminate) { + contentView.setProgressBar( + R.id.progress, mProgressMax, mProgress, mProgressIndeterminate); + contentView.setViewVisibility(R.id.progress, View.VISIBLE); + } else { + contentView.setViewVisibility(R.id.progress, View.GONE); + } } if (mWhen != 0) { contentView.setLong(R.id.time, "setTime", mWhen); @@ -1408,9 +1443,7 @@ public class Notification implements Parcelable if (mContentView != null) { return mContentView; } else { - return makeRemoteViews(mLargeIcon == null - ? R.layout.status_bar_latest_event_content - : R.layout.status_bar_latest_event_content_large_icon); + return applyStandardTemplate(R.layout.status_bar_latest_event_content); // no more special large_icon flavor } } @@ -1419,7 +1452,7 @@ public class Notification implements Parcelable return mTickerView; } else { if (mContentView == null) { - return makeRemoteViews(mLargeIcon == null + return applyStandardTemplate(mLargeIcon == null ? R.layout.status_bar_latest_event_ticker : R.layout.status_bar_latest_event_ticker_large_icon); } else { @@ -1516,4 +1549,100 @@ public class Notification implements Parcelable return n; } } + + /** + * @hide because this API is still very rough + * + * This is a "rebuilder": It consumes a Builder object and modifies its output. + * + * This represents the "big picture" style notification, with a large Bitmap atop the usual notification. + * + * Usage: + * <pre class="prettyprint"> + * Notification noti = new Notification.BigPictureStyle( + * new Notification.Builder() + * .setContentTitle("New mail from " + sender.toString()) + * .setContentText(subject) + * .setSmallIcon(R.drawable.new_mail) + * .setLargeIcon(aBitmap)) + * .bigPicture(aBigBitmap) + * .build(); + * </pre> + */ + public static class BigPictureStyle { + private Builder mBuilder; + private Bitmap mPicture; + + public BigPictureStyle(Builder builder) { + mBuilder = builder; + } + + public BigPictureStyle bigPicture(Bitmap b) { + mPicture = b; + return this; + } + + private RemoteViews makeBigContentView() { + RemoteViews contentView = mBuilder.applyStandardTemplate(R.layout.notification_template_big_picture); + + contentView.setImageViewBitmap(R.id.big_picture, mPicture); + + return contentView; + } + + public Notification build() { + Notification wip = mBuilder.getNotification(); + wip.bigContentView = makeBigContentView(); + return wip; + } + } + + /** + * @hide because this API is still very rough + * + * This is a "rebuilder": It consumes a Builder object and modifies its output. + * + * This represents the "big text" style notification, with more area for the main content text to be read in its entirety. + * + * Usage: + * <pre class="prettyprint"> + * Notification noti = new Notification.BigPictureStyle( + * new Notification.Builder() + * .setContentTitle("New mail from " + sender.toString()) + * .setContentText(subject) + * .setSmallIcon(R.drawable.new_mail) + * .setLargeIcon(aBitmap)) + * .bigText(aVeryLongString) + * .build(); + * </pre> + */ + public static class BigTextStyle { + private Builder mBuilder; + private CharSequence mBigText; + + public BigTextStyle(Builder builder) { + mBuilder = builder; + } + + public BigTextStyle bigText(CharSequence cs) { + mBigText = cs; + return this; + } + + private RemoteViews makeBigContentView() { + RemoteViews contentView = mBuilder.applyStandardTemplate(R.layout.status_bar_latest_event_content); + + contentView.setTextViewText(R.id.big_text, mBigText); + contentView.setViewVisibility(R.id.big_text, View.VISIBLE); + contentView.setTextViewText(R.id.text, ""); // XXX: what do do with this spot? + + return contentView; + } + + public Notification build() { + Notification wip = mBuilder.getNotification(); + wip.bigContentView = makeBigContentView(); + return wip; + } + } } diff --git a/core/res/res/layout/notification_template_big_picture.xml b/core/res/res/layout/notification_template_big_picture.xml new file mode 100644 index 0000000..6eb934e --- /dev/null +++ b/core/res/res/layout/notification_template_big_picture.xml @@ -0,0 +1,17 @@ +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="match_parent" + > + <ImageView + android:id="@+id/big_picture" + android:layout_width="match_parent" + android:layout_height="192dp" + android:scaleType="centerCrop" + /> + <include layout="@layout/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="@dimen/notification_large_icon_height" + android:layout_marginTop="192dp" + /> +</FrameLayout>
\ No newline at end of file diff --git a/core/res/res/layout/status_bar_latest_event_content.xml b/core/res/res/layout/status_bar_latest_event_content.xml index ec1bc81..57c149f 100644 --- a/core/res/res/layout/status_bar_latest_event_content.xml +++ b/core/res/res/layout/status_bar_latest_event_content.xml @@ -1,7 +1,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/status_bar_latest_event_content" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="wrap_content" > <ImageView android:id="@+id/icon" android:layout_width="@dimen/notification_large_icon_width" diff --git a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml index a2253b7..5f38e6a 100644 --- a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml +++ b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml @@ -6,6 +6,8 @@ android:orientation="vertical" android:paddingLeft="12dp" android:paddingRight="12dp" + android:paddingTop="4dp" + android:paddingBottom="4dp" > <LinearLayout android:id="@+id/line1" @@ -44,6 +46,13 @@ android:ellipsize="marquee" android:visibility="gone" /> + <TextView android:id="@+id/big_text" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="false" + android:visibility="gone" + /> <LinearLayout android:id="@+id/line3" android:layout_width="match_parent" @@ -70,7 +79,7 @@ android:gravity="center" android:paddingLeft="8dp" /> - <ImageView android:id="@+id/icon" + <ImageView android:id="@+id/right_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index e1bc33b..9c5f4d6 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -198,6 +198,8 @@ <java-symbol type="id" name="action0" /> <java-symbol type="id" name="action1" /> <java-symbol type="id" name="action2" /> + <java-symbol type="id" name="big_picture" /> + <java-symbol type="id" name="big_text" /> <java-symbol type="attr" name="actionModeShareDrawable" /> <java-symbol type="attr" name="alertDialogCenterButtons" /> @@ -1070,6 +1072,7 @@ <java-symbol type="layout" name="zoom_controls" /> <java-symbol type="layout" name="zoom_magnify" /> <java-symbol type="layout" name="notification_intruder_content" /> + <java-symbol type="layout" name="notification_template_big_picture" /> <java-symbol type="anim" name="slide_in_child_bottom" /> <java-symbol type="anim" name="slide_in_right" /> diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml index abbc89a..c307c6e 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_row.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml @@ -1,4 +1,4 @@ -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="@dimen/notification_height" > @@ -7,31 +7,17 @@ android:id="@+id/veto" android:layout_width="48dp" android:layout_height="match_parent" - android:layout_centerVertical="true" - android:layout_alignParentRight="true" + android:gravity="right" android:layout_marginRight="-80dp" android:background="@null" android:paddingRight="8dp" android:paddingLeft="8dp" /> - <ImageView - android:id="@+id/large_icon" - android:layout_width="@android:dimen/notification_large_icon_width" - android:layout_height="@android:dimen/notification_large_icon_height" - android:layout_alignParentTop="true" - android:layout_alignParentLeft="true" - android:scaleType="center" - android:clickable="true" - android:background="@*android:drawable/notify_panel_notification_icon_bg_tile" - /> - <com.android.systemui.statusbar.LatestItemView android:id="@+id/content" android:layout_width="match_parent" - android:layout_height="64dp" - android:layout_alignParentTop="true" - android:layout_toRightOf="@id/large_icon" - android:layout_alignParentRight="true" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/notification_divider_height" android:focusable="true" android:clickable="true" android:background="@drawable/notification_row_bg" @@ -40,8 +26,8 @@ <View android:layout_width="match_parent" android:layout_height="@dimen/notification_divider_height" - android:layout_alignParentBottom="true" + android:gravity="bottom" android:background="@drawable/status_bar_notification_row_background_color" /> -</RelativeLayout> +</FrameLayout> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 85e0a8a..023b21f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -675,10 +675,8 @@ public class PhoneStatusBar extends BaseStatusBar { if (contentIntent != null) { final View.OnClickListener listener = new NotificationClicker(contentIntent, notification.pkg, notification.tag, notification.id); - oldEntry.largeIcon.setOnClickListener(listener); oldEntry.content.setOnClickListener(listener); } else { - oldEntry.largeIcon.setOnClickListener(null); oldEntry.content.setOnClickListener(null); } // Update the icon. @@ -690,13 +688,6 @@ public class PhoneStatusBar extends BaseStatusBar { handleNotificationError(key, notification, "Couldn't update icon: " + ic); return; } - // Update the large icon - if (notification.notification.largeIcon != null) { - oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon); - } else { - oldEntry.largeIcon.getLayoutParams().width = 0; - oldEntry.largeIcon.setVisibility(View.INVISIBLE); - } } catch (RuntimeException e) { // It failed to add cleanly. Log, and remove the view from the panel. @@ -878,7 +869,10 @@ public class PhoneStatusBar extends BaseStatusBar { private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) { StatusBarNotification sbn = entry.notification; - RemoteViews remoteViews = sbn.notification.contentView; + // XXX: temporary: while testing big notifications, auto-expand all of them + final boolean big = (sbn.notification.bigContentView != null); + RemoteViews remoteViews = big ? sbn.notification.bigContentView + : sbn.notification.contentView; if (remoteViews == null) { return false; } @@ -887,20 +881,18 @@ public class PhoneStatusBar extends BaseStatusBar { LayoutInflater inflater = (LayoutInflater)mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false); + ViewGroup.LayoutParams lp = row.getLayoutParams(); + if (big) { + lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; + } else { + lp.height = mContext.getResources().getDimensionPixelSize(R.dimen.notification_height); + } + row.setLayoutParams(lp); View vetoButton = updateNotificationVetoButton(row, sbn); vetoButton.setContentDescription(mContext.getString( R.string.accessibility_remove_notification)); - // the large icon - ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon); - if (sbn.notification.largeIcon != null) { - largeIcon.setImageBitmap(sbn.notification.largeIcon); - largeIcon.setContentDescription(sbn.notification.tickerText); - } else { - largeIcon.getLayoutParams().width = 0; - largeIcon.setVisibility(View.INVISIBLE); - } - largeIcon.setContentDescription(sbn.notification.tickerText); + // NB: the large icon is now handled entirely by the template // bind the click event to the content area ViewGroup content = (ViewGroup)row.findViewById(R.id.content); @@ -911,10 +903,8 @@ public class PhoneStatusBar extends BaseStatusBar { if (contentIntent != null) { final View.OnClickListener listener = new NotificationClicker(contentIntent, sbn.pkg, sbn.tag, sbn.id); - largeIcon.setOnClickListener(listener); content.setOnClickListener(listener); } else { - largeIcon.setOnClickListener(null); content.setOnClickListener(null); } @@ -940,7 +930,6 @@ public class PhoneStatusBar extends BaseStatusBar { entry.row = row; entry.content = content; entry.expanded = expanded; - entry.largeIcon = largeIcon; return true; } |