简单的 Android RecyclerView 示例

Posted

技术标签:

【中文标题】简单的 Android RecyclerView 示例【英文标题】:Simple Android RecyclerView example 【发布时间】:2017-03-27 20:02:50 【问题描述】:

我用 androidRecyclerView 做了几次项目列表,但这是一个相当复杂的过程。浏览众多在线教程之一(this、this 和 this 很好),但我正在寻找一个可以复制和粘贴以快速启动和运行的简单示例。只需要以下功能:

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

因为这个愿望我已经好几次了,所以我最终决定做出下面的答案,以供我和你的参考。

【问题讨论】:

查看tutorial with source code 对于未来的小伙伴们,这里我写了一篇详细的文章,有视频教程handyopinion.com/… youtu.be/UZwiKdrm768:您可以查看此视频教程,因为它详细解释了 recyclerview: 检查这个要点.. github.com/AtifAbbAsi19/-RecyclerView 【参考方案1】:

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

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

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

更新 Gradle 依赖项

确保您的应用程序gradle.build 文件中有以下依赖项:

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

您可以将版本号更新为the most current。如果您仍在使用 Android Studio 2.x,请使用 compile 而不是 implementation

创建活动布局

RecyclerView 添加到您的 xml 布局中。

activity_main.xml

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rvAnimals"
        android:layout_
        android:layout_/>

</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_
    android:layout_
    android:orientation="horizontal"
    android:padding="10dp">

    <TextView
        android:id="@+id/tvAnimalName"
        android:layout_
        android:layout_
        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);
    

注意事项

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

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

如果您想要更复杂一点的东西,请查看以下答案:

How to add dividers and spaces between items in RecyclerView? How to indent the divider in a linear layout RecyclerView (ie, add padding, margin, or an inset only to the ItemDecoration)

点击时更改行颜色

请参阅this answer,了解如何更改背景颜色并在单击一行时添加波纹效果。

更新行

请参阅this answer,了解如何添加、删除和更新行。

进一步阅读

CodePath YouTube tutorials Android RecyclerView Example(堆栈提示教程) RecyclerView in Android: Tutorial

【讨论】:

非常好。这一直有效,直到我添加一个按钮并尝试设置它的点击监听器。有什么想法可能会干扰吗? @johnktejik,从您在此处提供的信息中很难确切知道您在说什么。这可能最好作为一个新问题提出。我的猜测是您的按钮正在处理动作事件,因此其他事情不会得到它。 抱歉.. 添加动物描述?例如:新 TextView 中的骆驼:是动物 // 新 TextVire 中的羊:是动物。我需要帮助..T_T @coder,不客气。是的,我已经将它用于水平输出,并且效果相同。 这个答案需要对 androidx 进行一些更新。【参考方案2】:

准备好使用 Kotlin 模板的最小回收器视图:

垂直布局 每行有一个 TextView 响应点击事件(Single 和 LongPress)

我知道这是一个旧线程,所以在这里回答。添加此答案以供将来参考:

在构建依赖中添加回收视图

  implementation 'com.google.android.material:material:1.4.0-alpha02'
    // RecyclerView
    implementation "androidx.recyclerview:recyclerview:1.2.0"

在布局中添加回收视图

   <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/wifiList"
            android:layout_
            android:layout_
           /> 

创建布局以显示列表项 (list_item.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_>
    <LinearLayout
        android:padding="5dp"
        android:layout_
        android:orientation="vertical"
        android:layout_>

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/ssid"
            android:text="@string/app_name"
            android:layout_
            android:textSize="17sp"
            android:layout_ />
        
    </LinearLayout>

</androidx.cardview.widget.CardView>

现在创建一个最小的适配器来保存数据,这里的代码是不言自明的

 class WifiAdapter(private val wifiList: ArrayList<ScanResult>) : RecyclerView.Adapter<WifiAdapter.ViewHolder>() 

     // holder class to hold reference
    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) 
        //get view reference
        var ssid: TextView = view.findViewById(R.id.ssid) as TextView
    

     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder 
         // create view holder to hold reference
         return ViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false))
     

    override fun onBindViewHolder(holder: ViewHolder, position: Int) 
        //set values
        holder.ssid.text =  wifiList[position].SSID
    

    override fun getItemCount(): Int 
        return wifiList.size
    
      // update your data
     fun updateData(scanResult: ArrayList<ScanResult>) 
         wifiList.clear()
         notifyDataSetChanged()
         wifiList.addAll(scanResult)
         notifyDataSetChanged()

     
 

添加此类以处理列表项上的单击和长按事件

import android.content.Context;
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener 

    public interface ClickListener 
        void onClick(View view, int position);

        void onLongClick(View view, RecyclerView recyclerView, int position);

    
    private GestureDetector gestureDetector;
    private ClickListener clickListener;

    public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) 
        this.clickListener = clickListener;
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() 
            @Override
            public boolean onSingleTapUp(MotionEvent e) 
                return true;
            

            @Override
            public void onLongPress(MotionEvent e) 
                View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                if (child != null && clickListener != null) 
                    clickListener.onLongClick(child,recyclerView,  recyclerView.getChildPosition(child));
                
            
        );
    


    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) 
        View child = rv.findChildViewUnder(e.getX(), e.getY());
        if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) 
            clickListener.onClick(child, rv.getChildPosition(child));
        
        return false;
    

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) 

    

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) 

    

最后将您的适配器设置为 Recycler View 并添加 Touch Listener 以开始拦截单击或双击列表项的触摸事件

    wifiAdapter = WifiAdapter(ArrayList())

    wifiList.apply 
        // vertical layout
        layoutManager = LinearLayoutManager(applicationContext)
        // set adapter
        adapter = wifiAdapter

        // Touch handling
        wifiList.addOnItemTouchListener(RecyclerTouchListener(applicationContext, wifiList, object : RecyclerTouchListener.ClickListener 
            override fun onClick(view: View?, position: Int) 
                Toast.makeText(applicationContext, "RV OnCLickj " + position, Toast.LENGTH_SHORT).show()
            

            override fun onLongClick(view: View, recyclerView: RecyclerView, position: Int) 
                Toast.makeText(applicationContext, "RV OnLongCLickj " + position, Toast.LENGTH_SHORT).show()
            
        
        ))
    

奖励:更新数据

wifiAdapter.updateData(mScanResults as ArrayList<ScanResult>)

结果:

【讨论】:

【参考方案3】:

这将是 RecyclerView 实现的最简单版本。

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_
        android:layout_
        android:id="@+id/recycler_view"/>

</FrameLayout>

list_item_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_>

    <TextView
        android:layout_
        android:layout_
        android:id="@+id/textview"
        android:text="TextView"
        android:textSize="16dp" />

</LinearLayout>

CustomAdapter.java

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> 
  private List<String> data;
  public CustomAdapter (List<String> data)
    this.data = data;
  

  @Override
  public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
    View rowItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_view, parent, false);
    return new ViewHolder(rowItem);
  

  @Override
  public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) 
    holder.textView.setText(this.data.get(position));
  

  @Override
  public int getItemCount() 
    return this.data.size();
  

  public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener 
    private TextView textView;

    public ViewHolder(View view) 
      super(view);
      view.setOnClickListener(this);
      this.textView = view.findViewById(R.id.textview);
    

    @Override
    public void onClick(View view) 
      Toast.makeText(view.getContext(), "position : " + getLayoutPosition() + " text : " + this.textView.getText(), Toast.LENGTH_SHORT).show();
    
  

MainActivity.java

public class MainActivity extends AppCompatActivity 

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

    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(new CustomAdapter(generateData()));
    recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
  

  private List<String> generateData() 
    List<String> data = new ArrayList<>();
    for (int i = 0; i < 100; i++) 
      data.add(String.valueOf(i) + "th Element");
    
    return data;
  


【讨论】:

【参考方案4】:

从添加 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_
    android:layout_>

    <RelativeLayout
        android:layout_
        android:padding="10dp"
        android:layout_>

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

        </RelativeLayout>
        <TextView
            android:id="@+id/username"
            android:layout_
            android:textSize="16sp"
            android:textColor="@color/headerColor"
            android:text="username"
            android:layout_marginStart="90dp"
            android:layout_centerVertical="true"
            android:layout_/>
        <ImageView
            android:layout_
            android:id="@+id/imageView"
            android:layout_margin="10dp"
            android:layout_alignParentEnd="true"
            android:src="@drawable/ic_navigate_next_black_24dp"
            android:layout_/>
    </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

【讨论】:

为什么要将上下文发送给用户适配器类usersAdapter = new UsersAdapter(userModelList,this); ?. @OmarBoshra this 指的是SelectedUser接口的实现。【参考方案5】:

这是一个更新的 Kotlin 解决方案,它比这里写的许多答案简单得多,它使用匿名类。

val items = mutableListOf<String>()

inner class ItemHolder(view: View): RecyclerView.ViewHolder(view) 
    var textField: TextView = view.findViewById(android.R.id.text1) as TextView


override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
    rvitems.layoutManager = LinearLayoutManager(context)
    rvitems.adapter = object : RecyclerView.Adapter<ItemHolder>() 

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder 
            return ItemHolder(LayoutInflater.from(parent.context).inflate(android.R.layout.simple_list_item_1, parent, false))
        

        override fun getItemCount(): Int 
            return items.size
        

        override fun onBindViewHolder(holder: ItemHolder, position: Int) 
            holder.textField.text = items[position]
            holder.textField.setOnClickListener 
                Toast.makeText(context, "Clicked $position", Toast.LENGTH_SHORT).show()
            
        
    

我冒昧地使用了 android.R.layout.simple_list_item_1,因为它更简单。我想进一步简化它并将 ItemHolder 作为内部类,但无法完全弄清楚如何在外部类参数的类型中引用它。

【讨论】:

我几乎放弃了 kotlin 和 android 开发,因为没有简单的解决方案,直到我看到你的。谢谢! 有趣。您如何响应点击? @SMBiggs 你是什么意思?处理点击的代码也出现在 onBindViewHolder 内的这个示例中。 我现在看到了——我的错。我不知何故跳过了 onBindViewHolder 的那部分。【参考方案6】:

基于不同的来源,我使用简单库创建了 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_
        android:layout_/>

现在在 MainActivity 中,通过传递需要绑定的 Class 的名称来创建一个 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);
    

通过在适配器中传递项目、类和布局来创建项目列表变量和适配器

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

一切都搞定了。

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

【讨论】:

什么是单一活动 :错误:找不到符号摘要 = v.findViewById(R.id.summary); ^ 符号:变量摘要位置:类 id EVHolder.java:15:错误:方法未覆盖或实现超类型 @Override 的方法 ^ EVHolder.java:17:错误:找不到符号 date.setText(c.date) ; @johnktejik R.id.summary 是为布局资源文件提供的 ID。请查看此布局文件github.com/hereshem/Easy-RecyclerView-Library/blob/master/app/…【参考方案7】:

开始,只是在 Recycler 视图中查看一些东西

recycler view adapter 可以是这样的。

class CustomAdapter: RecyclerView.Adapter<CustomAdapter.ViewHolder>() 
    var data =  listOf<String>()
        set(value) 
            field = value
            notifyDataSetChanged()
        
    override fun getItemCount() =data.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) 
        holder.txt.text= data[position]
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder 
        return ViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.item_view, parent, false)
        )
    


    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
        val txt: TextView = itemView.findViewById(R.id.item_text_view)
    

并将适配器附加到回收器视图并将数据附加到适配器

val view = findViewById<RecyclerView>(R.id.recycler_view)                                              
val adapter = CustomAdapter()                                                                          
val data = listOf("text1", "text2", "text3")
adapter.data = data                                                                             
view.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
view.adapter = adapter       
            

【讨论】:

【参考方案8】:

现在你需要1 adapter 来代表所有RecyclerView

一个适配器可用于所有 RecyclerView。所以 NO onBindViewHolder, No onCreateViewHolder 处理。 没有用于从 Java/Kotlin 类设置适配器的代码。检查sample class。 您可以使用Binding Adapters为每个列表设置事件和自定义数据。

我在这里展示了通过 1 个适配器设置两个不同的 RecyclerView -

