Список с изображениями android

Системные графические ресурсы

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

Для начала нужно отметить, что описание графических системных ресурсов можно найти на официальной странице для разработчиков под Android. Там можно узнать названия ресурсов, а также их числовые значения (константы).

Мы можем использовать системное изображение в своих целях, например, в примере создания текстового редактора для получения изображения дискеты к пункту меню «Сохранить» я использовал конструкцию:

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

res/layout/activity_main.xml

res/layout/row.xml

Добавим ещё один xml-файл для разметки элемента списка:

Теперь напишем сам код для основного класса приложения:

Запустив приложение, мы увидим прокручиваемый список с изображениями, которые используются системой Android для своих нужд.

Несмотря на кажущееся удобство использования встроенных системных ресурсов, данный способ не рекомендован компанией Google. Свою позицию они объясняют тем, что нет никаких гарантий, что в новых версиях Android останутся те же изображения, а также сохранятся их константы. В самом деле, в новых версиях происходят небольшие изменения и в словах Google есть небольшой резон.

Но, что делать разработчику, если очень хочется использовать системную графику в своих приложениях для придания профессионального вида? Выход есть! Купите моему коту полкило колбасы, и я открою вам тайну. Пока вы собираете деньги на покупку, я продолжу свой рассказ.

Если вы устанавливали Android SDK (а вы наверняка его устанавливали), то самое время найти ее папку. Далее перейдите в какую-нибудь папку типа platforms\android-НомерВерсии\data\res\drawable-hdpi. Например, на моем компьютере под Windows 8 путь выглядит как D:\Android\SDK\platforms\android-23\data\res\drawable-hdpi. В этой и других схожих папках вы найдете все необходимые вам системные изображения. Скопируйте нужно вам изображение в свой проект в качестве собственных ресурсов и пользуйтесь на здоровье.

Список drawable-ресурсов через рефлексию

Рефлексия всегда считалась нежелательной из-за потребления ресурсов. Только для общего развития.

Источник

ListView. Списки со значками

Расширим возможности списка, добавив в него значки. Такой список будет выглядеть гораздо интереснее для пользователя. За основу возьмём пример обычного списка с именами котов.

Подготовим разметку для отдельного элемента списка, который должен уметь отображать текст и значок (файл res/layout/list_item.xml):

Теперь переходим к java-коду. Мы воспользуемся ListActivity и код станет очень коротким.

В методе setListAdapter() мы сообщаем, что разметку для отдельного элемента списка надо брать из R.layout.list_item, текст размещать в компоненте с идентификатором R.id.text_view_cat_name, а массив текстов брать из mCatNames.

Запустив пример, мы получим готовое приложение, состоящее из списка с одинаковыми значками. Вы можете, как и прежде, щёлкать по пунктам и прокручивать список.

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

Вся магия содержится в методе адаптера getView(). Мы можем задать для каждого элемента списка свой значок. Добавим в проект значки для знаков зодиака. Для простоты в этом примере я покажу изменение одного знака зодиака Лев, который относится к семейству кошачьих. Разметка может оставаться прежней, только поменяйте идентификатор у TextView (по коду вы должны сами понять, на какой именно).

Читайте также:  Аудиоплеер для андроида самсунг

По такому же принципу вы можете усложнять пример, например, вычислять чётные и нечётные элементы списка и выводить значки, раскрашивать зеброй и т.д.

Немного информации о классе LayoutInflater. Класс берёт данные из XML-файла разметки и превращает их в реальные компоненты, которые становятся частью списка. Вам надо только указать источник для конвертации через метод inflate().

После этого, система понимает, где искать отдельные компоненты разметки. Мы вызываем знакомый нам метод findViewById(), только он уже относится не к активности, а к корневому элементу разметки. Поэтому мы вызываем метод из row.

Но чего-то не хватает в этом примере. Давайте под каждым названием будем выводить еще дату, которая относится к знаку зодиака. Стандартный подход здесь не сработает. Во-первых, у нас будет два отдельных массива строк (названия и даты), а стандартный адаптер работает с одним массивом. Выход — опять написать собственный адаптер под нашу задачу. Заодно подключим и остальные значки.

Сначала изменим макет для списка.

Теперь напишем свой адаптер и внесём изменения в код

Готовый результат выглядит гораздо лучше предыдущих примеров.

Здесь сразу хочу обратить внимание на сравнение if (convertView == null). Для данного примера это не принципиально, так как у нас список состоит всего из 12 элементов. Если счёт элементов пойдёт на сотни, то это уже вызовет проблемы с памятью. Вы просите систему создать более сотни новых компонентов, да ещё с картинками. Но в реальности вы на экране не видите сто элементов списка одновременно, а только часть из них. И был предложен хитрый механизм — не создавать новую строку списка при прокрутке, а использовать уже созданный ранее элемент и подгружать в него данные. Таким образом мы создаём элементы только для первых строк списка, видимых на экране. Допустим, экран вмещает десять строк списка, а остальные 90 с лишним элементов подгрузятся динамически. Это самый простой, но эффективный способ повышения производительности. Более продвинутые способы повышения производительности смотрите в статье Производительность при работе с ListView.

