Простий приклад сітки Android за допомогою RecyclerView з GridLayoutManager (як і старий GridView)


227

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

  • кілька комірок в ряд
  • поодинокий вигляд у кожній комірці
  • відповідає на події клацання

Відповіді:


556

Коротка відповідь

Для тих, хто вже знайомий із створенням RecyclerViewсписку , хороша новина полягає в тому, що створення сітки в основному те саме. Ви просто використовуєте GridLayoutManagerзамість, LinearLayoutManagerколи ви налаштовуєте RecyclerView.

recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));

Якщо вам потрібна додаткова допомога, то перегляньте наступний приклад.

Повний приклад

Далі наведено мінімальний приклад, який буде виглядати як на зображенні нижче.

введіть тут опис зображення

Почніть з порожньої діяльності. Ви будете виконувати такі завдання, щоб додати RecyclerViewсітку. Все, що вам потрібно зробити, - скопіювати та вставити код у кожен розділ. Пізніше ви можете налаштувати його під свої потреби.

  • Додайте залежності до gradle
  • Додайте файли макета xml для активності та для комірки сітки
  • Зробіть адаптер RecyclerView
  • Ініціалізуйте RecyclerView у своїй діяльності

Оновіть залежності Gradle

Переконайтеся, що у вашому додатку є такі залежності gradle.build:

compile 'com.android.support:appcompat-v7:27.1.1'
compile 'com.android.support:recyclerview-v7:27.1.1'

Ви можете оновити номери версій до тих, що є найбільш актуальними .

Створіть макет діяльності

Додайте RecyclerViewдо вашого формату XML.

activity_main.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">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rvNumbers"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

Створіть макет комірок сітки

Кожна комірка в нашій RecyclerViewсітці буде мати лише одну TextView. Створіть новий файл ресурсу макета.

recilerview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:padding="5dp"
    android:layout_width="50dp"
    android:layout_height="50dp">

        <TextView
            android:id="@+id/info_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:background="@color/colorAccent"/>

</LinearLayout>

Створіть адаптер

RecyclerViewПотрібен адаптер для заповнення уявлень в кожному осередку з вашими даними. Створіть новий файл Java.

MyRecyclerViewAdapter.java

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {

    private String[] mData;
    private LayoutInflater mInflater;
    private ItemClickListener mClickListener;

    // data is passed into the constructor
    MyRecyclerViewAdapter(Context context, String[] data) {
        this.mInflater = LayoutInflater.from(context);
        this.mData = data;
    }

    // inflates the cell layout from xml when needed
    @Override
    @NonNull 
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
        return new ViewHolder(view);
    }

    // binds the data to the TextView in each cell
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.myTextView.setText(mData[position]);
    }

    // total number of cells
    @Override
    public int getItemCount() {
        return mData.length;
    }


    // stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView myTextView;

        ViewHolder(View itemView) {
            super(itemView);
            myTextView = itemView.findViewById(R.id.info_text);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
        }
    }

    // convenience method for getting data at click position
    String getItem(int id) {
        return mData[id];
    }

    // allows clicks events to be caught
    void setClickListener(ItemClickListener itemClickListener) {
        this.mClickListener = itemClickListener;
    }

    // parent activity will implement this method to respond to click events
    public interface ItemClickListener {
        void onItemClick(View view, int position);
    }
}

Примітки

  • Хоча це і не є строго необхідним, я включив функціональність для прослуховування подій клацання по клітинках. Це було по-старому GridViewі є загальною потребою. Ви можете видалити цей код, якщо він вам не потрібен.

Ініціалізуйте RecyclerView у діяльності

Додайте наступний код до своєї основної діяльності.

MainActivity.java

