OSDN Git Service

Show action buttons in expanded notifications.
authorDaniel Sandler <dsandler@android.com>
Fri, 30 Mar 2012 20:37:36 +0000 (16:37 -0400)
committerDaniel Sandler <dsandler@android.com>
Sat, 31 Mar 2012 02:18:06 +0000 (22:18 -0400)
Any notification with at least one action will now have an
expanded form by default. BigPicture/BigText can have
actions, too, of course.

Change-Id: I6f54cac65d9a9f335d8038c2105cd2c674f991ff

core/java/android/app/Notification.java
core/res/res/layout/notification_action.xml [new file with mode: 0644]
core/res/res/layout/notification_template_base.xml [new file with mode: 0644]
core/res/res/layout/notification_template_big_picture.xml
core/res/res/layout/status_bar_latest_event_content.xml
core/res/res/layout/status_bar_latest_event_content_large_icon.xml [deleted file]
core/res/res/values/public.xml
packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java

index 1356801..096af93 100644 (file)
@@ -28,6 +28,7 @@ import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.IntProperty;
+import android.util.Log;
 import android.view.View;
 import android.widget.ProgressBar;
 import android.widget.RemoteViews;
@@ -808,7 +809,7 @@ public class Notification implements Parcelable
     public void setLatestEventInfo(Context context,
             CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) {
         RemoteViews contentView = new RemoteViews(context.getPackageName(),
-                R.layout.status_bar_latest_event_content);
+                R.layout.notification_template_base);
         if (this.icon != 0) {
             contentView.setImageViewResource(R.id.icon, this.icon);
         }
@@ -1439,11 +1440,28 @@ public class Notification implements Parcelable
             return contentView;
         }
 
+        private RemoteViews applyStandardTemplateWithActions(int layoutId) {
+            RemoteViews big = applyStandardTemplate(layoutId);
+
+            int N = mActions.size();
+            if (N > 0) {
+                Log.d("Notification", "has actions: " + mContentText);
+                big.setViewVisibility(R.id.actions, View.VISIBLE);
+                if (N>3) N=3;
+                for (int i=0; i<N; i++) {
+                    final RemoteViews button = generateActionButton(mActions.get(i));
+                    Log.d("Notification", "adding action " + i + ": " + mActions.get(i).title);
+                    big.addView(R.id.actions, button);
+                }
+            }
+            return big;
+        }
+
         private RemoteViews makeContentView() {
             if (mContentView != null) {
                 return mContentView;
             } else {
-                return applyStandardTemplate(R.layout.status_bar_latest_event_content); // no more special large_icon flavor
+                return applyStandardTemplate(R.layout.notification_template_base); // no more special large_icon flavor
             }
         }
 
@@ -1461,6 +1479,12 @@ public class Notification implements Parcelable
             }
         }
 
+        private RemoteViews makeBigContentView() {
+            if (mActions.size() == 0) return null;
+
+            return applyStandardTemplateWithActions(R.layout.notification_template_base);
+        }
+
         private RemoteViews makeIntruderView(boolean showLabels) {
             RemoteViews intruderView = new RemoteViews(mContext.getPackageName(),
                     R.layout.notification_intruder_content);
@@ -1500,6 +1524,15 @@ public class Notification implements Parcelable
             return intruderView;
         }
 
+        private RemoteViews generateActionButton(Action action) {
+            RemoteViews button = new RemoteViews(mContext.getPackageName(), R.layout.notification_action);
+            button.setTextViewCompoundDrawables(R.id.action0, action.icon, 0, 0, 0);
+            button.setTextViewText(R.id.action0, action.title);
+            button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
+            button.setContentDescription(R.id.action0, action.title);
+            return button;
+        }
+
         /**
          * Combine all of the options that have been set and return a new {@link Notification}
          * object.
@@ -1528,6 +1561,7 @@ public class Notification implements Parcelable
             if (mCanHasIntruder) {
                 n.intruderView = makeIntruderView(mIntruderActionsShowText);
             }
+            n.bigContentView = makeBigContentView();
             if (mLedOnMs != 0 && mLedOffMs != 0) {
                 n.flags |= FLAG_SHOW_LIGHTS;
             }
@@ -1583,7 +1617,7 @@ public class Notification implements Parcelable
         }
 
         private RemoteViews makeBigContentView() {
-            RemoteViews contentView = mBuilder.applyStandardTemplate(R.layout.notification_template_big_picture);
+            RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(R.layout.notification_template_big_picture);
 
             contentView.setImageViewBitmap(R.id.big_picture, mPicture);
 
@@ -1630,7 +1664,7 @@ public class Notification implements Parcelable
         }
 
         private RemoteViews makeBigContentView() {
-            RemoteViews contentView = mBuilder.applyStandardTemplate(R.layout.status_bar_latest_event_content);
+            RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(R.layout.notification_template_base);
 
             contentView.setTextViewText(R.id.big_text, mBigText);
             contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
diff --git a/core/res/res/layout/notification_action.xml b/core/res/res/layout/notification_action.xml
new file mode 100644 (file)
index 0000000..54fde70
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/action0"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    style="@android:style/Widget.Holo.Button.Small"
+    android:gravity="left"
+    />
\ No newline at end of file
diff --git a/core/res/res/layout/notification_template_base.xml b/core/res/res/layout/notification_template_base.xml
new file mode 100644 (file)
index 0000000..5b06460
--- /dev/null
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<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="wrap_content"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:background="@android:drawable/notify_panel_notification_icon_bg_tile"
+        android:scaleType="center"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:layout_marginLeft="@dimen/notification_large_icon_width"
+        android:minHeight="@dimen/notification_large_icon_height"
+        android:orientation="vertical"
+        android:paddingLeft="12dp"
+        android:paddingRight="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp"
+        >
+        <LinearLayout
+            android:id="@+id/line1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            >
+            <TextView android:id="@+id/title"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                android:layout_weight="1"
+                />
+            <DateTimeView android:id="@+id/time"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Time"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:singleLine="true"
+                android:gravity="center"
+                android:paddingLeft="8dp"
+                />
+        </LinearLayout>
+        <TextView android:id="@+id/text2"
+            android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Line2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-2dp"
+            android:layout_marginBottom="-2dp"
+            android:singleLine="true"
+            android:fadingEdge="horizontal"
+            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"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            >
+            <TextView android:id="@+id/text"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="center"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                />
+            <TextView android:id="@+id/info"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:singleLine="true"
+                android:gravity="center"
+                android:paddingLeft="8dp"
+                />
+            <ImageView android:id="@+id/right_icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:scaleType="center"
+                android:paddingLeft="8dp"
+                android:visibility="gone"
+                android:drawableAlpha="180"
+                />
+        </LinearLayout>
+        <ProgressBar
+            android:id="@android:id/progress"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            style="?android:attr/progressBarStyleHorizontal"
+            />
+        <LinearLayout
+               android:id="@+id/actions"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+               >
+               <!-- actions will be added here -->
+        </LinearLayout>
+    </LinearLayout>
+</FrameLayout>
index 6eb934e..8be84bd 100644 (file)
@@ -1,3 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
@@ -9,9 +25,9 @@
         android:layout_height="192dp"
         android:scaleType="centerCrop"
         />
-    <include layout="@layout/status_bar_latest_event_content
+    <include layout="@layout/notification_template_base
         android:layout_width="match_parent"
-        android:layout_height="@dimen/notification_large_icon_height"
+        android:layout_height="wrap_content"
         android:layout_marginTop="192dp"
         />
 </FrameLayout>
\ No newline at end of file
index 57c149f..b3db01a 100644 (file)
@@ -1,17 +1,29 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Nobody should be using this file directly. If you do, you will get a
+     purple background. Have fun with that. -->
+<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="wrap_content"
+    android:background="#FFFF00FF"
     >
-    <ImageView android:id="@+id/icon"
-        android:layout_width="@dimen/notification_large_icon_width"
-        android:layout_height="@dimen/notification_large_icon_height"
-        android:background="@android:drawable/notify_panel_notification_icon_bg_tile"
-        android:scaleType="center"
-        />
-    <include layout="@layout/status_bar_latest_event_content_large_icon" 
+    <include layout="@layout/notification_template_base"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center"
         />
-</LinearLayout>
+</FrameLayout>
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
deleted file mode 100644 (file)
index 5f38e6a..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/status_bar_latest_event_content_large_icon"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    android:orientation="vertical"
-    android:paddingLeft="12dp"
-    android:paddingRight="12dp"
-    android:paddingTop="4dp"
-    android:paddingBottom="4dp"
-    >
-    <LinearLayout
-        android:id="@+id/line1"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        >
-        <TextView android:id="@+id/title"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:singleLine="true"
-            android:ellipsize="marquee"
-            android:fadingEdge="horizontal"
-            android:layout_weight="1"
-            />
-        <DateTimeView android:id="@+id/time"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Time"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:layout_weight="0"
-            android:singleLine="true"
-            android:gravity="center"
-            android:paddingLeft="8dp"
-            />
-    </LinearLayout>
-    <TextView android:id="@+id/text2"
-        android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Line2"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="-2dp"
-        android:layout_marginBottom="-2dp"
-        android:singleLine="true"
-        android:fadingEdge="horizontal"
-        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"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        >
-        <TextView android:id="@+id/text"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:layout_gravity="center"
-            android:singleLine="true"
-            android:ellipsize="marquee"
-            android:fadingEdge="horizontal"
-            />
-        <TextView android:id="@+id/info"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:layout_weight="0"
-            android:singleLine="true"
-            android:gravity="center"
-            android:paddingLeft="8dp"
-            />
-        <ImageView android:id="@+id/right_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:layout_weight="0"
-            android:scaleType="center"
-            android:paddingLeft="8dp"
-            android:visibility="gone"
-            android:drawableAlpha="180"
-            />
-    </LinearLayout>
-    <ProgressBar
-        android:id="@android:id/progress"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:visibility="gone"
-        style="?android:attr/progressBarStyleHorizontal"
-        />
-</LinearLayout>
index 7b4f50b..cb86902 100644 (file)
   <java-symbol type="layout" name="select_dialog" />
   <java-symbol type="layout" name="simple_dropdown_hint" />
   <java-symbol type="layout" name="status_bar_latest_event_content" />
-  <java-symbol type="layout" name="status_bar_latest_event_content_large_icon" />
   <java-symbol type="layout" name="status_bar_latest_event_ticker" />
   <java-symbol type="layout" name="status_bar_latest_event_ticker_large_icon" />
   <java-symbol type="layout" name="text_edit_action_popup_text" />
   <java-symbol type="layout" name="zoom_container" />
   <java-symbol type="layout" name="zoom_controls" />
   <java-symbol type="layout" name="zoom_magnify" />
+  <java-symbol type="layout" name="notification_action" />
   <java-symbol type="layout" name="notification_intruder_content" />
+  <java-symbol type="layout" name="notification_template_base" />
   <java-symbol type="layout" name="notification_template_big_picture" />
 
   <java-symbol type="anim" name="slide_in_child_bottom" />
index 23222f2..b982220 100644 (file)
@@ -19,6 +19,9 @@ package com.android.systemui.statusbar;
 import java.util.ArrayList;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -181,6 +184,25 @@ public abstract class BaseStatusBar extends SystemUI implements
         return vetoButton;
     }
     
+
+    protected void applyLegacyRowBackground(StatusBarNotification sbn, View content) {
+        if (sbn.notification.contentView.getLayoutId() !=
+                com.android.internal.R.layout.notification_template_base) {
+            int version = 0;
+            try {
+                ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.pkg, 0);
+                version = info.targetSdkVersion;
+            } catch (NameNotFoundException ex) {
+                Slog.e(TAG, "Failed looking up ApplicationInfo for " + sbn.pkg, ex);
+            }
+            if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
+                content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
+            } else {
+                content.setBackgroundResource(R.drawable.notification_row_bg);
+            }
+        }
+    }
+
     public void dismissIntruder() {
         // pass
     }
index 7c679b2..3737604 100644 (file)
@@ -895,24 +895,6 @@ public class PhoneStatusBar extends BaseStatusBar {
         return true;
     }
 
-    void applyLegacyRowBackground(StatusBarNotification sbn, View content) {
-        if (sbn.notification.contentView.getLayoutId() !=
-                com.android.internal.R.layout.status_bar_latest_event_content) {
-            int version = 0;
-            try {
-                ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.pkg, 0);
-                version = info.targetSdkVersion;
-            } catch (NameNotFoundException ex) {
-                Slog.e(TAG, "Failed looking up ApplicationInfo for " + sbn.pkg, ex);
-            }
-            if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
-                content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
-            } else {
-                content.setBackgroundResource(R.drawable.notification_row_bg);
-            }
-        }
-    }
-
     StatusBarNotification removeNotificationViews(IBinder key) {
         NotificationData.Entry entry = mNotificationData.remove(key);
         if (entry == null) {
index 2491d18..3fa4a05 100644 (file)
@@ -1880,24 +1880,6 @@ public class TabletStatusBar extends BaseStatusBar implements
         return true;
     }
 
-    void applyLegacyRowBackground(StatusBarNotification sbn, View content) {
-        if (sbn.notification.contentView.getLayoutId() !=
-                com.android.internal.R.layout.status_bar_latest_event_content) {
-            int version = 0;
-            try {
-                ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.pkg, 0);
-                version = info.targetSdkVersion;
-            } catch (NameNotFoundException ex) {
-                Slog.e(TAG, "Failed looking up ApplicationInfo for " + sbn.pkg, ex);
-            }
-            if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
-                content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
-            } else {
-                content.setBackgroundResource(R.drawable.notification_row_bg);
-            }
-        }
-    }
-
     public void clearAll() {
         try {
             mBarService.onClearAllNotifications();