简单的Android RecyclerView示例

我已经使用Android的RecyclerView做了几次项目列表,但这是一个相当复杂的过程。通过众多的在线教程作品之一(,和都很好),但我正在寻找一个基本的例子,我可以复制和粘贴来快速启动和运行。只需要以下特性:

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

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

392019 次浏览

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

RecyclerView with a list of animal names

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

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

更新Gradle依赖项

确保以下依赖项在你的app gradle.build文件中:

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

你可以将版本号更新为最新的。如果你仍在使用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_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);
}
}

笔记

  • 虽然不是严格必要的,但我包含了监听行上的单击事件的功能。这在旧的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);

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

在单击时更改行颜色

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

插入单个项目

更新的行

有关如何添加、删除和更新行,请参阅这个答案

插入单个项目

进一步的阅读

依赖关系

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上找到了一个简单、组织良好的教程 http://www.androiddeft.com/2017/10/01/recyclerview-android/ < / p >

除此之外,当你要在你的活动中添加一个回收器视图时,你想做的事情如下所示,你应该如何做,已经在链接中描述了

  • 将RecyclerView组件添加到布局文件中
  • 创建一个要显示为列表行的类
  • 制作一个布局文件,这是你列表中的一行的布局
  • 现在我们需要一个自定义适配器,因此通过扩展创建一个自定义适配器 从父类RecyclerView。李适配器< / >
  • 在mainActivity oncreate中添加recyclerview
  • 添加分隔符
  • 添加Touch监听器

基于不同的资源,我使用简单库创建了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();
}
});

都搞定了。

更多的例子和实现可以找到在这里。 希望这能有所帮助!!< / p >

现在你需要为所有RecyclerView使用1个适配器

  • 一个适配器可以用于所有的RecyclerView。所以没有 onBindViewHolder没有 onCreateViewHolder处理。
  • 没有从Java/Kotlin类设置适配器的代码。检查样本类
  • 你可以使用绑定适配器为每个列表设置事件和自定义数据。

截图

我在这里显示设置两个不同的RecyclerView by 1适配器-

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_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">


<android.support.v7.widget.RecyclerView
rvItemLayout="@{@layout/row_one}"
rvList="@{listOne}"
rvOnItemClick="@{onItemClickListenerOne}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
/>


<android.support.v7.widget.RecyclerView
rvItemLayout="@{@layout/row_two}"
rvList="@{listTwo}"
rvOnItemClick="@{onItemClickListenerTwo}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
/>


</LinearLayout>


</layout>

你可以看到我传递列表,项目布局id和点击listener从布局。

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中,你传递list,点击listener like

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中看到GeneralAdapter.java

如果您在设置数据绑定时遇到问题,请参阅这个答案

您可以使用带有diff utils和过滤器的抽象适配器

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")

最小化回收器视图准备使用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_width="match_parent"
android:layout_height="match_parent"
/>

创建一个显示列表项的布局(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_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:padding="5dp"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">


<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/ssid"
android:text="@string/app_name"
android:layout_width="match_parent"
android:textSize="17sp"
android:layout_height="wrap_content" />
        

</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) {


}

最后,将适配器设置为回收器视图,并添加触摸侦听器,以开始拦截单次或双击列表项的触摸事件

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

< >强结果: enter image description here < / p >

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

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

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

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

enter image description here

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_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">


<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
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_width="match_parent"
android:layout_height="46dp">


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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;
}


}

这里有一个更新的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作为一个内部类,但不太清楚如何在外部类参数的类型中引用它。

Android RecyclerView

首先添加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);


}

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

< a href = " https://youtu.be/ujKDN_ZtGHQ?sub_confirmation = 1”rel = " noreferrer " Android RecyclerView > < / >

首先,在Recycler视图中查看一些内容

回收器视图适配器可以是这样的。

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
            

我很高兴我不是唯一一个认为这些“最小”的东西都很疯狂的人。例如,为了创建一个简单的工具,需要创建至少4个不同的文件。

下面是Kotlin中的一个独立活动(构建在这是Saifur Rahman Mohsin的回答之上),它实现了一个基本的回收器视图:

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView


class ModelDownloaderActivity : AppCompatActivity() {


val items = (1..50).toList().map { "Item #$it" }
inner class ItemHolder(view: View, var textField: TextView = view.findViewById(android.R.id.text1)) : RecyclerView.ViewHolder(view)


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)


// Create recycler view, or find it in Activity's XML file if you prefer
val myLayoutResource: Int? = null // Replace with R.layout.activity_model_downloader if you want to use an XML layout with a recycler view in it
val recyclerView = myLayoutResource?.let {
setContentView(it)
findViewById(R.id.modelRecyclerView) // Replace with ID of your recycler view in layout
} ?: RecyclerView(this).also { setContentView(ConstraintLayout(this).apply { addView(it) }) }


// Bind controls to it.
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = object : RecyclerView.Adapter<ItemHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
ItemHolder(LayoutInflater.from(parent.context).inflate(android.R.layout.simple_list_item_1, parent, false))
override fun getItemCount() = items.size
override fun onBindViewHolder(holder: ItemHolder, position: Int) {
holder.textField.text = items[position]
holder.textField.setOnClickListener {
Toast.makeText(this@ModelDownloaderActivity, "Clicked $position", Toast.LENGTH_SHORT).show()
}
}
}
}
}