😽作者:勇敢di牛牛
🚀个人项目地址:englishlearningapp
个人简介:有一年工作经验的大学生。
工作:汽车系统应用开发(阿里集团)
个人网站:牛牛の小窝
🚏独学而无友,则孤陋而寡闻
🚏独学而无友,则孤陋而寡闻# 前言
之前我们用listview+cardView的方法,实现了一个工具列表(在Fragment中实现listview中嵌套cardview),现在要做一个单词书本的列表,本来打算也是用listview+cardView的方法去实现,但是最近发现了RecyclerView这个控件,看起来好像略微高级一丢丢,所以就尝试一下,用RecyclerView+cardView来实现这个功能。
效果预览
用bean装载数据
我们在在Fragment中实现listview中嵌套cardview这篇文章中用的是List<Map<String, Object>>来装填数据,显得较为麻烦,刚好最近刷视频,看到有UP主用到这个方法,所以今天就来实践一下。
Bean是什么?
javaBean在MVC设计模型中是model,又称模型层,在一般的程序中,我们称它为数据层,就是用来设置数据的属性和一些行为,然后我会提供获取属性和设置属性的get/set方法JavaBean是一种JAVA语言写成的可重用组件。
所以,我们一般利用bean类来存放一些特定的属性或行为,而不存放值,这样我们就能多次调用bean类中的属性并赋值使用,实现重复使用的功能。
——————————————弱水三千Y
我个人理解其实就是把List之类的数据面向对象化了。
Bean该怎么使用
首先新建一个文件夹,里面新建一个Java文件,
如上图所示,我在RecyclerView中的每一个Iteam都需要这些属性来对其进行填充,建里这样一个类,方便我们对数据进行操作。
写一个适配器
适配器的写法和之前的大同小异,这里就直接贴代码了,
package com.example.testapp.Adapter;
// 获取词书封面,标题,简介,下载状态。
import static android.content.ContentValues.TAG;
import static com.example.testapp.R.drawable.ic_collected;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.example.testapp.R;
import com.example.testapp.bean.BookItemBean;
import java.util.List;
public class BookListAdapter extends RecyclerView.Adapter<BookListAdapter.InnerHolder> {
private final List<BookItemBean> mData;
public BookListAdapter(List<BookItemBean> data){
mData = data;
}
@Override
public InnerHolder onCreateViewHolder( ViewGroup parent, int viewType) {
//复用布局
View view = View.inflate(parent.getContext(),R.layout.word_book_card,null);
return new InnerHolder(view);
}
@Override
public void onBindViewHolder(@NonNull BookListAdapter.InnerHolder holder, int position) {
holder.setData(mData.get(position));
}
@Override
public int getItemCount() {
if(mData != null){
return mData.size();
}
return 0;
}
public class InnerHolder extends RecyclerView.ViewHolder {
View view;
ImageView imgView;
TextView name,introduce;
Button button;
public InnerHolder(@NonNull View itemView) {
super(itemView);
view = itemView;
imgView = view.findViewById(R.id.book_image);
name = view.findViewById(R.id.book_name);
introduce = view.findViewById(R.id.book_introduce);
button = view.findViewById(R.id.book_download);
}
public void setData(BookItemBean bean) {
Log.i(TAG, String.valueOf(Uri.parse(bean.BookImg)));
Glide.with(imgView).load(bean.BookImg).into(imgView);
//imgView.setImageURI(Uri.parse(bean.BookImg));
name.setText(bean.BookName);
introduce.setText(bean.BookIntroduce);
}
}
}
分割线的简单实现方法
这个不像之前的listView,RecyclerView是没有提供实现分割线的Api,
android:divider = "#00000000"
android:dividerHeight="18dp"
这样添加分割的方法在recyclerview中是无效的。网上也有许多添加分割的方法,但是比较复杂,这里我用一个投机取巧的方法实现同养的效果。
思路:
从cardView下手,在cardView的外面包裹一个Layout,然后设置cardView与其之间的间距。
如图,我们把红色的一整个部分当作ItemView,当取消背景后,看起来就和设置了间距的效果一样了。
下拉刷新效果的实现步骤:
这里做了一个刷新后向列表的最前面添加一条Item
在xml中添加下拉控件
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/book_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/book_list"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
这里一定要把RecyclerView包裹进去
我猜到这里,你会报错找不到这个空间,如果出现波浪线的解决方法:
在bulid.grandle文件中添加:
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
然后就Ok啦 。
在Activity中添加刷新的监听事件
swipeRefresh = this.findViewById(R.id.book_refresh);
initData();
handlerRefresh();
}
private void handlerRefresh() {
swipeRefresh.setEnabled(true);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
//@SuppressLint("NotifyDataSetChanged")
@SuppressLint("NotifyDataSetChanged")
@Override
public void onRefresh() {
//新建一条数据
Log.i(TAG, "onRefresh:刷新数据");
BookItemBean data = new BookItemBean();
data.BookName = "新书";
data.isDownload = false;
data.BookIntroduce = "我是新添加的书本";
data.BookImg = "https://img0.baidu.com/it/u=3939618057,2844598562&fm=253&fmt=auto&app=138&f=JPEG?w=350&h=350";
mdata.add(0,data);
adapter.notifyDataSetChanged();
swipeRefresh.setRefreshing(false);
}
});
}
这里的swipeRefresh要在前面申明,类型:SwipeRefreshLayout
在实际应用中这种刷新的操作不能放在主线程中进行,要开一个新线程,这里为了方便实现演示效果所以放在主线程中去添加一条数据。