我用Android的RecyclerView做过几次物品列表,但这是一个相当复杂的过程。浏览众多在线教程中的一个作品(这个,这个,这个都很好),但我正在寻找一个简单的示例,我可以复制和粘贴来快速启动和运行。只需要以下特性:

垂直布局 每行都有一个单一的TextView 响应点击事件

因为这个愿望我已经许过好几次了,所以我最终决定把答案写在下面,供我和你们将来参考。


当前回答

实现androidx.recyclerview: recyclerview:… 建议更新到下面的androidx库:

https://developer.android.com/jetpack/androidx/releases/recyclerview

布局文件Widget XML标签必须更新为: androidx.recyclerview.widget.RecyclerView

其他回答

依赖关系

compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:multidex:1.0.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.android.support:support-v4:25.3.1'
compile 'com.lguipeng.bubbleview:library:1.0.0'
compile 'com.larswerkman:HoloColorPicker:1.5'
compile 'com.mcxiaoke.volley:library-aar:1.0.0'

一个类为点击项目

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
    private OnItemClickListener mListener;

    public interface OnItemClickListener {
        public void onItemClick(View view, int position);
    }

    GestureDetector mGestureDetector;

    public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
        mListener = listener;
        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
        View childView = view.findChildViewUnder(e.getX(), e.getY());
        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(childView, view.getChildPosition(childView));
            return true;
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }


}

第二个类RecyclerView

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;

public class SLByTopics extends Fragment {


    public static ArrayList<MByTopics> byTopicsMainArrayList=new ArrayList<>();


    TabRefreshReceiver tabRefreshReceiver;
    RecyclerView recyclerView;
    SAdpByTopics sAdpByTopics;
    public ArrayList<MByTopics> mByTopicsArrayList=new ArrayList<>();
    ProgressDialog progressDialog;

    public SLByTopics(){
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.sl_fragment_by_topics, container, false);

        progressDialog = new ProgressDialog(getActivity());
        if (IsOnline.isNetworkAvailable(getActivity())) {
            getCategoryTree();
        } else{
            IsOnline.showNoInterNetMessage(getActivity());
        }
        tabRefreshReceiver = new TabRefreshReceiver();
       LocalBroadcastManager.getInstance(getContext()).registerReceiver(tabRefreshReceiver, new IntentFilter("BY_TOPICS"));

        setUpView(view);
        return view;
    }

    private void setUpView(View view) {

        recyclerView=(RecyclerView)view.findViewById(R.id.by_topics_list_recyclerView);
        LinearLayoutManager linearLayoutManager=new LinearLayoutManager(getActivity());
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
    }

    @Override
    public void onResume() {
        super.onResume();

        recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
            @Override
            public void onItemClick(View view, final int position) {

                if (mByTopicsArrayList.get(position).getChild().size()>0){
                    Intent intent = new Intent(getActivity(), SByTopicCategory.class);
                    intent.putExtra("selectedCategoryName",mByTopicsArrayList.get(position).getCatname());
                    intent.putExtra("jsonData",mByTopicsArrayList.get(position).getMainTopicJson());
                    startActivity(intent);
                    getActivity().overridePendingTransition(R.anim.activity_in, R.anim.activity_out);
                }else {
                    Intent intent = new Intent(getActivity(), SByCategoryQuestionList.class);
                    intent.putExtra("selectedSubCategoryName",mByTopicsArrayList.get(position).getCatname());
                    intent.putExtra("catID",mByTopicsArrayList.get(position).getId());
                    startActivity(intent);
                    getActivity().overridePendingTransition(R.anim.activity_in, R.anim.activity_out);
                }
            }
        }));

    }

    private class TabRefreshReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            try {
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                ft.detach(SLByTopics.this).attach(SLByTopics.this).commit();
                LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(tabRefreshReceiver);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    private void getCategoryTree() {
        progressDialog.setMessage("Please Wait...");
        progressDialog.setCancelable(false);
        progressDialog.show();

        StringRequest stringRequest = new StringRequest(Request.Method.POST, Const.HOSTNAME + Const.STUDENT_GET_CATEGORY_TREE,
                new Response.Listener<String>() {
                    @SuppressLint("LongLogTag")
                    @Override
                    public void onResponse(String response) {
                        try {
                            JSONObject object = new JSONObject(response);
                            String status = object.getString("status");
                            int i = Integer.parseInt(status);

                            switch (i) {

                                case 0:
                                    progressDialog.dismiss();
//                                    Toast.makeText(getActivity(), "getCategorySuccess", Toast.LENGTH_SHORT).show();
                                    Log.e("getCategoryTree Response", "getCategoryTree Response : " + response);

                                    try {    
                                        byTopicsMainArrayList.clear();
                                        JSONArray info = object.getJSONArray("info");
                                        if (info.length() > 0) {
                                            for (i = 0; i < info.length(); i++) {
                                                JSONObject data = info.getJSONObject(i);
                                                MByTopics mByTopics = new MByTopics();
                                                mByTopics.setId(data.getString("id"));
                                                mByTopics.setCatname(data.getString("catname"));
                                                mByTopics.setMainTopicJson(data.toString());

                                                JSONArray topicChildren = data.getJSONArray("children");
                                                ArrayList<SMByTopicCategory> byChildrenArrayList = new ArrayList<>();

                                                for (int j = 0; j < topicChildren.length(); j++) {
                                                    JSONObject topicChildrenData = topicChildren.getJSONObject(j);
                                                    SMByTopicCategory smByTopicCategory = new SMByTopicCategory();
                                                    smByTopicCategory.setId(topicChildrenData.getString("id"));
                                                    smByTopicCategory.setCatname(topicChildrenData.getString("catname"));
                                                    smByTopicCategory.setChildTopicJson(topicChildrenData.toString());

                                                    JSONArray topicChildrenQuestion = topicChildrenData.getJSONArray("children");
                                                    ArrayList<SMByTopicSubCategory> byChildrenSubArrayList = new ArrayList<>();

                                                    for (int k = 0; k < topicChildrenQuestion.length(); k++) {
                                                        JSONObject topicChildrenSubData = topicChildrenQuestion.getJSONObject(k);
                                                        SMByTopicSubCategory smByTopicSubCategory = new SMByTopicSubCategory();
                                                        smByTopicSubCategory.setId(topicChildrenSubData.getString("id"));
                                                        smByTopicSubCategory.setCatname(topicChildrenSubData.getString("catname"));
                                                        smByTopicSubCategory.setChildSubTopicJson(topicChildrenSubData.toString());

                                                        byChildrenSubArrayList.add(smByTopicSubCategory);
                                                    }

                                                    smByTopicCategory.setQuestions(byChildrenSubArrayList);

                                                    byChildrenArrayList.add(smByTopicCategory);
                                                }
                                                mByTopics.setChild(byChildrenArrayList);
                                                byTopicsMainArrayList.add(mByTopics);
                                            }


                                            mByTopicsArrayList.clear();
                                            mByTopicsArrayList=byTopicsMainArrayList;
                                            sAdpByTopics=new SAdpByTopics(mByTopicsArrayList,getActivity());
                                            recyclerView.setAdapter(sAdpByTopics);
                                            sAdpByTopics.notifyDataSetChanged();

                                        }

                                    }catch (Exception e){
                                        e.printStackTrace();
                                    }
                                    break;

                                default:
                                    progressDialog.dismiss();
//                                    Toast.makeText(getActivity(), "getCategoryError : " + response, Toast.LENGTH_SHORT).show();
                                    Log.e("getCategoryTree Not Response", "getCategoryTree Uploading Not Response : " + response);
                            }

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        progressDialog.dismiss();
                        Log.e("getCategoryTree Error :","getCategoryTree Error :"+error.getMessage());
//                        Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_LONG).show();
                    }
                }){

        };/* {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {

                Map<String, String> map = new HashMap<String, String>();
//                map.put("uid", String.valueOf(ConfigManager.getUserId()));
                return map;
            }
        };*/

        stringRequest.setRetryPolicy(new DefaultRetryPolicy(
                0,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

        RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
        requestQueue.add(stringRequest);
    }
}

适配器类回收项目

import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;

public class SAdpByTopics extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        ArrayList<MByTopics> topicsArrayList=new ArrayList<>();
        Activity activity;

     public SAdpByTopics(ArrayList<MByTopics> topicsArrayList,Activity activity){
        this.topicsArrayList=topicsArrayList;
        this.activity=activity;
     }

     @Override
     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemeView= LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_by_topic_list,parent,false);
        RecyclerView.ViewHolder holder=new Holder(itemeView);
        holder.setIsRecyclable(false);
        return holder;
     }

     @Override
     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
         final Holder classHolder = (Holder) holder;
         try{
             classHolder.txt_topic_name.setText(topicsArrayList.get(position).getCatname());
         }catch (Exception e){
             e.printStackTrace();
         }
     }

     @Override
     public int getItemCount() {
        return topicsArrayList.size();
     }


