суббота, 2 апреля 2011 г.

Списки

 В этом посте расскажу как на android делаются списки. Пойдем от простого к сложному:





1. Для отображения списков в android используются адаптеры, которые связывают массивы данных с виджетами, которые эти данные рисуют на экране. Для начала сделаем простой список, выводящий массив строк.

2. Создаем новый проект (у меня он называется SimpleList), наследуем класс SimpleList от ListActivity. Это класс, который позволяет выводить список и предоставляет методы обработки нажатия на пункт списка.
  1. public class SimpleList extends ListActivity {  
  2.   // Строка, которую мы выводим в список  
  3.   String[] mSign =  {"Овен""Телец""Близнецы""Рак""Лев""Дева",  
  4.           "Весы""Скорпион""Стрелец""Козерог""Водолей""Рыбы"};  
  5.   
  6.   @Override  
  7.   public void onCreate(Bundle savedInstanceState) {  
  8.     super.onCreate(savedInstanceState);  
  9.     setContentView(R.layout.main);  
  10.           
  11.     ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mSign);  
  12.     setListAdapter(mAdapter);  
  13.  }  
  14.       
  15.   public void onListItemClick (ListView parent, View v, int position, long id) {  
  16.     Toast.makeText (getApplicationContext(), mSign[position], Toast.LENGTH_SHORT).show();  
  17.   }  
  18. }  

new ArrayAdapter(Context context, int textViewResourceId, String[] objects) - создает адаптер для списка, где
context - текущий контекст,
textViewResourceId - идентификатор ресурса с разметкой для каждой строки, в данном случае используется системный идентификатор android.R.layout.simple_list_item_1. Дополнительные системные ресурсы можно посмотреть тут android.R.layout.html
objects - собственно список строк

setListAdapter(ListAdapter) - связывает список с адаптером

onListItemClick (ListView l, View v, int position, long id) - метод, который вызывается при нажатие на пункт списка
l - ListView на котором произошло событие
v - View выбранной строки списка
position - порядковый номер выбранной строки
id - id выбранной строки

Toast - класс, отображающий всплывающее сообщение.

Компилируем, запускаем. Видим список:




3. Если мы хотим изменить внешний вид элементов списка, то необходимо создать собственную разметку вместо android.R.layout.simple_list_item_1. В директории /res/layout/ создаем файл item.xml, пишем туда
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   <TextView xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"   
  5.     android:padding="10dp"  
  6.     android:textSize="20sp"  
  7.     android:textStyle="bold"  
  8.     android:textColor="#00FF00"  
  9. />  

а при создании ArrayAdapter заменяем android.R.layout.simple_list_item_1 на созданную разметку R.layout.item.
  1. ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(this, R.layout.item, mSign);  

Запускаем, видим такой же, но уже зеленый список :)




4. Итак, простой список мы вывели, теперь улучшим его. У каждого элемента списка у нас будет не одна строчка, а две. Сверху название знака зодиака, а снизу даты. Для начала перепишем item.xml, добавим туда вертикальный LinearLayout с двумя текстовыми полями:
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:layout_height="wrap_content"   
  4.   android:layout_width="wrap_content"  
  5.   android:orientation="vertical"  
  6.   android:padding="5px"  
  7. >  
  8.   
  9.   <TextView   
  10.     android:id="@+id/Sign"   
  11.     android:layout_width="wrap_content"  
  12.     android:layout_height="wrap_content"  
  13.     android:textSize="20sp"  
  14.     android:textStyle="bold"  
  15.   />  
  16.   
  17.   <TextView    
  18.     android:id="@+id/Date"  
  19.     android:layout_width="wrap_content"   
  20.     android:layout_height="wrap_content"  
  21.     android:textSize="14sp"  
  22.     android:textStyle="italic"  
  23.   />  
  24. </LinearLayout>  


Добавим еще один массив строк с датами
String[] mDate = {"21 марта - 20 апреля", "21 апреля - 20 мая", "21 мая - 21 июня", "22 июня - 22 июля", "23 июля - 23 августа", "24 августа - 23 сентября", "24 сентября - 23 октября", "24 октября - 22 ноября", "23 ноября - 21 декабря", "22 декабря - 20 января", "21 января - 20 февраля", "21 февраля - 20 марта"};

Тут можно сделать как-нибудь более изящно, но мы пока оставим так.