Полосатый ListView

Коты бывают полосатыми. Давайте и ListView сделаем полосатым. Делается элементарно, всего одной строчкой кода.

В метод getView() из предыдущего примера вставляем:

В этом уроке рассматривается более продвинутый вариант полосатой разметки.

При подготовке материала использовалась статья Программирование для android — Списки

Напоследок советую вам использовать в качестве корневого элемента RelativeLayout вместо LinearLayout — первый вариант использует намного меньше ресурсов и постоянно пропагандируется в документации.

Источник

Полный список

— используем ListView для построения списка

Перед тем, как начать говорить про компонент ListView, предлагаю вспомнить еще раз прошлый урок и механизм построения списка, который мы там использовали. Мы перебирали массив данных, в каждой итерации создавали пункт списка, заполняли его данными и помещали в список.

При создании ListView создавать пункты за нас будет адаптер. Адаптеру нужны от нас данные и layout-ресурс пункта списка. Далее мы присваиваем адаптер списку ListView. Список при построении запрашивает у адаптера пункты, адаптер их создает (используя данные и layout) и возвращает списку. В итоге мы видим готовый список.

Есть различные типы списков и адаптеров. Мы пока что рассмотрим простейший вариант.

Project name: P0421_SimpleList
Build Target: Android 2.3.3
Application name: SimpleList
Package name: ru.startandroid.develop.p0421simplelist
Create Activity: MainActivity

Читайте также:  Android 4 для huawei vision

Открываем main.xml и добавим на экран компонент ListView (вкладка Composite):

ListView – это и есть компонент списка.

Теперь надо создать адаптер. Открываем MainActivity.java и пишем:

Вы не поверите, но это весь код, необходимый для создания списка )

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

и передали ему следующие параметры:

this – контекст
android.R.layout.simple_list_item_1 – это системный layout-файл, который представляет собой TextView
names – массив данных, которые мы хотим вывести в список

Мы можем посмотреть содержимое использованного simple_list_item_1. Для этого в вашем проекте найдите пункт Android 2.3.3., раскройте его, и раскройте android.jar

Проматывайте в самый низ и открывайте res.layout.

И внутри находим используемый нами simple_list_item_1

Двойной клик на него и смотрим содержимое:

Обычный TextView с набором параметров.

Когда список при формировании запрашивает очередной пункт, адаптер берет этот Layout-ресурс simple_list_item_1, прогоняет его через LayoutInflater и получает View, преобразует View к TextView, присваивает ему текст из массива данных и отдает списку.

Все сохраним и запустим. Видим список из наших данных.

Использование системного layout-ресурса simple_list_item_1 хорошо тем, что нам не надо самим layout рисовать. Однако, если нас не устраивает то, как выглядит список с использованием simple_list_item_1 в качестве пункта списка, мы можем создать свой layout-ресурс.

Создадим layout-файл my_list_item.xml в папке res/layout нашего проекта:

TextView с указанием цвета и размера шрифта, выравнивания текста и отступов.

Изменим существующий код, укажем адаптеру наш созданный layout-ресурс my_list_item:

Теперь адаптер будет использовать его при создании пунктов списка.

Все сохраним и запустим. Видим наш зеленый список:

В layout-ресурсе для пункта списка вместо TextView вы можете использовать какой-нибудь его производный класс – например Button. Главное, чтобы объект прошел преобразование к TextView. Адаптер присвоит ему текст методом setText и отдаст списку.

Немного про Context

На одном из прошлых уроков я говорил, что Context (контекст) используется для доступа к базовым функциям приложения. В этом уроке у нас получилось хорошее подтверждение этим словам.

ArrаyAdapter использует LayoutInflater, чтобы конвертнуть layout-ресурс в View. Но получение объекта LayoutInflater – это одна из базовых функций и она недоступна для класса ArrаyAdapter. Поэтому мы в ArrаyAdapter в качестве контекста передаем ссылку на Activity (Activity имеет доступ к базовым функциям через восходящую иерархию классов). А класс ArrayAdapter внутри себя использует переданный ему контекст, чтобы вызвать LayoutInflater. Без контекста он не смог бы это сделать.

На следующем уроке:

— используем список ListView для одиночного и множественного выбора элементов

public ArrayAdapter (Context context, int textViewResourceId, T[] objects)

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Как реализовать загрузку изображений в список в отдельном потоке на Android


По просьбам трудящихся, статья о методе загрузки изображений в список в отдельном потоке на Android.

Задача:

Реализовать механизм загрузки изображений из Интернета и отображения их в списке. При этом загрузка изображений должна быть реализована в отдельном потоке, во избежания «зависания» UI приложения.

Читайте также:  Android app activitythread main

Реализация:

