воскресенье, 3 апреля 2011 г.

Уведомления

В прошлом посте мы сделали список со знаками зодиака, сейчас попробуем изменить внешний вид этих серых, унылых окошек уведомлений при выборе одного знака. Заодно посмотрим как выводить уведомления в строке состояния.

1. Всплывающие уведомления рисуются с помощью класса Toast. В прошлом примере мы делали это так:
  1. Toast.makeText (getApplicationContext(), «Text»,  ).show();  
Для удобства восприятия разобьем на две строчки:
  1. Toast myToast = Toast.makeText (Context context, String text, int duration);  
  2. myToast.show();  
В первой строчке создаем уведомления, тут context - текущий контекст text — собственно текст сообщения duration — время показа сообщения в миллисекундах. Здесь можно использовать константы Toast.LENGTH_SHORT (короткий промежуток времени) и Toast.LENGTH_LONG (длинный промежуток). и во второй строчке show() - метод отображающий созданное сообщение. Тут вроде ничего не сложного.

2. Вывести уведомления можно также в строку состояния. Чаще такой вид уведомлений используется для приложений работающих в фоновом режиме и в нашем списке это не особо надо, но для примера разберемся. Для этого нам понадобятся два класса:
Notification — класс формирующий уведомление
Notification(int icon, CharSequence tickerText, long when)
тут вполне очевидно: icon и tickerText — иконка и текст, отображающиеся в строке уведомления, when — время вывода уведомления.

В Notification нас еще интересует метод, описывающий как будет выглядеть уведомление при просмотре. setLatestEventInfo(Context context, CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent)
тут context — текущий контекст
contentTitle и contentText — заголовок и текст сообщения
contentIntent — окно открываемое при нажатие на уведомление.

Второй класс NotificationManager, который собственно и выводит наше уведомление. Для этого используется метод
notify(int id, Notification notification) или
notify(String tag, int id, Notification notification) Каждое уведомление имеет id и необязательный tag. Эти параметры уникально определяют уведомление для системы. При вызове метода notify с уже существующими id и tag, уведомление не создается заново, а обновляется.
Создать экземпляр класса NotificationManager напрямую нельзя, поэтому будем использовать метод getSystemService(String) (из класса Context), который возвращает указатель на системную службу.

Также будут использоваться классы Intent и PendingIntent. Эти два класса вообще заслуживают отдельного детального разбирательства, но вкратце они позволяют нам запускать приложение или сервис.

Поехали. В начале, в класс SimpleList добавляем атрибуты
  1. public class SimpleList extends ListActivity {  
  2.   ...  
  3.   myAdapter mAdapter;  
  4.   private static final int NOTIFY_ID = 101;  
  5.   private NotificationManager myNotifyMgr;  
  6.   ...  
  7. }  


В методе onCreate получаем указатель на службу уведомлений
  1. public void onCreate(Bundle savedInstanceState) {  
  2.   ...          
  3.   myNotifyMgr = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);  
  4. }  


И наконец в метод onListItemClick пишем вызов уведомления
  1. public void onListItemClick (ListView parent, View v, int position, long id) {  
  2.   //** Всплывающее уведомление  
  3.   Toast.makeText (getApplicationContext(), mAdapter.getString(position), Toast.LENGTH_SHORT).show();  
  4.           
  5.   //** Уведомление в строке состояния  
  6.   // Определяем параметры, которые будем выводить  
  7.   CharSequence Title = "Выбран элемент";  
  8.   int icon = mImage[position];  
  9.   CharSequence Text = mAdapter.getString(position);    
  10.           
  11.   // Определяем окно, которое будет открываться (SimpleList.class — класс с  этим примером)  
  12.   Intent notificationIntent = new Intent (this, SimpleList.class);  
  13.   PendingIntent contentIntent = PendingIntent.getActivity(this0, notificationIntent, 0);  
  14.       
  15.   // Выводим уведомление  
  16.   Notification notification = new Notification(icon, Title, System.currentTimeMillis());  
  17.   notification.setLatestEventInfo(getApplicationContext(), Title, Text, contentIntent);  
  18.           
  19.   myNotifyMgr.notify(NOTIFY_ID, notification);  
  20. }  

Запускаем. Теперь при нажатии на элемент списка у нас появляется не только серое окошко, но и новое уведомление в строке состояния. При последовательном выборе нескольких элементов, уведомление будет изменяться. Если изменить строчку
  1. myNotifyMgr.notify(NOTIFY_ID, notification);  

на например такое
  1. myNotifyMgr.notify((new Random()).nextInt(100), notification);  