class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
    TextView txt_topic_name;

    public Holder(View itemView) {
        super(itemView);
        txt_topic_name = (TextView) itemView.findViewById(R.id.txt_topic_name);
    }

    @Override
    public void onClick(View v) {

    }
}
}

模块类

public class MByTopics {

    String id;
    String topicName;
    String catname;
    String MainTopicJson;
    ArrayList<SMByTopicCategory> child;
    ArrayList<SMByTopicSubCategory> questions;

    public void setId(String id){
        this.id=id;
    }
    public String getId(){
        return  id;
    }

    public void setCatname(String catname) {
        this.catname = catname;
    }

    public String getCatname() {
        return catname;
    }

    public void setTopicName(String topicName) {
        this.topicName = topicName;
    }
    public String getTopicName() {
        return topicName;
    }

    public void setChild(ArrayList<SMByTopicCategory> child) {
        this.child = child;
    }

    public String getMainTopicJson() {
        return MainTopicJson;
    }

    public void setMainTopicJson(String mainTopicJson) {
        MainTopicJson = mainTopicJson;
    }

    public ArrayList<SMByTopicCategory> getChild() {
        return child;
    }

    public void setQuestions(ArrayList<SMByTopicSubCategory> questions) {
        this.questions = questions;
    }

    public ArrayList<SMByTopicSubCategory> getQuestions() {
        return questions;
    }

    public ArrayList<MByTopics> getByTopicList() {
        ArrayList<MByTopics> mByTopicsArrayList = new ArrayList<>();

        for (int i=0;i<11;i++){
            MByTopics mQuestionBankCategory=new MByTopics();

            if (i==1 || i== 5|| i==9){
                mQuestionBankCategory.setTopicName("Microeconomics");
            }else  if (i==2 || i== 10|| i==6) {
                mQuestionBankCategory.setTopicName("Macroeconomics");
            }else {
                mQuestionBankCategory.setTopicName("Current Isssues");
            }

            mByTopicsArrayList.add(mQuestionBankCategory);
        }

        return mByTopicsArrayList;
    }

}

基于不同的资源,我使用简单库创建了RecyclerView的简单实现。

在build.gradle中添加这一行

implementation 'com.hereshem.lib:awesomelib:2.0.1'

通过在activity_main.xml中添加MyRecyclerView来创建一个RecyclerView

<com.hereshem.lib.recycler.MyRecyclerView
        android:id="@+id/recycler"
        app:layoutManager="LinearLayoutManager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

现在在MainActivity中,通过传递需要绑定的类的名称来创建一个ViewHolder

public static class EVHolder extends MyViewHolder<Events> {
    TextView date, title, summary;
    public EVHolder(View v) {
        super(v);
        date = v.findViewById(R.id.date);
        title = v.findViewById(R.id.title);
        summary = v.findViewById(R.id.summary);
    }
    @Override
    public void bindView(Events c) {
        date.setText(c.date);
        title.setText(c.title);
        summary.setText(c.summary);
    }
}

通过在适配器中传递项目、类和布局来创建Items列表变量和适配器,行数很少

List<Events> items = new ArrayList<>();
MyRecyclerView recycler = findViewById(R.id.recycler);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, items, EVHolder.class, R.layout.row_event);
recycler.setAdapter(adapter);

