1. Для работы с галерей используется класс Gallery. Напишем его в разметке xml:
- <Gallery
- android:id="@+id/gallery"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- />
2. Так же как и в списках (ListView) или в таблицах (GridView) для работы с галерей используется адаптер — класс унаследованный от BaseAdapter. Про него я уже писала в статьях Списки и Игра для тренировки памяти. При наследовании от класса BaseAdapter необходимо обязательно описать 4 метода:
public int getCount() - кол-во элементов (в данном случае в галерее)
public Object getItem(int position) — возвращает значение элемента с номером position
public long getItemId(int position) — возвращает ID элемента с номером position
public View getView(int position, View convertView, ViewGroup parent) — возвращает View, который будет является элементом с номером position.
3. Для представления галереи в android есть предопределенный стиль, который рисует для каждого элемента серую рамку (для выделенного — светло-серую). Называется стиль galleryItemBackground. Как мы знаем, чтобы задать фон или стиль в программе используется идентификатор типа R.drawable.image, причем image должен лежать в директории /res/drawable нашего проекта. Но стиль galleryItemBackground является системным и для того чтобы получить идентификатор создадим в /res/values файл (например attrs.xml) и напишем туда
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <declare-styleable name="MyGallery">
- <attr name="android:galleryItemBackground" />
- </declare-styleable>
- </resources>
Это ресурс стиля, который будет применен к каждому элементу помещеному в галерею. Элемент attr определяет конкретный атрибут. Таких элементов может быть несколько.
4. Теперь напишем собственно класс GalleryOne унаследованный от Activity
- public class GalleryOne extends Activity {
- Gallery mGallery;
- TextView mTextView;
- ImageAdapter mImageAdapter;
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.gallery);
- // Текстовое поле, в которое выводится номер выделенного элемента
- mTextView = (TextView) findViewById(R.id.selected);
- mGallery = (Gallery) findViewById(R.id.gallery);
- // Устанавливаем адаптер
- mImageAdapter = new ImageAdapter(this);
- mGallery.setAdapter(mImageAdapter);
- // Выделяем элемент по середине
- mGallery.setSelection(mImageAdapter.getCount() / 2);
- // Устанавливаем действия, которые будут выполнены при выделении элемента
- mGallery.setOnItemSelectedListener(new OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
- mTextView.setText(String.valueOf(position));
- }
- @Override
- public void onNothingSelected(AdapterView<?> arg0) {
- mTextView.setText("");
- }
- });
- }
- // Класс адаптера
- public class ImageAdapter extends BaseAdapter {
- int mGalleryItemBackground;
- private Context mContext;
- // Массив изображений
- private int[] mImageIds = {
- R.drawable.s01, R.drawable.s02, R.drawable.s03, R.drawable.s04,
- R.drawable.s05, R.drawable.s06, R.drawable.s07, R.drawable.s08,
- R.drawable.s09, R.drawable.s10};
- public ImageAdapter(Context c) {
- mContext = c;
- TypedArray attr = mContext.obtainStyledAttributes(R.styleable.MyGallery);
- mGalleryItemBackground = attr.getResourceId(R.styleable.MyGallery_android_galleryItemBackground, 0);
- attr.recycle();
- }
- public int getCount() {
- return mImageIds.length;
- }
- public Object getItem(int position) {
- return position;
- }
- public long getItemId(int position) {
- return position;
- }
- public View getView(int position, View convertView, ViewGroup parent) {
- ImageView imageView = new ImageView(mContext);
- imageView.setImageResource(mImageIds[position]);
- // Позиционирование по центру
- imageView.setScaleType(ImageView.ScaleType.CENTER);
- // Размер по содержимому
- imageView.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- imageView.setBackgroundResource(mGalleryItemBackground);
- return imageView;
- }
- }
- }
Основные места прокомментированы, так что должно быть все понятно. Более подробно расскажу про использование стиля galleryItemBackground. Для работы с такими стилями используется класс TypedArray, который является массивом. Инициализируется экземпляр класса с помощью obtainStyledAttributes() или obtainAttributes(). Метод obtainStyledAttributes() возвращает атрибуты прочитанные из ресурса styleable (то есть все элементы attr из attrs.xml).
Метод getResourceId(int index, int defValue) — возвращает идентификатор ресурса.
После работы с экземпляром класса TypedArray, его обязательно надо очистить с помощью метода recycle();
Таким образом мы получаем id ресурса для предопределенного стиля galleryItemBackground, который можем передать в метод imageView.setBackgroundResource().
5. Запускаем.
6. Если посмотреть исходники андроида, то можно найти, что galleryItemBackground, это не какой-то неизвестный кот в мешке, а вполне понятный файл ресурса drawable и выглядит он приблизительно так:
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/gallery_selected_default"
- android:state_selected="true"
- android:state_window_focused="false" />
- <item android:drawable="@drawable/gallery_unselected_default"
- android:state_selected="false"
- android:state_window_focused="false" />
- <item android:drawable="@drawable/gallery_selected_pressed"
- android:state_selected="true"
- android:state_pressed="true" />
- <item android:drawable="@drawable/gallery_selected_focused"
- android:state_selected="true"
- android:state_focused="true" />
- <item android:drawable="@drawable/gallery_selected_default"
- android:state_selected="true" />
- <item android:drawable="@drawable/gallery_unselected_pressed"
- android:state_selected="false"
- android:state_pressed="true" />
- <item android:drawable="@drawable/gallery_unselected_default" />
- </selector>
selector определяет drawable, значение которого меняется в зависимости от состояния. Поэтому если мы хотим сделать собственный стиль, можно скопировать этот код в файл в директории /res/drawable (у меня это bg.xml) и заменить «@drawable/...» на собственные изображения. Мне обрабатывать столько состояний объекта ни к чему, я хочу чтобы выделенный элемент (или элемент в фокусе) был в рамочке, а все остальные никак не выделялись. Напишем в bg.xml такое:
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:drawable="@drawable/selected" />
- <item android:state_focused="true" android:drawable="@drawable/selected" />
- <item android:drawable="@android:color/transparent" />
- </selector>
7. Теперь надо немного изменить наш класс. Прежде всего уберем все что связано с TypedArray из конструктора ImageAdapter и в методе getView() изменим строчку imageView.setBackgroundResource(R.drawable.bg);
8. Запустим
Рамочка нарисовалась, но картинки налезают друг на друга. Определим для галереи атрибут spacing (расстояние между элементами). Это можно сделать в gallery.xml или в самом коде. А также поставим для каждого элемента атрибут padding (расстояние между границей элемента и его содержимым). Итого получилось такое: (в комментариях показано какие строчки добавились, а какие надо удалить)
- public class GalleryOne extends Activity {
- ...
- public void onCreate(Bundle savedInstanceState) {
- ...
- // Выделяем элемент по середине
- mGallery.setSelection(mImageAdapter.getCount() / 2);
- mGallery.setSpacing(2); /* NEW */
- ...
- // Класс адаптера
- public class ImageAdapter extends BaseAdapter {
- // int mGalleryItemBackground; /* DELETE */
- private Context mContext;
- ...
- public ImageAdapter(Context c) {
- mContext = c;
- /* DELETE */
- //TypedArray attr = mContext.obtainStyledAttributes(R.styleable.MyGallery);
- // mGalleryItemBackground = attr.getResourceId(R.styleable.MyGallery_android_galleryItemBackground, 0);
- // attr.recycle();
- }
- ...
- public View getView(int position, View convertView, ViewGroup parent) {
- ...
- imageView.setBackgroundResource(R.drawable.bg); /* CHANGED */
- imageView.setPadding(10, 2, 10, 2); /* NEW */
- return imageView;
- }
- }
- }
9. Запускаем
10. Менять в зависимости от состояния можно не только фон, но и само изображение. Для каждой картинки создадим ее черно-белую копию (если изначальный файл s01.png, то копия будет s01_gray.png). Также создадим для каждой картинки файл (например d01.xml) в директории /res/drawable.
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:drawable="@drawable/s01" />
- <item android:drawable="@drawable/s01_gray" />
- </selector>
То есть для выбранного элемента будет использоваться картинка s01.png, а для невыбранного s01_gray.png
11. В коде нам необходимо заменить массив ресурсов на
private int[] mImageIds = {
R.drawable.d01, R.drawable.d02, R.drawable.d03, R.drawable.d04,
R.drawable.d05, R.drawable.d06, R.drawable.d07, R.drawable.d08,
R.drawable.d09, R.drawable.d10};
Вместо изображений s01, s02... s10, будут браться файлы drawable d01, d02... d10. И уберем добавление фона изображения, то есть строчку imageView.setBackgroundResource(R.drawable.bg);
12. Запускаем
13. Метод getView() адаптера возвращает не ImageView, а просто View. А значит элементом галереи необязательно должно быть изображение. Там может быть TextView (текстовое поле), Button (кнопка) или даже LinearLayout содержащий несколько элементов. В статье про списки мы уже такое делали. Там мы делали это с помощью класса LayoutInflater, сейчас посмотрим как сделать это без него. Добавим к нашим мордочкам текст. Для этого после массива с картинками, определим массив с строками
private String[] mStrings = {"Smiling", "In love", "Sad", "Crying", "Scared",
"Winking", "Laughting", "Surprised", "Upset", "Angry"};
И допишим метод getView ()
- public View getView(int position, View convertView, ViewGroup parent) {
- ImageView imageView = new ImageView(mContext);
- imageView.setImageResource(mImageIds[position]);
- imageView.setScaleType(ImageView.ScaleType.CENTER);
- imageView.setPadding(10, 2, 10, 2);
- imageView.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- TextView textView = new TextView(mContext);
- textView.setText(mStrings[position]);
- textView.setGravity(Gravity.CENTER);
- textView.setTypeface(Typeface.MONOSPACE);
- textView.setTextSize(10);
- textView.setTextColor(getResources().getColorStateList(R.color.text));
- LinearLayout layout = new LinearLayout(getApplicationContext());
- layout.setOrientation(LinearLayout.VERTICAL);
- layout.addView(imageView);
- layout.addView(textView);
- return layout;
- }
14. Вначале мы определяем изображение imageView (оно ничем не отличается оттого что у нас уже было). Затем определяем textView, устанавливаем ему значение из массива mStrings. Располагаем текст по центру, шрифт моноширинный 10pt. Цвет текста также должен меняться в зависимости от состояния элемента, поэтому добавим в /res/color файл text.xml
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:color="#FFAA25" />
- <item android:state_focused="true" android:color="#FFAA25" />
- <item android:color="#919191" />
- </selector>
И наконец создаем вертикальный LinearLayout и добавляем в него картинку и текст.
15. Запускаем
Мы посмотрели как создать галерею в android и несколько способов ее представления. В папке исходников лежат все 4 примера галерей.
Исходники:
GalleryReview.zip
Комментариев нет:
Отправить комментарий