Урок 109. Android 3. Fragments. ListFragment - список
В этом уроке:
- работаем с ListFragment
Вернемся к фрагментам. В Android есть несколько полезных классов – наследников класса Fragment. Мы рассмотрим несколько из них. Начнем с ListFragment. В принципе, это просто Fragment, в котором есть методы, упрощающие доступ к ListView и некоторым его операциям.
Тут можно провести аналогию - для Activity есть класс наследник ListActivity. Когда мы только знакомились со списками, я не стал рассматривать этот класс, чтобы не вносить путаницы в непростую тему. Но в учебниках и хелпе о нем обычно говорят. Думаю, многие уже сталкивались с ним и примерно знают, что это такое. Если да, то ListFragment будет совсем прост для понимания.
Напишем приложение и рассмотрим основные возможности ListFragment.
Создадим проект:
Project name: P1091_ListFragment
Build Target: Android 4.1
Application name: ListFragment
Package name: ru.startandroid.develop.p1091listfragment
Create Activity: MainActivity
Создадим класс фрагмента, наследующий не android.app.Fragment как обычно, а android.app.ListFragment.
MainList.java:
package ru.startandroid.develop.p1091listfragment;
import android.app.ListFragment;
public class MainList extends ListFragment {
}
Класс так и оставляем пока пустым. И пока что не будем создавать Layout-файл для этого фрагмента. Дело в том, что ListFragment по умолчанию уже содержит ListView и мы вполне можем обойтись им. Адаптер мы пока также никакой не создаем, посмотрим чего получится.
Редактируем layout для MainActivity
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:name="ru.startandroid.develop.p1091listfragment.MainList"
android:layout_width="match_parent"
android:layout_height="match_parent">
</fragment>
</LinearLayout>
Здесь только компонент fragment, использующий наш класс.
Все сохраняем, запускаем приложение.
ListFragment показывает нам, что он ждет данных.
Ок, давайте дадим ему данные. Перепишем MainList.java:
package ru.startandroid.develop.p1091listfragment;
import android.app.ListFragment;
import android.os.Bundle;
import android.widget.ArrayAdapter;
public class MainList extends ListFragment {
String data[] = new String[] { "one", "two", "three", "four" };
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, data);
setListAdapter(adapter);
}
}
Мы создаем адаптер и используем метод setListAdapter, чтобы передать его списку. Обратите внимание - мы даже не создаем или не находим (findViewById) список (ListView), он уже есть где-то внутри фрагмента и метод setListAdapter сам знает, как до него добраться. В принципе, это и есть основная фишка ListFragment - нам не надо работать с ListView.
Все сохраним, запустим приложение.
Данные появились.
Еще раз обращаю ваше внимание на то, что мы вообще не создавали никаких layout с ListView. ListFragment работает с каким-то своим, встроенным списком.
Если же вас чем-то не устраивает этот дефолтный список, можно использовать свой layout-файл для фрагмента.
В strings.xml добавим строки
<string name="number_list">Список чисел</string>
<string name="empty">Нет данных</string>
И создадим layout файл fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/number_list">
</TextView>
<ListView
android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
<TextView
android:id="@id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/empty">
</TextView>
</LinearLayout>
Первый TextView – просто заголовок списка. Далее идет ListView. Его ID обязательно должен быть равен @id/android:list. Чтобы ListFragment сам его нашел и мог с ним работать. Второй TextView – будет показан, если нет данных для списка. Его ID обязательно должен быть равен @id/android:empty.
Допишем в MainList.java метод создания View.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment, null);
}
Фрагмент будет отображать компоненты из layout-файла, который мы только что создавали.
Все сохраняем и запускаем.
Видим заголовок и данные. Наш layout был использован.
Если не дать списку данные, то приложение будет выглядеть так
Отобразился наш второй TextView с ID = @id/android:empty. Причем, это вовсе не обязательно должен быть TextView. Главное тут именно этот ID. Компонент с этим ID будет показан вместо ListView, если нет данных.
Чтобы включать одиночный и множественный выбор, необходимо провести все те же действия, которые мы рассматривали в Уроке 43: передать в адаптер соответствующий layout-файл и включить соответствующий режим выбора для списка. В этом же 43-м Уроке можно посмотреть, как определять, какие пункты списка выбраны. Чтобы в ListFragment получить доступ к списку – используйте метод getListView.
Результаты включения режима выбора будут такие:
одиночный выбор
множественный выбор
Еще, как вариант, можно в адаптер передавать layout-файл android.R.layout.simple_list_item_activated_1.
В этом случае результаты будут такие:
Это хорошо подходит для случая, когда у вас на экране слева фрагмент-список, а справа фрагмент-содержимое и вы всегда видите какой именно пункт из списка сейчас просматриваете.
Чуть не забыл про самое главное ) Ловить нажатия можно в методе onListItemClick. Он очень похож на метод onItemClick из Урока 44.
Если добавим в MainList.java его реализацию:
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Toast.makeText(getActivity(), "position = " + position, Toast.LENGTH_SHORT).show();
}
то при нажатии на пункт списка, увидим результат:
На следующем уроке:
- работаем с DialogFragment