ClickListener可以用以下几行添加

recycler.setOnItemClickListener(new MyRecyclerView.OnItemClickListener() {
    @Override
    public void onItemClick(int position) {
        Toast.makeText(MainActivity.this, "Recycler Item Clicked " + position, Toast.LENGTH_SHORT).show();
    }
});

都搞定了。

更多示例和实现可以在这里找到。 希望这能有所帮助!!

首先添加recyclerview库。

implementation 'androidx.recyclerview:recyclerview:1.1.0'

创建模型类。

     public class UserModel implements Serializable {

    private String userName;


    public UserModel(String userName) {
        this.userName = userName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
   }

创建适配器类。

public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.UsersAdapterVh> implements Filterable {

    private List<UserModel> userModelList;
    private List<UserModel> getUserModelListFiltered;
    private Context context;
    private SelectedUser selectedUser;

    public UsersAdapter(List<UserModel> userModelList,SelectedUser selectedUser) {
        this.userModelList = userModelList;
        this.getUserModelListFiltered = userModelList;
        this.selectedUser = selectedUser;
    }

    @NonNull
    @Override
    public UsersAdapter.UsersAdapterVh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        context = parent.getContext();

        return new UsersAdapterVh(LayoutInflater.from(context).inflate(R.layout.row_users,null));
    }

    @Override
    public void onBindViewHolder(@NonNull UsersAdapter.UsersAdapterVh holder, int position) {

        UserModel userModel = userModelList.get(position);

        String username = userModel.getUserName();
        String prefix = userModel.getUserName().substring(0,1);

        holder.tvUsername.setText(username);
        holder.tvPrefix.setText(prefix);

    }

    @Override
    public int getItemCount() {
        return userModelList.size();
    }

    @Override
    public Filter getFilter() {

        Filter filter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                FilterResults filterResults = new FilterResults();

                if(charSequence == null | charSequence.length() == 0){
                    filterResults.count = getUserModelListFiltered.size();
                    filterResults.values = getUserModelListFiltered;

                }else{
                    String searchChr = charSequence.toString().toLowerCase();

                    List<UserModel> resultData = new ArrayList<>();

                    for(UserModel userModel: getUserModelListFiltered){
                        if(userModel.getUserName().toLowerCase().contains(searchChr)){
                            resultData.add(userModel);
                        }
                    }
                    filterResults.count = resultData.size();
                    filterResults.values = resultData;

                }

                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {

                userModelList = (List<UserModel>) filterResults.values;
                notifyDataSetChanged();

            }
        };
        return filter;
    }


    public interface SelectedUser{

        void selectedUser(UserModel userModel);

    }

    public class UsersAdapterVh extends RecyclerView.ViewHolder {

        TextView tvPrefix;
        TextView tvUsername;
        ImageView imIcon;
        public UsersAdapterVh(@NonNull View itemView) {
            super(itemView);
            tvPrefix = itemView.findViewById(R.id.prefix);
            tvUsername = itemView.findViewById(R.id.username);
            imIcon = itemView.findViewById(R.id.imageView);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    selectedUser.selectedUser(userModelList.get(getAdapterPosition()));
                }
            });


        }
    }
}

创建布局row_uses.xml

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:padding="10dp"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:layout_width="50dp"
            android:background="@drawable/users_bg"
            android:layout_height="50dp">
            <TextView
                android:id="@+id/prefix"
                android:layout_width="wrap_content"
                android:textSize="16sp"
                android:textColor="@color/headerColor"
                android:text="T"
                android:layout_centerInParent="true"
                android:layout_height="wrap_content"/>

        </RelativeLayout>
        <TextView
            android:id="@+id/username"
            android:layout_width="wrap_content"
            android:textSize="16sp"
            android:textColor="@color/headerColor"
            android:text="username"
            android:layout_marginStart="90dp"
            android:layout_centerVertical="true"
            android:layout_height="wrap_content"/>
        <ImageView
            android:layout_width="wrap_content"
            android:id="@+id/imageView"
            android:layout_margin="10dp"
            android:layout_alignParentEnd="true"
            android:src="@drawable/ic_navigate_next_black_24dp"
            android:layout_height="wrap_content"/>
    </RelativeLayout>

