Форум программистов, компьютерный форум CyberForum.ru

PopupWindow. Что осталось за кадром? (Tutorial) - Программирование Android

Войти
Регистрация
Восстановить пароль
Другие темы раздела
Программирование Android Доступ из активити в фрагмент http://www.cyberforum.ru/android-dev/thread1247958.html
Здравствуйте, такой вопрос есть активити import java.io.File; import java.io.IOException; import java.text.DecimalFormat;
Программирование Android Drawable для нажатия на RelativeLayout В LinearLayout я засунул два RelativeLayout, а также создал drawable selector в котором при нажатии меняется цвет. При нажатии на один RelativeLayout цвет почему-то меняется и на втором. Почему так? Добавлено через 3 часа 55 минут Вот разметка <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ... http://www.cyberforum.ru/android-dev/thread1247916.html
Как создать ListView с двумя TextView и работать с ними Программирование Android
Как создать ListView с двумя TextView и работать с ними использую класс Adapter(Ну или чем то похожим если такое существует).
Программирование Android Как замостить изображение?
Когда я хочу разместить картинку на форме в самый крайний угол или сторону, система не позволяет сделать так, чтобы изображение начиналось именно с самого левого или иного края, все равно остается белая полоса. Как сделать так, чтобы вставляемый мною объект начинался чисто с самого края? И второй вопрос. На изображении видно, где у меня расположен квадрат с колесами(стоит на земле), но когда я...
Программирование Android Кто знает как отследить button.setOnClickListener? http://www.cyberforum.ru/android-dev/thread1247839.html
хочу что то типа button.setOnTouchListener(this); @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (view.getId()){ case R.id.btn: switch (motionEvent.getAction()){ case MotionEvent.ACTION_DOWN: ////тратататата
Программирование Android WifiManager и Service Добрый день, господа! Возник интересный вопрос, можно и использовать WifiManager в сервисе? Если да, то как? Заранее спасибо. Добавлено через 2 часа 2 минуты Вопрос можно удалить, ступил. подробнее

Показать сообщение отдельно
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,723

PopupWindow. Что осталось за кадром? (Tutorial) - Программирование Android

27.08.2014, 17:46. Просмотров 1767. Ответов 7
Метки (Все метки)

Здравствуйте!
Недавно потребовалось сделать выпадающий список более вменяемым, чем это бывает у Spinner. Поискав, понял, что лучше всего в этом деле пригодится связка EditText + PopupWindow с ListView. Вариант с Dialog показался мне сложным или нереализуемым, поэтому выбор пал на PopupWindow.
Подпрограмма должна:
1) при нажатии на EditText открывать выпадающий список,
2) при нажатии на список сохранять выбранный элемент в EditText и закрывать список,
3) при нажатии вне списка закрывать список.
К сожалению, нормальных документов найти не смог и потому написал свою подпрограмму. Большинство авторов воспринимают PopupWindow как разновидность диалогового окна, в то время как там можно нарисовать не только надпись с кнопкой. Буду рад, если кому пригодится. Весь код пишу по памяти, он может не работать, но общую концепцию понять можно.
Итак, для начала научимся показывать всплывающее окно с какой-нибудь кнопкой (потом переделаем). Добавим файл с разметкой, назовём её popup_layout.xml:
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Привет!"
        android:layout_gravity="center_horizontal" />
 
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Закрыть"
        android:layout_gravity="center_horizontal" />
</LinearLayout>
В форму, из которой будете вызывать PopupWindow, добавьте текстовое поле. Под ним будет появляться PopupWindow. Назовём его, например, txtCategory.
Java
1
2
3
4
5
6
7
8
9
private void showCategoriesWindow(LayoutInflater inflater) {
    /*Поскольку я открывал PopupWindow из Fragment, то инициализировать inflater не пришлось (передаём его из 
            onCreateView(final LayoutInflater inflater, ViewGroup viewGroup, Bundle SavedInstanceState)
    Если же вы вызываете PopupWindow из Activity, то инициализируем её так:
            LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);*/
    View popupView = inflater.inflate(R.layout.popup_layout, null);
    popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    popupWindow.showAsDropDown(txtCategory, 50, -20);
}
Далее запускаем:
Java
1
2
3
4
5
6
7
8
9
@Override
public View onCreateView(final LayoutInflater inflater, ViewGroup viewGroup, Bundle SavedInstanceState) {
    View v = inflater.inflate(R.layout.fragment, viewGroup, false);
    ...
    EditText txtCategory = (EditText) v.findViewById(R.id.category);
    ...
    showCategoriesWindow(inflater);
    ...
}
Должно появиться окно с прозрачным фоном, находящееся недалеко от txtCategory (координаты можете заменить на свои). Закроем программу и напишем код для закрытия всплывающего окна.
Java
1
2
3
4
5
6
7
    Button btnClose = (Button) popupView.findViewById(R.id.button);
    btnClose.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            popupWindow.dismiss();
        }
    });