то при выборе нескольких строк, уведомления начнут плодиться как кролики )) ((new Random()).nextInt(100) — генерация случайного числа от 0 до 100)


3. Теперь украсим оба этих уведомления. Способ изменения внешнего вида похож на тот, который мы уже использовали в прошлый раз для изменения пунктов списка. Итак, для начала создаем xml-разметку для уведомления, например так: (notify.xml)
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:id="@+id/linear_layout"   
  4.   android:layout_height="wrap_content"   
  5.   android:layout_width="wrap_content"  
  6.   android:orientation="vertical"  
  7.   android:background="@drawable/bg"  
  8.   android:gravity="center"  
  9.   android:minWidth="150px"  
  10. >  
  11.   <ImageView   
  12.     android:id="@+id/Image"   
  13.     android:layout_width="wrap_content"  
  14.     android:layout_height="wrap_content"  
  15.   />  
  16.               
  17.   <TextView   
  18.     android:id="@+id/Sign"   
  19.     android:layout_width="wrap_content"  
  20.     android:layout_height="wrap_content"  
  21.     android:textSize="20sp"  
  22.     android:textStyle="bold"  
  23.     android:textColor="#000000"  
  24.   />  
  25.       
  26.   <TextView    
  27.     android:id="@+id/Date"  
  28.     android:layout_width="wrap_content"   
  29.     android:layout_height="wrap_content"  
  30.     android:textSize="14sp"  
  31.     android:textStyle="italic"  
  32.     android:textColor="#000000"  
  33.   />  
  34. </LinearLayout>  
В SimpleList.java в методе onListItemClick пишем
  1. public void onListItemClick (ListView parent, View v, int position, long id) {  
  2.   // Всплывающее уведомление  
  3.   LayoutInflater mInflater = getLayoutInflater();  
  4.   View mLayout = mInflater.inflate(R.layout.notify, null);  
  5.   
  6.   ImageView image = (ImageView)mLayout.findViewById(R.id.Image);  
  7.   image.setImageResource(mImage[position]);  
  8.   
  9.   TextView sign = (TextView)mLayout.findViewById(R.id.Sign);  
  10.   sign.setText(mSign[position]);  
  11.   
  12.   TextView date = (TextView)mLayout.findViewById(R.id.Date);  
  13.   date.setText(mDate[position]);  
  14.   
  15.   Toast toast = new Toast (getApplicationContext());  
  16.   toast.setDuration(Toast.LENGTH_LONG);  
  17.   toast.setView(mLayout);  
  18.   toast.show();  
  19.   ...  
  20. }  
LayoutInflater — класс позволяющий вставлять в View разметку из xml файла View inflate(int resource, ViewGroup root) — метод возвращающий View из файла resource, причем начиная с элемента root (то есть элемент root и его вложенные элементы) этого файла. Создаем mLayout с разметкой файла notify.xml (второй параметр метода inflate() root = null, значит берем все разметку начиная с корневого элемента). Дальше инициализируем изображение и два текстовых поля данными выбранного элемента и показываем уведомление. Запускаем:

4. Ну и последнее изменим уведомление в строке состояния. Напишем xml-разметку item.xml (пример приводить не буду, у меня она практически не отличается от последней версии item.xml из прошлого поста). В классе Notification есть поле public RemoteViews contentView, который определяет вид уведомления. Он как и LayoutInflater создает View из файла xml-разметки. Пишем:
  1. public void onListItemClick (ListView parent, View v, int position, long id) {  
  2.   ...  
  3.   // Уведомление в строке состояния  
  4.   CharSequence Title = "Выбран элемент " + mSign[position];  
  5.   int icon = mImage[position];  
  6.               
  7.   Intent notificationIntent = new Intent (this, SimpleList.class);  
  8.   PendingIntent contentIntent = PendingIntent.getActivity(this0, notificationIntent, 0);  
  9.           
  10.   RemoteViews mRemoteView = new RemoteViews(getPackageName(), R.layout.notify);  
  11.   mRemoteView.setImageViewResource(R.id.Image, mImage[position]);  
  12.   mRemoteView.setTextViewText(R.id.Sign, mSign[position]);  
  13.   mRemoteView.setTextViewText(R.id.Date, mDate[position]);  
  14.   
  15.   Notification notification = new Notification(icon, Title, System.currentTimeMillis());  
  16.   notification.contentIntent = contentIntent;  
  17.   notification.contentView = mRemoteView;  
  18.           
  19.   myNotifyMgr.notify(NOTIFY_ID, notification);  
  20. }  
Запускаем:

Вот как-то так :) Исходники этой и предыдущей статьи Списки можно скачать здесь SimpleList Sources

1 комментарий: