субота, 3 лютого 2018 р.

ListView з власним адаптером (Android)

Стандартні адаптери для ListView реалізовані для простих стандартних списків, які складаються або з простих текстових полів, або з текстових полів та якогось перемикача (прапорця або радіокнопки). Якщо необхідно реалізувати, щось інше, то необхідно реалізувати власний адаптер, який би відображав пункти списку в потрібному вигляді.

Завдання
Реалізуймо список, який би відображав телефонну книгу і кожен пункт включав би фото, ім’я та номер телефону. Після натиснення на пункті списку виводитиметься відповідне повідомлення.

Підготовка
Спочатку створюємо проект з пустою активністю ListActivity.java 
У папочку res/drawable необхідно закинути зображення, які будуть використовуватися в якості фото.

Для того, щоб програма запрацювала нам знадобиться чотири файли:
ListActivity.java – головна активність програми
Person.java – клас, що містить інформацію про особу (фото, ім’я та телефон)
activity_list.xml – макет активності ListActivity.java (містить віджети TextView та ListView)
item_list.xml – макет пункту списку, в якому вказується як відображатиметься фото і текст, відображенням його на екран займатиметься адаптер, що буде внутрішнім класом у ListActivity.java.





Далі створюємо наш макет активності activity_list.xml



<?xml version="1.0" encoding="utf-8"?>
<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="ua.kyiv.volodimirg.mylistview.ListActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Моя телефонна книга"
        android:minHeight="50dp"
        android:textStyle="bold"
        android:textSize="20dp"
        android:id="@+id/textView"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:clickable="false"
        />

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/phonelistView"
        android:layout_below="@+id/textView"
        />
</RelativeLayout>

Другий макет Item_list.xml – містить вигляд пункту списку

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
    >

    <ImageView
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:id="@+id/personPhoto"
        android:paddingEnd="10dp"
        android:paddingStart="10dp"
        android:src="@drawable/smile2"
        android:focusable="false"
        android:clickable="false"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="First And Last Name"
        android:id="@+id/txtName"
        android:layout_alignParentTop="true"
        android:layout_toEndOf="@+id/personPhoto"
        android:focusable="false"
        android:clickable="false"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="phone"
        android:id="@+id/txtPhone"
        android:text="+3800000000000"
        android:textSize="20dp"
        android:layout_alignBottom="@+id/personPhoto"
        android:layout_alignParentEnd="true"
        android:layout_margin="10dp"
        android:focusable="false"
        android:clickable="false"/>

</RelativeLayout>
 
Важливо встановити  у віджетах пункту списку властивості android:focusable="false" та android:clickable="false". Це для того, щоб натиснення на пункт оброблялися правильно, інакше фокус будуть перехоплювати дані елементи і замість пункту меню, натискатимуться відповідні текстові елементи або ж зображення і обробка події натиснення пункту може не відбуватися.

Клас Person.java 

Наш список братиме дані із відповідної моделі особи – класу Person, що містить фото, ім’я і номер телефону.

package ua.kyiv.volodimirg.mylistview;

public class Person {
    private int photo;
    private String name;
    private String number;

    public Person(int photo, String name, String number) {
        this.photo = photo;
        this.name = name;
        this.number = number;
    }

    public int getPhoto() {
        return photo;
    }

    public String getNumber() {
        return number;
    }

    public String getName() {
        return name;
    }
}


Основна активність ListActivit.java

Для початку необхідне поле, що містило б масив персон:

private List persons= new ArrayList();

в середині onCreate() заповнюємо наш масив:
 
persons.add(new Person(R.drawable.boy, "Ігор Манко", "+380115448966"));
persons.add(new Person(R.drawable.smile, "Галя", "+380115448966"));
persons.add(new Person(R.drawable.smile2, "Назар Аргов", "+380115448966"));
persons.add(new Person(R.drawable.boy, "Ігор Зем", "+380115448966"));
persons.add(new Person(R.drawable.face, "Марія Нелько", "+380115448966"));
persons.add(new Person(R.drawable.angry, "Ліна", "+380115448966"));
persons.add(new Person(R.drawable.smile2, "Володимир Богданович Найко", "+380115448966"));

Для функціонування ListView нам потрібен відповідний клас адаптер. Створення адаптера переважно полягає у розширенні певного класу наприклад ArrayAdapter та перевизначенні деяких методів. Для нас достатньо перевизначити метод getView().

