我用Android的RecyclerView做过几次物品列表,但这是一个相当复杂的过程。浏览众多在线教程中的一个作品(这个,这个,这个都很好),但我正在寻找一个简单的示例,我可以复制和粘贴来快速启动和运行。只需要以下特性:
垂直布局 每行都有一个单一的TextView 响应点击事件
因为这个愿望我已经许过好几次了,所以我最终决定把答案写在下面,供我和你们将来参考。
我用Android的RecyclerView做过几次物品列表,但这是一个相当复杂的过程。浏览众多在线教程中的一个作品(这个,这个,这个都很好),但我正在寻找一个简单的示例,我可以复制和粘贴来快速启动和运行。只需要以下特性:
垂直布局 每行都有一个单一的TextView 响应点击事件
因为这个愿望我已经许过好几次了,所以我最终决定把答案写在下面,供我和你们将来参考。
当前回答
首先添加recyclerview库。
implementation 'androidx.recyclerview:recyclerview:1.1.0'
创建模型类。
public class UserModel implements Serializable {
private String userName;
public UserModel(String userName) {
this.userName = userName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
创建适配器类。
public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.UsersAdapterVh> implements Filterable {
private List<UserModel> userModelList;
private List<UserModel> getUserModelListFiltered;
private Context context;
private SelectedUser selectedUser;
public UsersAdapter(List<UserModel> userModelList,SelectedUser selectedUser) {
this.userModelList = userModelList;
this.getUserModelListFiltered = userModelList;
this.selectedUser = selectedUser;
}
@NonNull
@Override
public UsersAdapter.UsersAdapterVh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
return new UsersAdapterVh(LayoutInflater.from(context).inflate(R.layout.row_users,null));
}
@Override
public void onBindViewHolder(@NonNull UsersAdapter.UsersAdapterVh holder, int position) {
UserModel userModel = userModelList.get(position);
String username = userModel.getUserName();
String prefix = userModel.getUserName().substring(0,1);
holder.tvUsername.setText(username);
holder.tvPrefix.setText(prefix);
}
@Override
public int getItemCount() {
return userModelList.size();
}
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults filterResults = new FilterResults();
if(charSequence == null | charSequence.length() == 0){
filterResults.count = getUserModelListFiltered.size();
filterResults.values = getUserModelListFiltered;
}else{
String searchChr = charSequence.toString().toLowerCase();
List<UserModel> resultData = new ArrayList<>();
for(UserModel userModel: getUserModelListFiltered){
if(userModel.getUserName().toLowerCase().contains(searchChr)){
resultData.add(userModel);
}
}
filterResults.count = resultData.size();
filterResults.values = resultData;
}
return filterResults;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
userModelList = (List<UserModel>) filterResults.values;
notifyDataSetChanged();
}
};
return filter;
}
public interface SelectedUser{
void selectedUser(UserModel userModel);
}
public class UsersAdapterVh extends RecyclerView.ViewHolder {
TextView tvPrefix;
TextView tvUsername;
ImageView imIcon;
public UsersAdapterVh(@NonNull View itemView) {
super(itemView);
tvPrefix = itemView.findViewById(R.id.prefix);
tvUsername = itemView.findViewById(R.id.username);
imIcon = itemView.findViewById(R.id.imageView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
selectedUser.selectedUser(userModelList.get(getAdapterPosition()));
}
});
}
}
}
创建布局row_uses.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:padding="10dp"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="50dp"
android:background="@drawable/users_bg"
android:layout_height="50dp">
<TextView
android:id="@+id/prefix"
android:layout_width="wrap_content"
android:textSize="16sp"
android:textColor="@color/headerColor"
android:text="T"
android:layout_centerInParent="true"
android:layout_height="wrap_content"/>
</RelativeLayout>
<TextView
android:id="@+id/username"
android:layout_width="wrap_content"
android:textSize="16sp"
android:textColor="@color/headerColor"
android:text="username"
android:layout_marginStart="90dp"
android:layout_centerVertical="true"
android:layout_height="wrap_content"/>
<ImageView
android:layout_width="wrap_content"
android:id="@+id/imageView"
android:layout_margin="10dp"
android:layout_alignParentEnd="true"
android:src="@drawable/ic_navigate_next_black_24dp"
android:layout_height="wrap_content"/>
</RelativeLayout>
</LinearLayout>
查找recyclerview并填充数据。
Toolbar toolbar;
RecyclerView recyclerView;
List<UserModel> userModelList = new ArrayList<>();
String[] names = {"Richard","Alice","Hannah","David"};
UsersAdapter usersAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerview);
toolbar = findViewById(R.id.toolbar);
this.setSupportActionBar(toolbar);
this.getSupportActionBar().setTitle("");
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
for(String s:names){
UserModel userModel = new UserModel(s);
userModelList.add(userModel);
}
usersAdapter = new UsersAdapter(userModelList,this);
recyclerView.setAdapter(usersAdapter);
}
在这里找到完整的教程和源代码:
Android RecyclerView
其他回答
基于不同的资源,我使用简单库创建了RecyclerView的简单实现。
在build.gradle中添加这一行
implementation 'com.hereshem.lib:awesomelib:2.0.1'
通过在activity_main.xml中添加MyRecyclerView来创建一个RecyclerView
<com.hereshem.lib.recycler.MyRecyclerView
android:id="@+id/recycler"
app:layoutManager="LinearLayoutManager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
现在在MainActivity中,通过传递需要绑定的类的名称来创建一个ViewHolder
public static class EVHolder extends MyViewHolder<Events> {
TextView date, title, summary;
public EVHolder(View v) {
super(v);
date = v.findViewById(R.id.date);
title = v.findViewById(R.id.title);
summary = v.findViewById(R.id.summary);
}
@Override
public void bindView(Events c) {
date.setText(c.date);
title.setText(c.title);
summary.setText(c.summary);
}
}
通过在适配器中传递项目、类和布局来创建Items列表变量和适配器,行数很少
List<Events> items = new ArrayList<>();
MyRecyclerView recycler = findViewById(R.id.recycler);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, items, EVHolder.class, R.layout.row_event);
recycler.setAdapter(adapter);
ClickListener可以用以下几行添加
recycler.setOnItemClickListener(new MyRecyclerView.OnItemClickListener() {
@Override
public void onItemClick(int position) {
Toast.makeText(MainActivity.this, "Recycler Item Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
都搞定了。
更多示例和实现可以在这里找到。 希望这能有所帮助!!
这将是RecyclerView实现的最简单版本。
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;
}
}
由于我还不能评论,我将发布一个链接的答案..我在recyclerview上找到了一个简单、组织良好的教程 http://www.androiddeft.com/2017/10/01/recyclerview-android/
除此之外,当你要在你的活动中添加一个回收器视图时,你想做的事情如下所示,你应该如何做,已经在链接中描述了
将RecyclerView组件添加到布局文件中 创建一个要显示为列表行的类 制作一个布局文件,这是你列表中的一行的布局 现在我们需要一个自定义适配器,因此通过扩展来创建一个自定义适配器 从父类RecyclerView。适配器 在mainActivity oncreate中添加recyclerview 添加分隔符 添加Touch监听器
首先,在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
最小化回收器视图准备使用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>)
结果: