Некоторое время назад меня увлекла идея разработки приложений под платформу Android. Дабы не заниматься изучением платформы на простых hello-world программках решил сделать что-то такое, что позволило бы освоиться с UI частью фреймворка, работой с БД, сетью и социальными сервисами.
Идея была придумана до одурения простая и я бы даже сказал, тупая. И вот когда я начал что-то делать то тут резко захотелось мне сделать красивое диалоговое окно с выбором пункта меню с иконками. Такой диалог присутствует в стандартном Андроиде, например, долгий тап на рабочем столе открывает диалог выбора добавляемого контента (виджет, обоины и т.д.). Итак, добро пожаловать под кат…
Как было упомянуто выше передо мной стояла задача сделать диалоговое окно типа такого:
Погуглив некоторое время и почитав официальные доки по платформе я так и не нашел, как реализовать подобный диалог. После некоторого времени копания я нашел результат, который быстрее всего будет очевидным для опытных Андроид-разработчиков.
Ответ оказался прост и лежал он на поверхности. Суть его состоит в том, что для диалогового билдера нужно просто подставить соответствующий провайдер данных (есстественно, провайдер нужно самим написать).
Итак, сейчас будет некоторое количество кода с комментариями о том, что происходит.
Это простая обертка вокруг списка возможных типов аккаунтов. Тип аккаунта здесь простой POJO класс, который состоит из идентификатора (константа), названия сервиса и идентификатора ресурса иконки для данного типа сервиса.
Для начала нужно передать в конструктор список типов, с которым будет работать адаптер списка. Привязка конкретного item'а к лэйауту происходит в переопределенном методе getView(). В нем загружается лэйаут из указанного ресурса, извлекаются виджеты и в них записываются данные об конкретном элементе списка. Кстати, индекс этого элемента автоматически доступен через параметр position.
Все, что теперь осталось — это привязать разработанный лист-адаптер к конкретному диалоговому окну
и вызвать в нужном месте activity диалог
Диалог после своего завершения вернет индекс выбранного item'а параметром selectedItemId в листенер, который указан при вызове диалога. В данном простом случае этот индекс будет совпадать с ID типа аккаунта (item'а в списке), поэтому никаких дополнительных преобразований или извлечений не требуется. Для моей задачи этого индекса более чем достаточно.
В итоге у меня получился такой вот симпатичный диалог
Может я в данном топике просто описал прописные истины, может нет. Решать, как говорится, Вам, Хабраюзеры…
Спасибо и удачи всем в увлекательном процессе разработки под Android-платформу ;)
Идея была придумана до одурения простая и я бы даже сказал, тупая. И вот когда я начал что-то делать то тут резко захотелось мне сделать красивое диалоговое окно с выбором пункта меню с иконками. Такой диалог присутствует в стандартном Андроиде, например, долгий тап на рабочем столе открывает диалог выбора добавляемого контента (виджет, обоины и т.д.). Итак, добро пожаловать под кат…
Как было упомянуто выше передо мной стояла задача сделать диалоговое окно типа такого:
Погуглив некоторое время и почитав официальные доки по платформе я так и не нашел, как реализовать подобный диалог. После некоторого времени копания я нашел результат, который быстрее всего будет очевидным для опытных Андроид-разработчиков.
Ответ оказался прост и лежал он на поверхности. Суть его состоит в том, что для диалогового билдера нужно просто подставить соответствующий провайдер данных (есстественно, провайдер нужно самим написать).
Итак, сейчас будет некоторое количество кода с комментариями о том, что происходит.
Список (провайдер) возможных типов аккаунтов
- public final class AccountTypesProvider {
- public static List<AccountType> accountTypes = Collections.unmodifiableList(Arrays.asList(
- new AccountType(AccountType.TWITTER_ACCOUNT, "Twitter", R.drawable.twitter_icon_big),
- new AccountType(AccountType.FACEBOOK_ACCOUNT, "Facebook", R.drawable.facebook_icon_big),
- new AccountType(AccountType.BUZZ_ACCOUNT, "Google Buzz", R.drawable.buzz_icon_big),
- new AccountType(AccountType.LINKEDIN_ACCOUNT, "LinkedIn", R.drawable.linkedin_icon_big),
- new AccountType(AccountType.VKONTAKTE_ACOUNT, "ВКонтакте", R.drawable.vkontakte_icon_big)
- ));
- }
* This source code was highlighted with Source Code Highlighter.
Это простая обертка вокруг списка возможных типов аккаунтов. Тип аккаунта здесь простой POJO класс, который состоит из идентификатора (константа), названия сервиса и идентификатора ресурса иконки для данного типа сервиса.
ListAdapter для отображения списка типов аккаунтов в заданном layout'е
- public final class AccountsTypesListAdapter extends ArrayAdapter<AccountType> {
- private Activity context;
- private List<AccountType> accountTypes;
-
- public AccountsTypesListAdapter(Activity context, List<AccountType> accountTypes) {
- super(context, R.layout.select_account_item, accountTypes);
-
- this.context = context;
- this.accountTypes = accountTypes;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- LayoutInflater inflater = context.getLayoutInflater();
- View row = inflater.inflate(R.layout.select_account_item, parent, false);
-
- TextView label = (TextView) row.findViewById(R.id.text_item);
- label.setText(accountTypes.get(position).title);
-
- ImageView icon = (ImageView) row.findViewById(R.id.icon_item);
- icon.setImageResource(accountTypes.get(position).bigIconId);
-
- return row;
- }
- }
* This source code was highlighted with Source Code Highlighter.
Для начала нужно передать в конструктор список типов, с которым будет работать адаптер списка. Привязка конкретного item'а к лэйауту происходит в переопределенном методе getView(). В нем загружается лэйаут из указанного ресурса, извлекаются виджеты и в них записываются данные об конкретном элементе списка. Кстати, индекс этого элемента автоматически доступен через параметр position.
Данный лист-адаптер работает с таким вот лэйаутом
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal" android:layout_width="fill_parent"
- android:layout_height="fill_parent" android:padding="10px">
-
- <ImageView android:id="@+id/icon_item" android:layout_width="wrap_content"
- android:layout_height="fill_parent"/>
- <TextView android:id="@+id/text_item" android:layout_width="wrap_content"
- android:layout_height="fill_parent" android:paddingLeft="10px"
- android:paddingTop="5px" android:textStyle="bold"
- android:textColor="#000000"/>
- </LinearLayout>
* This source code was highlighted with Source Code Highlighter.
Все, что теперь осталось — это привязать разработанный лист-адаптер к конкретному диалоговому окну
- public static void showSelectAccountTypeDialog(Activity context, String title, OnClickListener dialogListener) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(title);
- builder.setAdapter(new AccountsTypesListAdapter(context, AccountTypesProvider.accountTypes), dialogListener);
- builder.create().show();
- }
* This source code was highlighted with Source Code Highlighter.
и вызвать в нужном месте activity диалог
- private void displaySelectAccountTypeDialog() {
- ApplicationDialogs.showSelectAccountTypeDialog(this, "Select network", new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int selectedItemId) {
- setupAccount(selectedItemId);
- }
- });
- }
* This source code was highlighted with Source Code Highlighter.
Диалог после своего завершения вернет индекс выбранного item'а параметром selectedItemId в листенер, который указан при вызове диалога. В данном простом случае этот индекс будет совпадать с ID типа аккаунта (item'а в списке), поэтому никаких дополнительных преобразований или извлечений не требуется. Для моей задачи этого индекса более чем достаточно.
В итоге у меня получился такой вот симпатичный диалог
Может я в данном топике просто описал прописные истины, может нет. Решать, как говорится, Вам, Хабраюзеры…
Спасибо и удачи всем в увлекательном процессе разработки под Android-платформу ;)