Для реализации поставленной задачи использованы стандартный виджет ListView и адаптер — ArrayAdapter. Для работы с изображениями создан helper-класс ImageManager, который имеет два метода downloadImage() и fetchImage(). Первый загружает изображений из Интернета. Второй — вызывает загрузку изображений в отдельном потоке и устанавливает результат в ImageView.

Пример испольования:

Реализацию поставленной задачи будем расматривать на примере моего проекта. И на его код я буду ссылаться в статье.
Исходники: fileshare.in.ua/3053597
APK: fileshare.in.ua/3053596

Описание реализации:

  1. package com.rudenko.android.ListIconFetching;
  2. import java.io.BufferedInputStream;
  3. import java.io.IOException;
  4. import java.net.HttpURLConnection;
  5. import java.net.MalformedURLException;
  6. import java.net.URL;
  7. import android.graphics. Bitmap ;
  8. import android.graphics.BitmapFactory;
  9. import android.os.Handler;
  10. import android.os.Message;
  11. import android.util.Log;
  12. import android.widget.ImageView;
  13. public class ImageManager <
  14. private final static String TAG = «ImageManager» ;
  15. /** Private constructor prevents instantiation from other classes */
  16. private ImageManager () <>
  17. public static void fetchImage(final String iUrl, final ImageView iView) <
  18. if ( iUrl == null || iView == null )
  19. return ;
  20. final Handler handler = new Handler() <
  21. @Override
  22. public void handleMessage(Message message) <
  23. final Bitmap image = ( Bitmap ) message.obj;
  24. iView.setImageBitmap(image);
  25. >
  26. >;
  27. final Thread thread = new Thread() <
  28. @Override
  29. public void run() <
  30. final Bitmap image = downloadImage(iUrl);
  31. if ( image != null ) <
  32. Log.v(TAG, «Got image by URL: » + iUrl);
  33. final Message message = handler.obtainMessage(1, image);
  34. handler.sendMessage(message);
  35. >
  36. >
  37. >;
  38. iView.setImageResource(R.drawable.icon);
  39. thread.setPriority(3);
  40. thread.start();
  41. >
  42. public static Bitmap downloadImage( String iUrl) <
  43. Bitmap bitmap = null ;
  44. HttpURLConnection conn = null ;
  45. BufferedInputStream buf_stream = null ;
  46. try <
  47. Log.v(TAG, «Starting loading image by URL: » + iUrl);
  48. conn = (HttpURLConnection) new URL(iUrl).openConnection();
  49. conn.setDoInput( true );
  50. conn.setRequestProperty( «Connection» , «Keep-Alive» );
  51. conn.connect();
  52. buf_stream = new BufferedInputStream(conn.getInputStream(), 8192);
  53. bitmap = BitmapFactory.decodeStream(buf_stream);
  54. buf_stream.close();
  55. conn.disconnect();
  56. buf_stream = null ;
  57. conn = null ;
  58. > catch (MalformedURLException ex) <
  59. Log.e(TAG, «Url parsing was failed: » + iUrl);
  60. > catch (IOException ex) <
  61. Log.d(TAG, iUrl + » does not exists» );
  62. > catch (OutOfMemoryError e) <
  63. Log.w(TAG, «Out of memory. » );
  64. return null ;
  65. > finally <
  66. if ( buf_stream != null )
  67. try < buf_stream.close(); >catch (IOException ex) <>
  68. if ( conn != null )
  69. conn.disconnect();
  70. >
  71. return bitmap;
  72. >
  73. >

* This source code was highlighted with Source Code Highlighter .

Метод fetchImage():

public static void fetchImage(final String iUrl, final ImageView iView);

Входные параметры:

iUrl — URL к изображению для загрузки
iView — ссылка на виджет ImageView, которому будет назначено изображение после загрузки.
Оба параметра являются обязательными.

Результат:

Функция не возвращает ничего.

Краткое описание:

Функция создает поток для загрузки изображения. На время загрузки во входной ImageView устанавливается стандартное изображение. После завершения загрузки, изображение входного ImageView обновляется загруженным.

Несколько слов о потоке: в строке 46 происходит понижение приоритета потока. Это сделано для того, что бы данный поток не забирал ресурсы необходимые для корректной работы приложения.

Метод downloadImage():

public static Bitmap downloadImage( String iUrl);

Входные параметры:

iUrl — URL к изображению для загрузки

Результат:

Изображение загруженное из интернета, либо Null — если операция не была выполнена успешно.

Краткое описание:

В функции создается соединение с сервером, где находится изображение. Происходит получение входного потока, который далее передается в BitmapFactory для создания изображения.

Как использовать ImageManager:

Рассмотрим на примере к статье. В методе FetchImageAdapter.getView(), для подгрузки изображений в ImageView строки списка, используется следующая строка:
ImageManager.fetchImage(android.image, holder.ib_logo);
где android.image — URL к изображению, а holder.ib_logo — ImageView строки списка.

Заключение:

Данный механизм подходит для загрузки изображения из Интернета в параллельном потоке, для любого виджета ImageView Android. Т. е. данный механизм можно использовать не только для конкретно поставленной задачи.

Источник

Оцените статью