Ví dụ lưới Android đơn giản sử dụng RecyclerView với GridLayoutManager (như GridView cũ)


227

Tôi biết rằng RecyclerViewđã thay thế các chức năng của cũ ListViewGridView. Tôi đang tìm kiếm một ví dụ rất cơ bản cho thấy thiết lập lưới tối thiểu bằng cách sử dụng RecyclerView. Tôi không tìm kiếm giải thích phong cách hướng dẫn dài, chỉ là một ví dụ tối thiểu. Tôi tưởng tượng lưới đơn giản nhất bắt chước GridView cũ sẽ bao gồm các tính năng sau:

  • nhiều ô mỗi hàng
  • Chế độ xem đơn trong mỗi ô
  • phản ứng với các sự kiện nhấp

Câu trả lời:


556

Câu trả lời ngắn

Đối với những người đã quen thuộc với việc thiết lập RecyclerViewmột danh sách , tin tốt là việc tạo lưới phần lớn giống nhau. Bạn chỉ cần sử dụng GridLayoutManagerthay vì một LinearLayoutManagerkhi bạn thiết RecyclerViewlập.

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

Nếu bạn cần trợ giúp nhiều hơn thế, hãy xem ví dụ sau.

Ví dụ đầy đủ

Sau đây là một ví dụ tối thiểu sẽ trông giống như hình ảnh dưới đây.

nhập mô tả hình ảnh ở đây

Bắt đầu với một hoạt động trống rỗng. Bạn sẽ thực hiện các tác vụ sau để thêm RecyclerViewlưới. Tất cả bạn cần làm là sao chép và dán mã trong mỗi phần. Sau này bạn có thể tùy chỉnh nó để phù hợp với nhu cầu của bạn.

  • Thêm phụ thuộc vào lớp
  • Thêm tệp bố cục xml cho hoạt động và cho ô lưới
  • Tạo bộ điều hợp RecyclerView
  • Khởi tạo RecyclerView trong hoạt động của bạn

Cập nhật phụ thuộc Gradle

Đảm bảo các phụ thuộc sau có trong gradle.buildtệp ứng dụng của bạn :

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

Bạn có thể cập nhật số phiên bản thành bất cứ điều gì mới nhất .

Tạo bố cục hoạt động

Thêm vào RecyclerViewbố cục xml của bạn.

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>

Tạo bố trí ô lưới

Mỗi ô trong RecyclerViewlưới của chúng tôi sẽ chỉ có một TextView. Tạo một tệp tài nguyên bố cục mới.

recyclerview_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>

Tạo bộ chuyển đổi

Các RecyclerViewcần một bộ chuyển đổi để cư quan điểm trong mỗi tế bào với các dữ liệu của bạn. Tạo một tệp java mới.

MyRecyclerViewAd Module.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);
    }
}

Ghi chú

  • Mặc dù không thực sự cần thiết, tôi đã bao gồm chức năng nghe các sự kiện nhấp chuột trên các ô. Điều này đã có sẵn trong cái cũ GridViewvà là một nhu cầu phổ biến. Bạn có thể xóa mã này nếu bạn không cần nó.

Khởi tạo RecyclerView trong Activity

Thêm mã sau vào hoạt động chính của bạn.

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);
    }
}

Ghi chú

  • Lưu ý rằng hoạt động thực hiện ItemClickListenermà chúng tôi đã xác định trong bộ điều hợp của chúng tôi. Điều này cho phép chúng tôi xử lý các sự kiện nhấp chuột di động trong onItemClick.

Đã kết thúc

Đó là nó. Bạn sẽ có thể chạy dự án của bạn bây giờ và nhận được một cái gì đó tương tự như hình ảnh ở trên cùng.

Đang xảy ra

Góc tròn

Cột tự động lắp

Học cao hơn


2
@ MarianPaździoch, Vâng, tôi chỉ làm điều này như một ví dụ tối thiểu. Nó chắc chắn có thể sử dụng một số công việc làm đẹp. Tôi sẽ cố gắng cập nhật câu trả lời này một thời gian trong tương lai.
Suragch

1
Tôi đã đăng nhập chỉ để chỉ ra rằng những người như bạn đã giữ cho cổng thông tin này tồn tại và đá. Tôi đã bị mắc kẹt trong hai ngày trước khi thấy giải pháp này. cảm ơn rất nhiều
VarunJoshi129

1
@androiddeveloper, Các mục lưới được đặt từ trái sang phải, từ trên xuống dưới. Cuộn là dọc khi có nhiều mục hơn có thể vừa trên màn hình.
Suragch

13
Các độc giả tương lai, hãy để tôi giúp bạn tiết kiệm thời gian, điều quan trọng làrecyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
daka

1
@daka, điểm tốt. Tôi đã chỉnh sửa câu trả lời của tôi để bao gồm điều này vào đầu.
Suragch

7

Mặc dù tôi rất thích và đánh giá cao câu trả lời của Suragch , tôi muốn để lại một ghi chú vì tôi thấy rằng mã hóa Bộ điều hợp ( MyRecyclerViewAdapter) để xác định và hiển thị phương thức Listener onItemClickkhông phải là cách tốt nhất để thực hiện, do không sử dụng đóng gói lớp chính xác Vì vậy, đề nghị của tôi là để Bộ điều hợp chỉ xử lý các hoạt động Nghe (đó là mục đích của anh ấy!) Và tách chúng ra khỏi Hoạt động sử dụng Bộ điều hợp ( MainActivity). Vì vậy, đây là cách tôi sẽ thiết lập lớp Adaptor:

MyRecyclerViewAd Module.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);
    }
}

Xin lưu ý onItemClickphương thức hiện được xác định trong MyRecyclerViewAdapterđó là nơi bạn muốn mã hóa các tác vụ của mình cho sự kiện / hành động nhận được.

Chỉ có một thay đổi nhỏ được thực hiện để hoàn thành chuyển đổi này: Hoạt động không cần phải thực hiện MyRecyclerViewAdapter.ItemClickListenernữa, vì bây giờ điều đó được thực hiện hoàn toàn bởi Bộ điều hợp . Đây sẽ là sửa đổi cuối cùng:

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
Điều gì xảy ra nếu hoạt động không cần lắng nghe các sự kiện nhấp chuột? ví dụ: truyền dữ liệu cho người thuyết trình, thực hiện một số logic dựa trên mục được nhấp, theo dõi, v.v.
Ahmad Fadli

Tôi đồng ý rằng Bộ điều hợp nên xử lý các sự kiện nhấp chuột, vì nó có các mục có dữ liệu trong đó. @AhmadFadli nếu bạn cần thực hiện một số công việc trong máy chủ của bộ điều hợp (Đoạn hoặc Hoạt động), bạn nên tạo giao diện gọi lại với các phương thức bạn cần. Máy chủ của bạn thực hiện giao diện này. Và sau đó bạn chuyển một thể hiện của máy chủ lưu trữ của bạn vào hàm tạo của Adaptor. Có phiên bản của máy chủ lưu trữ, bạn có thể gọi phương thức của nó khi bạn cần từ Bộ điều hợp. Và máy chủ của bạn, chúng tôi nhận được cuộc gọi lại. Điều này thường được sử dụng khi bạn cần làm việc với ActionMode. Khi bạn nhấn vào để chọn các mục và sử dụng các nút ActionBar.
Kirill Karmazin

Tôi không đồng ý và nghĩ rằng các sự kiện nhấp chuột nên được xử lý trong lưu trữ Activity. Bởi vì chỉ có nó nhấp chuột nghe có thể biết về Activityquan điểm và khác Fragments, Activitiesvv Các bộ chuyển đổi chỉ có thể gửi vào các sự kiện để cấp trên. Nó nên có giao diện ItemClickListener với rất nhiều sự kiện, vì nhiều khung nhìn của bộ điều hợp có thể tạo ra. Giải pháp này đã được viết ngay cả trước đó: stackoverflow.com/a/40563598/2914140 .
CoolMind

4

Bạn phải đặt trình quản lý bố cục tái chế của mình thành Chế độ Gridlayout, Để làm điều này Chỉ cần thay đổi mã của bạn khi bạn muốn Đặt Trình quản lý bố cục RecyclerView của bạn:

Lưu ý: thay thế Số lượng cột của bạn mà bạn muốn bằng ### GIÚP ###

   recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),###HELP###));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.