Skip to content

Commit 970de33

Browse files
dsandlerAndroid (Google) Code Review
authored andcommitted
Merge "The beginning of expanded notifications."
2 parents f3fda69 + f3b7343 commit 970de33

File tree

8 files changed

+205
-71
lines changed

8 files changed

+205
-71
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3724,6 +3724,7 @@ package android.app {
37243724
method public android.app.Notification.Builder setSmallIcon(int, int);
37253725
method public android.app.Notification.Builder setSound(android.net.Uri);
37263726
method public android.app.Notification.Builder setSound(android.net.Uri, int);
3727+
method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
37273728
method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
37283729
method public android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
37293730
method public android.app.Notification.Builder setUsesIntruderAlert(boolean);

core/java/android/app/Notification.java

Lines changed: 155 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,20 @@ public class Notification implements Parcelable
187187
*/
188188
public RemoteViews contentView;
189189

190-
191190
/**
192191
* The view that will represent this notification in the pop-up "intruder alert" dialog.
193192
* @hide
194193
*/
195194
public RemoteViews intruderView;
196195

196+
/**
197+
* A larger version of {@link #contentView}, giving the Notification an
198+
* opportunity to show more detail. The system UI may choose to show this
199+
* instead of the normal content view at its discretion.
200+
* @hide
201+
*/
202+
public RemoteViews bigContentView;
203+
197204
/**
198205
* The bitmap that may escape the bounds of the panel and bar.
199206
*/
@@ -584,6 +591,9 @@ public Notification(Parcel parcel)
584591
if (parcel.readInt() != 0) {
585592
intruderView = RemoteViews.CREATOR.createFromParcel(parcel);
586593
}
594+
if (parcel.readInt() != 0) {
595+
bigContentView = RemoteViews.CREATOR.createFromParcel(parcel);
596+
}
587597
}
588598

589599
@Override
@@ -650,6 +660,9 @@ public Notification clone() {
650660
if (this.intruderView != null) {
651661
that.intruderView = this.intruderView.clone();
652662
}
663+
if (this.bigContentView != null) {
664+
that.bigContentView = this.bigContentView.clone();
665+
}
653666

654667
return that;
655668
}
@@ -747,6 +760,13 @@ public void writeToParcel(Parcel parcel, int flags)
747760
} else {
748761
parcel.writeInt(0);
749762
}
763+
764+
if (bigContentView != null) {
765+
parcel.writeInt(1);
766+
bigContentView.writeToParcel(parcel, 0);
767+
} else {
768+
parcel.writeInt(0);
769+
}
750770
}
751771