activity_home.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="listOne"
            type="java.util.List"/>

        <variable
            name="listTwo"
            type="java.util.List"/>

        <variable
            name="onItemClickListenerOne"
            type="com.ks.nestedrecyclerbindingexample.callbacks.OnItemClickListener"/>

        <variable
            name="onItemClickListenerTwo"
            type="com.ks.nestedrecyclerbindingexample.callbacks.OnItemClickListener"/>

    </data>

    <LinearLayout
        android:layout_
        android:layout_
        android:orientation="vertical">

        <android.support.v7.widget.RecyclerView
            rvItemLayout="@@layout/row_one"
            rvList="@listOne"
            rvOnItemClick="@onItemClickListenerOne"
            android:layout_
            android:layout_
            app:layoutManager="android.support.v7.widget.LinearLayoutManager"
            />

        <android.support.v7.widget.RecyclerView
            rvItemLayout="@@layout/row_two"
            rvList="@listTwo"
            rvOnItemClick="@onItemClickListenerTwo"
            android:layout_
            android:layout_
            app:layoutManager="android.support.v7.widget.LinearLayoutManager"
            />

    </LinearLayout>

</layout>

你可以看到我从布局中传递了列表、项目布局id和点击监听器。

rvItemLayout="@@layout/row_one"
rvList="@listOne"
rvOnItemClick="@onItemClickListenerOne"

此自定义属性由 BindingAdapter 创建。

public class BindingAdapters 
    @BindingAdapter(value = "rvItemLayout", "rvList", "rvOnItemClick", requireAll = false)
    public static void setRvAdapter(RecyclerView recyclerView, int rvItemLayout, List rvList, @Nullable OnItemClickListener onItemClickListener) 
        if (rvItemLayout != 0 && rvList != null && rvList.size() > 0)
            recyclerView.setAdapter(new GeneralAdapter(rvItemLayout, rvList, onItemClickListener));
    

现在从Activity,你传递列表,点击监听器

HomeActivity.java

public class HomeActivity extends AppCompatActivity 
    ActivityHomeBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_home);
        binding.setListOne(new ArrayList()); // pass your list or set list from response of API
        binding.setListTwo(new ArrayList());
        binding.setOnItemClickListenerOne(new OnItemClickListener() 
            @Override
            public void onItemClick(View view, Object object) 
                if (object instanceof ModelParent) 
                    // TODO: your action here
                
            
        );
        binding.setOnItemClickListenerTwo(new OnItemClickListener() 
            @Override
            public void onItemClick(View view, Object object) 
                if (object instanceof ModelChild) 
                    // TODO: your action here  
                
            
        );
    

你不想读太多,直接从我的github repo克隆/下载full example。自己试试吧。

你可以在上面的 repo 中看到GeneralAdapter.java

如果您在设置数据绑定时遇到问题,请参阅this answer。

【讨论】:

【参考方案9】:

依赖关系

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;
    


【讨论】:

解释会很好 代码不干净,没有解释!【参考方案10】:

由于我无法发表评论,但我将发布链接作为答案。我在 recyclerview 上找到了一个简单、组织良好的教程 http://www.androiddeft.com/2017/10/01/recyclerview-android/

除此之外,当您要在活动中添加回收站视图时,您想要执行的操作如下,链接中已经描述了您应该如何执行此操作

将 RecyclerView 组件添加到您的布局文件中 创建一个要显示为列表行的类 制作一个布局文件,它是你列表中一行的布局 现在我们需要一个自定义适配器,所以通过扩展创建一个自定义适配器 来自父类 RecyclerView.Adapter 将 recyclerview 添加到您的 mainActivity oncreate 添加分隔符 添加触摸监听器

【讨论】:

【参考方案11】:

您可以将抽象适配器与差异工具和过滤器一起使用

SimpleAbstractAdapter.kt

abstract class SimpleAbstractAdapter<T>(private var items: ArrayList<T> = arrayListOf()) : RecyclerView.Adapter<SimpleAbstractAdapter.VH>() 
   protected var listener: OnViewHolderListener<T>? = null
   private val filter = ArrayFilter()
   private val lock = Any()
   protected abstract fun getLayout(): Int
   protected abstract fun bindView(item: T, viewHolder: VH)
   protected abstract fun getDiffCallback(): DiffCallback<T>?
   private var onFilterObjectCallback: OnFilterObjectCallback? = null
   private var constraint: CharSequence? = ""