private class MyListAdapter extends ArrayAdapter {
    public MyListAdapter(){
        super(ListActivity.this, R.layout.item_list, persons);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View itemView=convertView;
        //зв'язуємо пункт з нашим макетом
        if (itemView==null){
            itemView =getLayoutInflater().inflate(R.layout.item_list, parent,false);
         }
         //заповнюємо пункт інформацією відповідно до позиції
         Person currentPerson= persons.get(position);
         ImageView photo= (ImageView)itemView.findViewById(R.id.personPhoto);
         photo.setImageResource(currentPerson.getPhoto());
         TextView txtName=(TextView)  itemView.findViewById(R.id.txtName);
         txtName.setText(currentPerson.getName());
         TextView txtPhone=(TextView)  itemView.findViewById(R.id.txtPhone);
         txtPhone.setText(currentPerson.getNumber());
        

        return itemView;
    }
}

Адаптер буде у нас внутрішнім (inner) класом.
В головній активності пишемо в методі onCreate :

    ArrayAdapter customAdapter = new MyListAdapter();
    ListView list= (ListView) findViewById(R.id.phonelistView);
    list.setAdapter(customAdapter);

Залишається обробити натиснення на пункт списку:

ListView list2= (ListView)findViewById(R.id.phonelistView);
list2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
     @Override
     public void onItemClick(AdapterView parent, View viewClicked, int position, long id) {
         Person clickedPerson = persons.get(position);
         String msg= "Ви вибрали "+ clickedPerson.getName();
         Context context = getApplicationContext();
         Toast.makeText(context, msg,Toast. LENGTH_SHORT).show();
     }
 });

Повний текст ListActivity.java 

package ua.kyiv.volodimirg.mylistview;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class ListActivity extends AppCompatActivity {
    private List persons= new ArrayList();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);

        populatePersons();
        populateListView();
        onClickProcessing();


    }

    private void populateListView() {
        //створюємо адаптер
        ArrayAdapter customAdapter = new MyListAdapter();
        //зв'язуємо список з адаптером
        ListView list= (ListView) findViewById(R.id.phonelistView);
        list.setAdapter(customAdapter);
    }

    /**
     * Створюємо осіб і додаємо у ArrayList
     */
    private void populatePersons(){

        persons.add(new Person(R.drawable.boy, "Ігор Манко", "+380115448966"));
        persons.add(new Person(R.drawable.smile, "Галя", "+380115448966"));
        persons.add(new Person(R.drawable.smile2, "Назар Аргов", "+380115448966"));
        persons.add(new Person(R.drawable.boy, "Ігор Зем", "+380115448966"));
        persons.add(new Person(R.drawable.face, "Марія Нелько", "+380115448966"));
        persons.add(new Person(R.drawable.angry, "Ліна", "+380115448966"));
        persons.add(new Person(R.drawable.smile2, "Володимир Богданович Найко", "+380115448966"));
    }

    /**
     * обробляємо натиснення на пункт списку
     */
    private void onClickProcessing(){
        ListView list2= (ListView)findViewById(R.id.phonelistView);
       list2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View viewClicked, int position, long id) {
                Person clickedPerson = persons.get(position);
                String msg= "Ви вибрали "+ clickedPerson.getName();
                Context context = getApplicationContext();
                Toast.makeText(context, msg,Toast. LENGTH_SHORT).show();
            }
        });
    }
    private class MyListAdapter extends ArrayAdapter {
        public MyListAdapter(){
            super(ListActivity.this, R.layout.item_list, persons);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View itemView=convertView;
            //зв'язуємо пункт з нашим макетом
            if (itemView==null){
                itemView =getLayoutInflater().inflate(R.layout.item_list, parent,false);
             }
             //заповнюємо пункт інформацією відповідно до позиції
             Person currentPerson= persons.get(position);
             ImageView photo= (ImageView)itemView.findViewById(R.id.personPhoto);
             photo.setImageResource(currentPerson.getPhoto());
             TextView txtName=(TextView)  itemView.findViewById(R.id.txtName);
             txtName.setText(currentPerson.getName());
             TextView txtPhone=(TextView)  itemView.findViewById(R.id.txtPhone);
             txtPhone.setText(currentPerson.getNumber());
           



            return itemView;
        }
    }
}

Джерела: ListView with Images and Text: Android Programming

Немає коментарів:

Дописати коментар