752772
/**
@@ -896,6 +916,7 @@ public static class Builder {
896916
private CharSequence mContentTitle;
897917
private CharSequence mContentText;
898918
private CharSequence mContentInfo;
919+
private CharSequence mSubText;
899920
private PendingIntent mContentIntent;
900921
private RemoteViews mContentView;
901922
private PendingIntent mDeleteIntent;
@@ -1012,6 +1033,15 @@ public Builder setContentText(CharSequence text) {
10121033
return this;
10131034
}
10141035

1036+
/**
1037+
* Set the third line of text in the platform notification template.
1038+
* Don't use if you're also using {@link #setProgress(int, int, boolean)}; they occupy the same location in the standard template.
1039+
*/
1040+
public Builder setSubText(CharSequence text) {
1041+
mSubText = text;
1042+
return this;
1043+
}
1044+
10151045
/**
10161046
* Set the large number at the right-hand side of the notification. This is
10171047
* equivalent to setContentInfo, although it might show the number in a different
@@ -1025,7 +1055,6 @@ public Builder setNumber(int number) {
10251055
/**
10261056
* A small piece of additional information pertaining to this notification.
10271057
*
1028-
10291058
* The platform template will draw this on the last line of the notification, at the far
10301059
* right (to the right of a smallIcon if it has been placed there).
10311060
*/
@@ -1037,7 +1066,6 @@ public Builder setContentInfo(CharSequence info) {
10371066
/**
10381067
* Set the progress this notification represents.
10391068
*
1040-
10411069
* The platform template will represent this using a {@link ProgressBar}.
10421070
*/
10431071
public Builder setProgress(int max, int progress, boolean indeterminate) {
@@ -1050,7 +1078,6 @@ public Builder setProgress(int max, int progress, boolean indeterminate) {
10501078
/**
10511079
* Supply a custom RemoteViews to use instead of the platform template.
10521080
*
1053-
10541081
* @see Notification#contentView
10551082
*/
10561083
public Builder setContent(RemoteViews views) {
@@ -1061,17 +1088,12 @@ public Builder setContent(RemoteViews views) {
10611088
/**
10621089
* Supply a {@link PendingIntent} to be sent when the notification is clicked.
10631090
*
1064-
10651091
* As of {@link android.os.Build.VERSION_CODES#HONEYCOMB}, if this field is unset and you
10661092
* have specified a custom RemoteViews with {@link #setContent(RemoteViews)}, you can use
10671093
* {@link RemoteViews#setOnClickPendingIntent RemoteViews.setOnClickPendingIntent(int,PendingIntent)}
1068-
10691094
* to assign PendingIntents to individual views in that custom layout (i.e., to create
1070-
1071-
* clickable buttons inside the
1072-
* notification view).
1095+
* clickable buttons inside the notification view).
10731096
*
1074-
10751097
* @see Notification#contentIntent Notification.contentIntent
10761098
*/
10771099
public Builder setContentIntent(PendingIntent intent) {
@@ -1082,7 +1104,6 @@ public Builder setContentIntent(PendingIntent intent) {
10821104
/**
10831105
* Supply a {@link PendingIntent} to send when the notification is cleared explicitly by the user.
10841106
*
1085-
10861107
* @see Notification#deleteIntent
10871108
*/
10881109
public Builder setDeleteIntent(PendingIntent intent) {
@@ -1115,7 +1136,6 @@ public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {
11151136
* Set the "ticker" text which is displayed in the status bar when the notification first
11161137
* arrives.
11171138
*
1118-
11191139
* @see Notification#tickerText
11201140
*/
11211141
public Builder setTicker(CharSequence tickerText) {
@@ -1355,20 +1375,28 @@ private void setFlag(int mask, boolean value) {
13551375
}
13561376
}
13571377

1358-
private RemoteViews makeRemoteViews(int resId) {
1378+
private RemoteViews applyStandardTemplate(int resId) {
13591379
RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId);
13601380
boolean hasLine3 = false;
1381+
boolean hasLine2 = false;
1382+
int smallIconImageViewId = R.id.icon;
1383+
if (mLargeIcon != null) {
1384+
contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
1385+
smallIconImageViewId = R.id.right_icon;
1386+
}
13611387
if (mSmallIcon != 0) {
1362-
contentView.setImageViewResource(R.id.icon, mSmallIcon);
1363-
contentView.setViewVisibility(R.id.icon, View.VISIBLE);
1388+
contentView.setImageViewResource(smallIconImageViewId, mSmallIcon);
1389+
contentView.setViewVisibility(smallIconImageViewId, View.VISIBLE);
13641390
} else {
1365-
contentView.setViewVisibility(R.id.icon, View.GONE);
1391+
contentView.setViewVisibility(smallIconImageViewId, View.GONE);
13661392
}
13671393
if (mContentTitle != null) {
13681394
contentView.setTextViewText(R.id.title, mContentTitle);
13691395
}
13701396
if (mContentText != null) {
1371-
contentView.setTextViewText(R.id.text, mContentText);
1397+
contentView.setTextViewText(
1398+
(mSubText != null) ? R.id.text2 : R.id.text,
1399+
mContentText);
13721400
hasLine3 = true;
13731401
}
13741402
if (mContentInfo != null) {
@@ -1390,12 +1418,19 @@ private RemoteViews makeRemoteViews(int resId) {
13901418
} else {
13911419
contentView.setViewVisibility(R.id.info, View.GONE);
13921420
}
1393-
if (mProgressMax != 0 || mProgressIndeterminate) {
1394-
contentView.setProgressBar(
1395-
R.id.progress, mProgressMax, mProgress, mProgressIndeterminate);
1396-
contentView.setViewVisibility(R.id.progress, View.VISIBLE);
1421+
1422+
if (mSubText != null) {
1423+
contentView.setTextViewText(R.id.text, mSubText);
1424+
contentView.setViewVisibility(R.id.text2, View.VISIBLE);
13971425
} else {
1398-
contentView.setViewVisibility(R.id.progress, View.GONE);
1426+
contentView.setViewVisibility(R.id.text2, View.GONE);
1427+
if (mProgressMax != 0 || mProgressIndeterminate) {
1428+
contentView.setProgressBar(
1429+
R.id.progress, mProgressMax, mProgress, mProgressIndeterminate);
1430+
contentView.setViewVisibility(R.id.progress, View.VISIBLE);
1431+
} else {
1432+
contentView.setViewVisibility(R.id.progress, View.GONE);
1433+
}
13991434
}
14001435
if (mWhen != 0) {
14011436
contentView.setLong(R.id.time, "setTime", mWhen);
@@ -1408,9 +1443,7 @@ private RemoteViews makeContentView() {
14081443
if (mContentView != null) {
14091444
return mContentView;
14101445
} else {
1411-
return makeRemoteViews(mLargeIcon == null
1412-
? R.layout.status_bar_latest_event_content
1413-
: R.layout.status_bar_latest_event_content_large_icon);
1446+
return applyStandardTemplate(R.layout.status_bar_latest_event_content); // no more special large_icon flavor
14141447
}
14151448
}
14161449

@@ -1419,7 +1452,7 @@ private RemoteViews makeTickerView() {
14191452
return mTickerView;
14201453
} else {
14211454
if (mContentView == null) {
1422-
return makeRemoteViews(mLargeIcon == null
1455+
return applyStandardTemplate(mLargeIcon == null
14231456
? R.layout.status_bar_latest_event_ticker
14241457
: R.layout.status_bar_latest_event_ticker_large_icon);
14251458
} else {
@@ -1516,4 +1549,100 @@ public Notification getNotification() {
15161549
return n;
15171550
}
15181551
}
1552+
1553+
/**
1554+
* @hide because this API is still very rough
1555+
*
1556+
* This is a "rebuilder": It consumes a Builder object and modifies its output.
1557+
*
1558+
* This represents the "big picture" style notification, with a large Bitmap atop the usual notification.
1559+
*
1560+
* Usage:
1561+
* <pre class="prettyprint">
1562+
* Notification noti = new Notification.BigPictureStyle(
1563+
* new Notification.Builder()
1564+
* .setContentTitle(&quot;New mail from &quot; + sender.toString())
1565+
* .setContentText(subject)
1566+
* .setSmallIcon(R.drawable.new_mail)
1567+
* .setLargeIcon(aBitmap))
1568+
* .bigPicture(aBigBitmap)
1569+
* .build();
1570+
* </pre>
1571+
*/
1572+
public static class BigPictureStyle {
1573+
private Builder mBuilder;
1574+
private Bitmap mPicture;
1575+
1576+
public BigPictureStyle(Builder builder) {
1577+
mBuilder = builder;
1578+
}
1579+
1580+
public BigPictureStyle bigPicture(Bitmap b) {
1581+
mPicture = b;
1582+
return this;
1583+
}
1584+
1585+
private RemoteViews makeBigContentView() {
1586+
RemoteViews contentView = mBuilder.applyStandardTemplate(R.layout.notification_template_big_picture);
1587+
1588+
contentView.setImageViewBitmap(R.id.big_picture, mPicture);
1589+
1590+
return contentView;
1591+
}
1592+
1593+
public Notification build() {
1594+
Notification wip = mBuilder.getNotification();
1595+
wip.bigContentView = makeBigContentView();
1596+
return wip;
1597+
}
1598+
}
1599+
1600+
/**
1601+
* @hide because this API is still very rough
1602+
*
1603+
* This is a "rebuilder": It consumes a Builder object and modifies its output.
1604+
*
1605+
* This represents the "big text" style notification, with more area for the main content text to be read in its entirety.
1606+
*
1607+
* Usage:
1608+
* <pre class="prettyprint">
1609+
* Notification noti = new Notification.BigPictureStyle(
1610+
* new Notification.Builder()
1611+
* .setContentTitle(&quot;New mail from &quot; + sender.toString())
1612+
* .setContentText(subject)
1613+
* .setSmallIcon(R.drawable.new_mail)
1614+
* .setLargeIcon(aBitmap))
1615+
* .bigText(aVeryLongString)
1616+
* .build();
1617+
* </pre>
1618+
*/
1619+
public static class BigTextStyle {
1620+
private Builder mBuilder;
1621+
private CharSequence mBigText;
1622+
1623+
public BigTextStyle(Builder builder) {
1624+
mBuilder = builder;
1625+
}
1626+
1627+
public BigTextStyle bigText(CharSequence cs) {
1628+
mBigText = cs;
1629+
return this;
1630+
}
1631+
1632+
private RemoteViews makeBigContentView() {
1633+
RemoteViews contentView = mBuilder.applyStandardTemplate(R.layout.status_bar_latest_event_content);
1634+
1635+
contentView.setTextViewText(R.id.big_text, mBigText);
1636+
contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
1637+
contentView.setTextViewText(R.id.text, ""); // XXX: what do do with this spot?
1638+
1639+
return contentView;
1640+
}
1641+
1642+
public Notification build() {
1643+
Notification wip = mBuilder.getNotification();
1644+
wip.bigContentView = makeBigContentView();
1645+
return wip;
1646+
}
1647+
}
15191648
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:id="@+id/status_bar_latest_event_content"
3+
android:layout_width="match_parent"
4+
android:layout_height="match_parent"
5+
>
6+
<ImageView
7+
android:id="@+id/big_picture"
8+
android:layout_width="match_parent"
9+
android:layout_height="192dp"
10+
android:scaleType="centerCrop"
11+
/>
12+
<include layout="@layout/status_bar_latest_event_content"
13+
android:layout_width="match_parent"
14+
android:layout_height="@dimen/notification_large_icon_height"
15+
android:layout_marginTop="192dp"
16+
/>
17+
</FrameLayout>

core/res/res/layout/status_bar_latest_event_content.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
22
android:id="@+id/status_bar_latest_event_content"
33
android:layout_width="match_parent"
4-
android:layout_height="match_parent"
4+
android:layout_height="wrap_content"
55
>
66
<ImageView android:id="@+id/icon"
77
android:layout_width="@dimen/notification_large_icon_width"

core/res/res/layout/status_bar_latest_event_content_large_icon.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
android:orientation="vertical"
77
android:paddingLeft="12dp"
88
android:paddingRight="12dp"
9+
android:paddingTop="4dp"
10+
android:paddingBottom="4dp"
911
>
1012
<LinearLayout
1113
android:id="@+id/line1"
@@ -44,6 +46,13 @@
4446
android:ellipsize="marquee"
4547
android:visibility="gone"
4648
/>
49+
<TextView android:id="@+id/big_text"
50+
android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
51+
android:layout_width="match_parent"
52+
android:layout_height="wrap_content"
53+
android:singleLine="false"
54+
android:visibility="gone"
55+
/>
4756
<LinearLayout
4857
android:id="@+id/line3"
4958
android:layout_width="match_parent"
@@ -70,7 +79,7 @@
7079
android:gravity="center"
7180
android:paddingLeft="8dp"
7281
/>
73-
<ImageView android:id="@+id/icon"
82+
<ImageView android:id="@+id/right_icon"
7483
android:layout_width="wrap_content"
7584
android:layout_height="wrap_content"
7685
android:layout_gravity="center"

0 commit comments

Comments
 (0)