Теперь при нажатии кнопки PopupWindow будет исчезать. Если PopupWindow не закрыть, а затем закрыть приложение или перейти на другую форму, то приложение будет выдавать в LogCat ошибку. Большинство авторов про неё не упоминают.
Исправим сей недостаток:
Java
1
2
3
4
5
6
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (popupWindow != null)
            popupWindow.dismiss();
    }
Теперь попробуем улучшить разметку для PopupWindow. Сделаем не банальную кнопку, а список. Создайте разметку и назовите файл category_list.xml.
Например, так:
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">
 
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Закрыть"
        android:layout_gravity="center_horizontal" />
 
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>
Добавим также описание каждого элемента списка. Будем сокращать не влезающие в экран строки (назовём файл category_list_item.xml):
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="utf-8"?>
 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white" >
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="17sp"
        android:ellipsize="end"
        android:singleLine="true"
        android:text="sample"
        android:gravity="center_vertical" />
 
</LinearLayout>
Свяжем PopupWindow со списком:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void showCategoriesWindow(LayoutInflater inflater) {
    View popupView = inflater.inflate(R.layout.category_list, null);
    popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    popupWindow.showAsDropDown(txtCategory, 0, 0);
 
    final ArrayList<String> arrList = new ArrayList<String>();
    // Заполните здесь arrList несколькими строчками.
    arrList.add("Россия");
    arrList.add("Беларусь");
    arrList.add("Украина");
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(
        getActivity().getApplicationContext(), R.layout.category_list_item, R.id.textView, arrList);
    final ListView listView = (ListView) popupView.findViewById(R.id.listView);
    listView.setAdapter(adapter);
 
    Button btnClose = (Button) popupView.findViewById(R.id.button);
    btnClose.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            popupWindow.dismiss();
        }
    });
}
Теперь при вызове showCategoriesWindow будет открываться окно с белым фоном, кнопкой и списком. Доработаем пример. Хочется, чтобы окно закрывалось при нажатии на элемент списка, а само значение попадало бы в текстовую надпись на форме.
Для этого вместо последних строк (закрытия окна по нажатию кнопки) напишем другие.
Java
1
2
3
4
5
6
7
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            txtCategory.setText(arrList.get(position));
            popupWindow.dismiss();
        }
    });
Теперь кнопку btnClose можно убрать из кода и разметки. Но если мы вызовем получившуюся процедуру, то увидим, что окно не закрывается. Оказывается (об этом тоже мало где написано), ListView не получает фокуса.
Исправим недочёт. Для этого можно, например, создание окна сделать с параметром true в конце:
Java
1
popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
Кстати, второй параметр при вызове этой процедуры - ширина окна, можете поменять её.
Кроме того, оказалось, что если пользователь нажимает пальцем за пределами PopupWindow, то ничего не происходит. А хотелось бы, чтобы список закрывался. Исправим процедуру.
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void showCategoriesWindow(LayoutInflater inflater) {
    View popupView = inflater.inflate(R.layout.category_list, null);
    popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
    popupWindow.setBackgroundDrawable(new ColorDrawable());
    popupWindow.setOutsideTouchable(true);
    popupWindow.showAsDropDown(txtCategory, (int)(txtCategory.getWidth() * 0.1), 0);
 
    final ArrayList<String> arrList = new ArrayList<String>();
    arrCategoryId = new ArrayList<Integer>();
 
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(
        getActivity().getApplicationContext(), R.layout.category_list_item, R.id.textView, arrList);
    final ListView listView = (ListView) popupView.findViewById(R.id.listView);
    listView.setAdapter(adapter);
    arrList.add("Россия");
    arrList.add("Беларусь");
    arrList.add("Украина");
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            txtCategory.setText(arrList.get(position).trim());
            iCategory = arrCategoryId.get(position);
            popupWindow.dismiss();
        }
    });
}
Многие авторы в четвёртой строке пишут new BitmapDrawable(), но этот код устарел. Я пробовал посоветованный на stackoverflow вариант ShapeDrawable(), но у него есть один небольшой недостаток. Если ваше PopupWindow будет иметь, например, скруглённые углы, то в самых краях этих углов появятся чёрные точки. Поэтому я использовал ColorDrawable().
Осталось научить программму открывать и закрывать всплывающее окно по нажатию на текстовое поле.
Java
1
2
3
4
5
6
7
8
9
10
11
txtCategory.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (popupWindow == null) {
            showCategoriesWindow(inflater);
        }
        if (!popupWindow.isShowing()) {
            popupWindow.showAsDropDown(txtCategory, 0, 0);
        }
    }
});
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru