Статьи

Android ListView — учебник и базовый пример

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

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

очень простой и простой адаптер под названием SimpleAdapter .

Итак, давайте создадим проект Android с действием MainActivity и макетом Activity_main.xml . Этот макет очень прост, он просто содержит компонент listView.

01
02
03
04
05
06
07
08
09
10
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
 
    <ListView android:id="@+id/listView"
              android:layout_height="match_parent"
              android:layout_width="match_parent"/>
 
</RelativeLayout>

Наш класс MainActivity это:

01
02
03
04
05
06
07
08
09
10
public class MainActivity extends Activity {
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ....
    }
...
}

Так что теперь пришло время заполнить наш listView. Как было сказано ранее, мы используем SimpleAdapter, стандартный адаптер, присутствующий в SDK. Предположим, мы хотим показать список с планетами Солнечной системы. SimpleAdapter принимает java.util.List с типом элемента java.util.Map . В нашем случае мы имеем:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// The data to show
List<Map<String, String>> planetsList = new ArrayList<Map<String,String>>();
 
.....
 
   private void initList() {
    // We populate the planets
 
    planetsList.add(createPlanet("planet", "Mercury"));
    planetsList.add(createPlanet("planet", "Venus"));
    planetsList.add(createPlanet("planet", "Mars"));
    planetsList.add(createPlanet("planet", "Jupiter"));
    planetsList.add(createPlanet("planet", "Saturn"));
    planetsList.add(createPlanet("planet", "Uranus"));
    planetsList.add(createPlanet("planet", "Neptune"));
 
}
 
private HashMap<String, String> createPlanet(String key, String name) {
    HashMap<String, String> planet = new HashMap<String, String>();
    planet.put(key, name);
 
    return planet;
}

и SimpleAdapter может быть создан как:

1
2
3
4
5
6
7
// This is a simple adapter that accepts as parameter
// Context
// Data list
// The row layout that is used during the row creation
// The keys used to retrieve the data
// The View id used to show the data. The key number and the view id must match
simpleAdpt = new SimpleAdapter(this, planetsList, android.R.layout.simple_list_item_1, new String[] {"planet"}, new int[] {android.R.id.text1});

где первый параметр — это ссылка на контекст (наша активность), второй — данные, которые мы хотим отобразить в списке. Третье — это макет, который мы хотим использовать для каждой строки в списке. В этом случае мы просто использовали готовый макет, поставляемый с Android SDK, который вы можете найти внутри android sdk directroy, а затем платформы \ android-16 \ data \ res \ layout . Это очень простой макет, который содержит только TextView с идентификатором text1. Четвёртый параметр — это массив ключей, используемый для получения данных с карты. Каждый элемент списка в java.util.List представляет строку в ListView, и каждый элемент внутри строки должен иметь уникальный ключ, который используется для получения содержимого элемента. В нашем случае, чтобы сделать вещи очень простыми, мы просто использовали планету в качестве ключа. Пятый элемент — это массив int, представляющий идентификаторы View внутри макета строки. В нашем случае это просто text1 id. Обратите внимание, что длина массива ключей должна соответствовать длине массива идентификаторов.

Мы почти закончили. Давайте изменим метод onCreate в нашей Activity следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    initList();
 
    // We get the ListView component from the layout
    ListView lv = (ListView) findViewById(R.id.listView);
 
    // This is a simple adapter that accepts as parameter
    // Context
    // Data list
    // The row layout that is used during the row creation
    // The keys used to retrieve the data
    // The View id used to show the data. The key number and the view id must match
    simpleAdpt = new SimpleAdapter(this, planetsList, android.R.layout.simple_list_item_1, new String[] {"planet"}, new int[] {android.R.id.text1});
 
    lv.setAdapter(simpleAdpt);
}

Если мы запустим наш проект, у нас будет:

Взаимодействие с пользователем

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

Если мы хотим слушать, когда пользователь нажимает на элемент, нам просто нужно реализовать AdapterView.OnItemClickListener (). Итак, мы имеем:

01
02
03
04
05
06
07
08
09
10
11
12
13
// React to user clicks on item
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
 
     public void onItemClick(AdapterView<?> parentAdapter, View view, int position,
                             long id) {
 
         // We know the View is a TextView so we can cast it
         TextView clickedView = (TextView) view;
 
         Toast.makeText(MainActivity.this, "Item with id ["+id+"] - Position ["+position+"] - Planet ["+clickedView.getText()+"]", Toast.LENGTH_SHORT).show();
 
     }
});

Когда пользователь нажимает на элемент, мы просто показываем позицию и идентификатор элемента, щелкнувшего с помощью простого тоста.

Что если мы хотим создать контекстное меню, когда пользователь долго нажимает на элемент? Ну, это очень просто, потому что мы должны переопределить метод onCreateContextMenu в классе Activity и зарегистрировать класс в качестве слушателя. Сначала переопределите метод:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
// We want to create a context Menu when the user long click on an item
  @Override
  public void onCreateContextMenu(ContextMenu menu, View v,
          ContextMenuInfo menuInfo) {
 
      super.onCreateContextMenu(menu, v, menuInfo);
      AdapterContextMenuInfo aInfo = (AdapterContextMenuInfo) menuInfo;
 
      // We know that each row in the adapter is a Map
      HashMap map =  (HashMap) simpleAdpt.getItem(aInfo.position);
 
      menu.setHeaderTitle("Options for " + map.get("planet"));
      menu.add(1, 1, 1, "Details");
      menu.add(1, 2, 2, "Delete");
 
  }

Что мы делаем в этом методе? Ну, во-первых, мы называем супер, чтобы SO работал. Затем мы приводим ContextMenuInfo к AdapterContextMenuInfo, потому что мы используем ListView. AdapterContextMenuInfo имеет атрибут, который устаревает позицию элемента, по которой щелкнули, поскольку мы используем эту информацию для получения информации об элементе. Мы знаем, что используем HashMap для представления строки, поэтому мы приводим результат к HashMap. Это время, когда мы создаем меню.

Сначала мы создаем заголовок меню, используя имя планеты, полученное с помощью HashMap, а затем устанавливаем две опции « Детали » и « Удалить » с разными идентификаторами, но принадлежащие к той же группе, которую мы назвали «1».

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

1
2
// we register for the contextmneu       
registerForContextMenu(lv);

Давайте запустим наш проект, и когда мы будем долго нажимать на элемент, мы получим:

Последний шаг — дескриптор, когда пользователь нажимает на один из вариантов. Мы должны переопределить метод onContextItemSelected следующим образом:

1
2
3
4
5
6
7
8
// This method is called when user selects an Item in the Context menu
@Override
public boolean onContextItemSelected(MenuItem item) {
    int itemId = item.getItemId();
    // Implements our logic
    Toast.makeText(this, "Item id ["+itemId+"]", Toast.LENGTH_SHORT).show();
    return true;
}

В этом случае мы просто показываем тост с идентификатором пункта меню.

Ссылка: Android ListView — учебное пособие и базовый пример от нашего партнера по JCG Франческо Аццолы из блога Surviving w / Android .