public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {

    MyRecyclerViewAdapter adapter;

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

        // data to populate the RecyclerView with
        String[] data = {"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", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"};

        // set up the RecyclerView
        RecyclerView recyclerView = findViewById(R.id.rvNumbers);
        int numberOfColumns = 6;
        recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
        adapter = new MyRecyclerViewAdapter(this, data);
        adapter.setClickListener(this);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onItemClick(View view, int position) {
        Log.i("TAG", "You clicked number " + adapter.getItem(position) + ", which is at cell position " + position);
    }
}

Примітки

  • Зауважте, що діяльність реалізує те, ItemClickListenerщо ми визначили в нашому адаптері. Це дозволяє нам обробляти події кліку клітинки в onItemClick.

Готово

Це воно. Ви повинні мати можливість запустити свій проект зараз і отримати щось подібне до зображення вгорі.

Продовжувати

Закруглені кути

Автоматичні підгонки стовпців

Подальше навчання


2
@ MarianPaździoch, Так, я просто зробив це як мінімальний приклад. Однозначно можна було б використати деякі роботи по благоустрою. Спробую оновити цю відповідь деякий час у майбутньому.
Сурагч

1
Я увійшов, щоб зазначити, що такі люди, як ви, підтримували цей портал живим і брикаючи. велике спасибі
VarunJoshi129

1
@androiddeveloper, елементи сітки викладаються зліва направо, зверху вниз. Прокрутка вертикальна, коли на екрані більше елементів, ніж може вміститися.
Сурагч

13
Майбутні читачі, дозвольте мені заощадити трохи часу, головнеrecyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
дака

1
@daka, хороший момент. Я відредагував свою відповідь, щоб включити це на початку.
Сурагч

7

Хоча я , як і оцінити Suragch відповідь «S , я хотів би залишити записку , бо я виявив , що кодування адаптера ( MyRecyclerViewAdapter) , щоб визначити і виставити метод Прослуховувач onItemClickне кращий спосіб зробити це, з - за не використовуючи клас инкапсуляцию правильно. Тож моя пропозиція - дозволити Адаптеру керувати операціями слухання виключно (це його призначення!) Та відокремити ті дії, які використовує адаптер ( MainActivity). Ось так я б встановив клас Адаптер:

MyRecyclerViewAdapter.java

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {

    private String[] mData = new String[0];
    private LayoutInflater mInflater;

    // Data is passed into the constructor
    public MyRecyclerViewAdapter(Context context, String[] data) {
        this.mInflater = LayoutInflater.from(context);
        this.mData = data;
    }

    // Inflates the cell layout from xml when needed
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    // Binds the data to the textview in each cell
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String animal = mData[position];
        holder.myTextView.setText(animal);
    }

    // Total number of cells
    @Override
    public int getItemCount() {
        return mData.length;
    }

    // Stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public TextView myTextView;

        public ViewHolder(View itemView) {
            super(itemView);
            myTextView = (TextView) itemView.findViewById(R.id.info_text);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            onItemClick(view, getAdapterPosition());
        }
    }

    // Convenience method for getting data at click position
    public String getItem(int id) {
        return mData[id];
    }

    // Method that executes your code for the action received
    public void onItemClick(View view, int position) {
        Log.i("TAG", "You clicked number " + getItem(position).toString() + ", which is at cell position " + position);
    }
}

Зверніть увагу на onItemClickметод, визначений зараз, у MyRecyclerViewAdapterтому місці, де ви хочете кодувати свої завдання для отриманої події / дії.

Для завершення цієї трансформації слід зробити лише невелику зміну: Діяльність більше не потрібно впроваджувати MyRecyclerViewAdapter.ItemClickListener, тому що тепер це зроблено повністю Адаптером . Тоді це буде остаточна модифікація:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    MyRecyclerViewAdapter adapter;

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

        // data to populate the RecyclerView with
        String[] data = {"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", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"};

        // set up the RecyclerView
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rvNumbers);
        int numberOfColumns = 6;
        recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
        adapter = new MyRecyclerViewAdapter(this, data);
        adapter.setClickListener(this);
        recyclerView.setAdapter(adapter);
    }
}

3
Що робити, якщо діяльності потрібно слухати події клацання? наприклад, передача даних ведучому, певна логіка на основі клацання предмета, відстеження тощо.
Ахмад Фадлі

Я погоджуюся, що адаптер повинен обробляти події клацання, оскільки в ньому є елементи з даними. @AhmadFadli, якщо вам потрібно виконати певну роботу в хості адаптера (фрагмент або активність), вам слід створити інтерфейс зворотного дзвінка з необхідними методами. Ваш хост реалізує цей інтерфейс. А потім ви передаєте екземпляр свого хоста в конструктор Adapter. Маючи екземпляр хоста, ви можете викликати його методи, коли вам потрібно з вашого адаптера. І вашому хосту ми отримуємо дзвінки зворотного дзвінка. Це часто використовується, коли вам потрібно працювати з ActionMode. Коли ви довго натискаєте кнопку, щоб вибрати елементи та використовувати кнопки ActionBar.
Кирило Кармазін

Я не погоджуюсь і вважаю, що події натискання повинні бути оброблені на хостингу Activity. Тому що тільки це кликни слухач може дізнатися про Activityпоглядах і інших Fragments, Activitiesі т.д. Адаптер може відправляти подія натискання на верхній рівень. Він повинен мати інтерфейс ItemClickListener з такою кількістю подій, як може видаватися кількість поглядів адаптера. Це рішення було написано ще раніше: stackoverflow.com/a/40563598/2914140 .
CoolMind

4

Вам доведеться встановити ваш макет-менеджер рециркулятора на режим Gridlayout, для цього просто змініть свій код, коли хочете встановити RecyclerView LayoutManager:

Примітка: замініть свій колонку, яку ви хочете, на ### HELP ###

   recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),###HELP###));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.