</LinearLayout>

查找recyclerview并填充数据。

Toolbar toolbar;
RecyclerView recyclerView;

List<UserModel> userModelList = new ArrayList<>();

String[] names = {"Richard","Alice","Hannah","David"};

UsersAdapter usersAdapter;


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

    recyclerView = findViewById(R.id.recyclerview);
    toolbar = findViewById(R.id.toolbar);

    this.setSupportActionBar(toolbar);
    this.getSupportActionBar().setTitle("");

    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));

    for(String s:names){
        UserModel userModel = new UserModel(s);

        userModelList.add(userModel);
    }

    usersAdapter = new UsersAdapter(userModelList,this);

    recyclerView.setAdapter(usersAdapter);

}

在这里找到完整的教程和源代码:

Android RecyclerView

下面是一个类似下图的最小示例。

从一个空活动开始。您将执行以下任务来添加RecyclerView。您所需要做的就是复制并粘贴每个部分中的代码。稍后,您可以自定义它以满足您的需求。

向gradle添加依赖项 为活动和RecyclerView行添加xml布局文件 制作RecyclerView适配器 初始化活动中的RecyclerView

更新Gradle依赖项

确保以下依赖项在你的应用程序gradle中。构建文件:

implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'

您可以将版本号更新为最新的版本号。如果你还在使用Android Studio 2.x,请使用编译而不是实现。

创建活动布局

将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/rvAnimals"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

创建行布局

我们的RecyclerView中的每一行都只会有一个单一的TextView。创建一个新的布局资源文件。

recyclerview_row.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="wrap_content"
    android:orientation="horizontal"
    android:padding="10dp">

    <TextView
        android:id="@+id/tvAnimalName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"/>

</LinearLayout>

创建适配器

RecyclerView需要一个适配器来用您的数据填充每行中的视图。创建一个新的java文件。

MyRecyclerViewAdapter.java

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

    private List<String> mData;
    private LayoutInflater mInflater;
    private ItemClickListener mClickListener;

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

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

    // binds the data to the TextView in each row
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String animal = mData.get(position);
        holder.myTextView.setText(animal);
    }

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


    // 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.tvAnimalName);
            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.get(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);
    }
}

笔记

虽然不是严格必要的,但我包含了监听行上的单击事件的功能。这在旧的listview中是可用的,是一种常见的需求。如果不需要,可以删除此代码。

在Activity中初始化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
        ArrayList<String> animalNames = new ArrayList<>();
        animalNames.add("Horse");
        animalNames.add("Cow");
        animalNames.add("Camel");
        animalNames.add("Sheep");
        animalNames.add("Goat");

        // set up the RecyclerView
        RecyclerView recyclerView = findViewById(R.id.rvAnimals);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        adapter = new MyRecyclerViewAdapter(this, animalNames);
        adapter.setClickListener(this);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onItemClick(View view, int position) {
        Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
    }
}

笔记

注意,该活动实现了我们在适配器中定义的ItemClickListener。这允许我们在onItemClick中处理行单击事件。

完成了

就是这样。您现在应该能够运行您的项目,并获得与顶部图像类似的内容。

发生了

在行之间添加分隔符

你可以像这样加一个简单的分隔符

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
    layoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);

如果你想要一些更复杂的东西,请参阅以下答案:

如何在RecyclerView中添加项目之间的分隔符和空格? 如何在线性布局中缩进分隔符(即,仅在ItemDecoration中添加填充,边距或插入)

在单击时更改行颜色

查看这个答案,了解如何更改背景颜色,并在单击一行时添加涟漪效应。

更新的行

有关如何添加、删除和更新行,请参阅此回答。

进一步的阅读

CodePath 视频教程 Android RecyclerView示例(stacktips教程) RecyclerView在Android:教程

实现androidx.recyclerview: recyclerview:… 建议更新到下面的androidx库:

https://developer.android.com/jetpack/androidx/releases/recyclerview

布局文件Widget XML标签必须更新为: androidx.recyclerview.widget.RecyclerView