override fun onBindViewHolder(vh: VH, position: Int) 
    getItem(position)?.let  bindView(it, vh) 


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH 
    return VH(parent, getLayout())


override fun getItemCount(): Int = items.size

protected abstract class DiffCallback<T> : DiffUtil.Callback() 
    private val mOldItems = ArrayList<T>()
    private val mNewItems = ArrayList<T>()

    fun setItems(oldItems: List<T>, newItems: List<T>) 
        mOldItems.clear()
        mOldItems.addAll(oldItems)
        mNewItems.clear()
        mNewItems.addAll(newItems)
    

    override fun getOldListSize(): Int 
        return mOldItems.size
    

    override fun getNewListSize(): Int 
        return mNewItems.size
    

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean 
        return areItemsTheSame(
                mOldItems[oldItemPosition],
                mNewItems[newItemPosition]
        )
    

    abstract fun areItemsTheSame(oldItem: T, newItem: T): Boolean

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean 
        return areContentsTheSame(
                mOldItems[oldItemPosition],
                mNewItems[newItemPosition]
        )
    

    abstract fun areContentsTheSame(oldItem: T, newItem: T): Boolean


class VH(parent: ViewGroup, @LayoutRes layout: Int) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(layout, parent, false))

interface OnViewHolderListener<T> 
    fun onItemClick(position: Int, item: T)


fun getItem(position: Int): T? 
    return items.getOrNull(position)


fun getItems(): ArrayList<T> 
    return items


fun setViewHolderListener(listener: OnViewHolderListener<T>) 
    this.listener = listener


fun addAll(list: List<T>) 
    val diffCallback = getDiffCallback()
    when 
        diffCallback != null && !items.isEmpty() -> 
            diffCallback.setItems(items, list)
            val diffResult = DiffUtil.calculateDiff(diffCallback)
            items.clear()
            items.addAll(list)
            diffResult.dispatchUpdatesTo(this)
        
        diffCallback == null && !items.isEmpty() -> 
            items.clear()
            items.addAll(list)
            notifyDataSetChanged()
        
        else -> 
            items.addAll(list)
            notifyDataSetChanged()
        
    


fun add(item: T) 
    items.add(item)
    notifyDataSetChanged()


fun add(position:Int, item: T) 
    items.add(position,item)
    notifyItemInserted(position)


fun remove(position: Int) 
    items.removeAt(position)
    notifyItemRemoved(position)


fun remove(item: T) 
    items.remove(item)
    notifyDataSetChanged()


fun clear(notify: Boolean=false) 
    items.clear()
    if (notify) 
        notifyDataSetChanged()
    


fun setFilter(filter: SimpleAdapterFilter<T>): ArrayFilter 
    return this.filter.setFilter(filter)


interface SimpleAdapterFilter<T> 
    fun onFilterItem(contains: CharSequence, item: T): Boolean


fun convertResultToString(resultValue: Any): CharSequence 
    return filter.convertResultToString(resultValue)


fun filter(constraint: CharSequence) 
    this.constraint = constraint
    filter.filter(constraint)


fun filter(constraint: CharSequence, listener: Filter.FilterListener) 
    this.constraint = constraint
    filter.filter(constraint, listener)


fun getFilter(): Filter 
    return filter


interface OnFilterObjectCallback 
    fun handle(countFilterObject: Int)


fun setOnFilterObjectCallback(objectCallback: OnFilterObjectCallback) 
    onFilterObjectCallback = objectCallback