Так как у нас теперь не просто массив строк, то простой ArrayAdapter нам не подходит. Поэтому в качестве адаптера будеv использовать свой класс, наследованный от BaseAdapter

  1. public class SimpleList extends ListActivity {  
  2.   String[] mSign ...;  
  3.   String[] mDate...;  
  4.       
  5.   @Override  
  6.   public void onCreate(Bundle savedInstanceState) {  
  7.     ...  
  8.   }  
  9.       
  10.   public void onListItemClick (ListView parent, View v, int position, long id) {  
  11.     ...  
  12.   }  
  13.       
  14.   public class myAdapter extends BaseAdapter {  
  15.     private LayoutInflater mLayoutInflater;  
  16.           
  17.     public myAdapter (Context ctx) {  
  18.       mLayoutInflater = LayoutInflater.from(ctx);  
  19.     }  
  20.           
  21.     public int getCount () {  
  22.       return mSign.length;  
  23.     }  
  24.           
  25.     public Object getItem (int position) {  
  26.       return position;  
  27.     }  
  28.           
  29.     public long getItemId (int position) {  
  30.       return position;  
  31.     }  
  32.           
  33.     public String getString (int position) {  
  34.       return mSign[position] + " (" + mDate[position] + ")";  
  35.     }  
  36.           
  37.     public View getView(int position, View convertView, ViewGroup parent) {   
  38.       if (convertView == null)  
  39.         convertView = mLayoutInflater.inflate(R.layout.item, null);  
  40.                
  41.       TextView sign = (TextView)convertView.findViewById(R.id.Sign);  
  42.       sign.setText(mSign[position]);  
  43.   
  44.       TextView date = (TextView)convertView.findViewById(R.id.Date);  
  45.       date.setText(mDate[position]);               
  46.       return convertView;  
  47.     }  
  48.   }   
  49. }  


Теперь по порядку:
BaseAdapter — общий класс-родитель для адаптеров используется в ListView и Spinner
LayoutInflater — класс позволяющий вставлять в View разметку из xml файла
View inflate(int resource, ViewGroup root) — метод возвращающий View из файла resource, причем начиная с элемента root (то есть элемент root и его вложенные элементы) этого файла.

getView — Возвращает View для каждой строки нашего списка. View можно создать вручную, но в нашем случае мы создаем его из файла item.xml (с помощью LayoutInflater).
positiion — порядковый номер строки для который мы создаем View
convertView — старый View для повторного использования
parent — родитель к которому присоединяется созданная строка.
В методе мы проверяем, не была ли строка списка уже создана и если convertView = null, то создаем ее из файла item.xml и задаем значения для двух текстовых полей.

Запускаем:




5. Ну и наконец последнее изменение, добавим к нашему списку еще и иконку. Положим в директорию /res/drawable/ иконки для знаков зодиака Добавим еще один массив
Integer[] mImage = {R.drawable.aries, R.drawable.taurus, R.drawable.gemini, R.drawable.cancer, R.drawable.lion, R.drawable.virgo, R.drawable.libra, R.drawable.scorpio, R.drawable.sagittarius, R.drawable.capricorn, R.drawable.aquarius, R.drawable.pisces};
Поворюсь, что три массива не лучшее решение, но нам сейчас интересно не это. Добавим в item.xml ImageView например так:
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:layout_height="wrap_content"   
  4.   android:layout_width="wrap_content"  
  5.   android:padding="5px"  
  6. >  
  7.   <ImageView   
  8.     android:id="@+id/Image"   
  9.     android:layout_width="wrap_content"  
  10.     android:layout_height="wrap_content"  
  11.   />  
  12.               
  13.   <LinearLayout  
  14.     android:layout_height="wrap_content"   
  15.     android:layout_width="wrap_content"  
  16.     android:orientation="vertical"  
  17.     android:paddingLeft="15px"  
  18.   >  
  19.     <TextView   
  20.       android:id="@+id/Sign"   
  21.       android:layout_width="wrap_content"  
  22.       android:layout_height="wrap_content"  
  23.       android:textSize="20sp"  
  24.       android:textStyle="bold"  
  25.     />  
  26.       
  27.     <TextView    
  28.       android:id="@+id/Date"  
  29.       android:layout_width="wrap_content"   
  30.       android:layout_height="wrap_content"  
  31.       android:textSize="14sp"  
  32.       android:textStyle="italic"  
  33.     />  
  34.   </LinearLayout>  
  35. </LinearLayout>  


И при инициализации convertView добавим
  1. public View getView(int position, View convertView, ViewGroup parent) {   
  2.   ...  
  3.   ImageView image = (ImageView)convertView.findViewById(R.id.Image);  
  4.   image.setImageResource(mImage[position]);  
  5.   return convertView;  
  6. }  


Все. Запускаем, видим вполне симпатичную картинку




Вот таким нехитрым способом можно создавать любые списки :)

Исходники можно скачать в следующей статье Уведомления

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

  1. Доброго, я в андроиде и яве как керзовый сопог в элитном женском обувном бутике, Вы можете помочь мне со списком?

    ОтветитьУдалить