inner class ArrayFilter : Filter() 
    private var original: ArrayList<T> = arrayListOf()
    private var filter: SimpleAdapterFilter<T> = DefaultFilter()
    private var list: ArrayList<T> = arrayListOf()
    private var values: ArrayList<T> = arrayListOf()


    fun setFilter(filter: SimpleAdapterFilter<T>): ArrayFilter 
        original = items
        this.filter = filter
        return this
    

    override fun performFiltering(constraint: CharSequence?): Filter.FilterResults 
        val results = Filter.FilterResults()
        if (constraint == null || constraint.isBlank()) 
            synchronized(lock) 
                list = original
            
            results.values = list
            results.count = list.size
         else 
            synchronized(lock) 
                values = original
            
            val result = ArrayList<T>()
            for (value in values) 
                if (constraint!=null && constraint.trim().isNotEmpty() && value != null) 
                    if (filter.onFilterItem(constraint, value)) 
                        result.add(value)
                    
                 else 
                    value?.let  result.add(it) 
                
            
            results.values = result
            results.count = result.size
        
        return results
    

    override fun publishResults(constraint: CharSequence, results: Filter.FilterResults) 
        items = results.values as? ArrayList<T> ?: arrayListOf()
        notifyDataSetChanged()
        onFilterObjectCallback?.handle(results.count)
    



class DefaultFilter<T> : SimpleAdapterFilter<T> 
    override fun onFilterItem(contains: CharSequence, item: T): Boolean 
        val valueText = item.toString().toLowerCase()
        if (valueText.startsWith(contains.toString())) 
            return true
         else 
            val words = valueText.split(" ".toRegex()).dropLastWhile  it.isEmpty() .toTypedArray()
            for (word in words) 
                if (word.contains(contains)) 
                    return true
                
            
        
        return false
    
  

并通过实现方法扩展抽象适配器

TasksAdapter.kt

import android.annotation.SuppressLint
  import kotlinx.android.synthetic.main.task_item_layout.view.*

class TasksAdapter(private val listener:TasksListener? = null) : SimpleAbstractAdapter<Task>() 
override fun getLayout(): Int 
    return R.layout.task_item_layout


override fun getDiffCallback(): DiffCallback<Task>? 
    return object : DiffCallback<Task>() 
        override fun areItemsTheSame(oldItem: Task, newItem: Task): Boolean 
            return oldItem.id == newItem.id
        

        override fun areContentsTheSame(oldItem: Task, newItem: Task): Boolean 
            return oldItem.items == newItem.items
        
    


@SuppressLint("SetTextI18n")
override fun bindView(item: Task, viewHolder: VH) 
    viewHolder.itemView.apply 
        val position = viewHolder.adapterPosition
        val customer = item.customer
        val customerName = if (customer != null) customer.name else ""
        tvTaskCommentTitle.text = customerName + ", #" + item.id
        tvCommentContent.text = item.taskAddress
        ivCall.setOnClickListener 
            listener?.onCallClick(position, item)
        
        setOnClickListener 
            listener?.onItemClick(position, item)
        
    


 interface TasksListener : SimpleAbstractAdapter.OnViewHolderListener<Task> 
    fun onCallClick(position: Int, item: Task)
 

初始化适配器

mAdapter = TasksAdapter(object : TasksAdapter.TasksListener 
            override fun onCallClick(position: Int, item:Task) 
            

            override fun onItemClick(position: Int, item:Task) 

            
        )
rvTasks.adapter = mAdapter

填充

mAdapter?.addAll(tasks)

添加自定义过滤器

mAdapter?.setFilter(object : SimpleAbstractAdapter.SimpleAdapterFilter<MoveTask> 
            override fun onFilterItem(contains: CharSequence, item:Task): Boolean 
                return contains.toString().toLowerCase().contains(item.id?.toLowerCase().toString())
            
    )

过滤数据

mAdapter?.filter("test")

【讨论】:

使用 diff utils 添加一些更改,添加类型支持gist.github.com/arnyigor/568035c6db9bdbeaf609b68a71834349【参考方案12】:

实现 androidx.recyclerview:recyclerview:.... 建议更新到这里的 androidx 库:

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

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

【讨论】:

你是对的。我需要用 AndroidX 更新我的答案。

以上是关于简单的 Android RecyclerView 示例的主要内容,如果未能解决你的问题,请参考以下文章

RecyclerView的简单使用方法

android RecyclerView简单的使用

Android实战----RecyclerView下拉刷新和上拉加载的简单实现

Android实战----RecyclerView下拉刷新和上拉加载的简单实现

使用带有 GridLayoutManager 的 RecyclerView 的简单 Android 网格示例(如旧的 GridView)

RecyclerView简单例子演示