本人是新入坑的Android开发小白,最近呢,应领导要求,公司对项目重新设计了,其中一个页面是这样的,重新设计以后要做成这个样子,如果是以前,我肯定会不加思索的照原来一样用两个recyclerview嵌套来实现,但毕竟是以前嘛,这里给大家推荐一个万能适配器BaseQuickAdapter之BaseSectionQuickAdapter来实现这一功能,如果有类似需求,使用这个可能会比较方便一点,一个recyclerview就可以搞定,如果有更方便好用的,还请不吝赐教,这是我的第一篇博客,写的不好,还请各位前辈指点一二,话不多说,进入正题。
设计前 设计后 实现效果
添加依赖:implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'
在布局文件添加 RecyclerView
<LinearLayout 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/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
两个item,一个头部布局
<?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="wrap_content">
<TextView
android:id="@+id/text_header"
android:padding="@dimen/dp_10"
android:textColor="#000000"
android:textSize="@dimen/sp_16"
android:text="标题"
android:layout_marginLeft="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
一个子item布局
<?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="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:padding="@dimen/dp_10"
android:id="@+id/text_content"
android:gravity="center"
android:textSize="@dimen/sp_14"
android:text="内容"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
一个实体类,继承SectionEntity
public class ExamCourseSection extends SectionEntity<ExamInfoBean.ExamDataBean.InfoListBean> {
public ExamCourseSection(boolean isHeader, String header) {
super(isHeader, header);
}
public ExamCourseSection(ExamInfoBean.ExamDataBean.InfoListBean bean) {
super(bean);
}
}
我的数据实体类,当然你也可以只写一个实体类,把下面这个和上面的写成一个
public class ExamInfoBean {
private int Status;
private String Ver;
private String ErrMsg;
private List<ExamDataBean> Data;
public int getStatus() {
return Status;
}
public void setStatus(int Status) {
this.Status = Status;
}
public String getVer() {
return Ver;
}
public void setVer(String Ver) {
this.Ver = Ver;
}
public String getErrMsg() {
return ErrMsg;
}
public void setErrMsg(String ErrMsg) {
this.ErrMsg = ErrMsg;
}
public List<ExamDataBean> getData() {
return Data;
}
public void setData(List<ExamDataBean> Data) {
this.Data = Data;
}
public static class ExamDataBean {
private int etId;
private String title;
private int order;
private List<InfoListBean> infoList;
public int getEtId() {
return etId;
}
public void setEtId(int etId) {
this.etId = etId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public List<InfoListBean> getInfoList() {
return infoList;
}
public void setInfoList(List<InfoListBean> infoList) {
this.infoList = infoList;
}
public static class InfoListBean {
private int eiid;
private int etid;
private String title;
private String eiIco;
private int isCentCourse;
private int order;
public int getEiid() {
return eiid;
}
public void setEiid(int eiid) {
this.eiid = eiid;
}
public int getEtid() {
return etid;
}
public void setEtid(int etid) {
this.etid = etid;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getIsCentCourse() {
return isCentCourse;
}
public void setIsCentCourse(int isCentCourse) {
this.isCentCourse = isCentCourse;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public String getEiIco() {
return eiIco;
}
public void setEiIco(String eiIco) {
this.eiIco = eiIco;
}
}
}
}
来看一下适配器,两个方法,一个设置header的显示内容,一个设置content显示内容,适配器初始化的时候要注意这段话
/**
* Same as QuickAdapter#QuickAdapter(Context,int) but with
* some initialization data.
*
* @param layoutResId The layout resource id of each item.
* @param sectionHeadResId The section head layout id for each item
* @param data A new list is created out of this one to avoid mutable list
*/
public class ExamCourseAdapter extends BaseSectionQuickAdapter<ExamCourseSection, BaseViewHolder> {
/**
* Same as QuickAdapter#QuickAdapter(Context,int) but with
* some initialization data.
*
* @param layoutResId The layout resource id of each item.
* @param sectionHeadResId The section head layout id for each item
* @param data A new list is created out of this one to avoid mutable list
*/
public ExamCourseAdapter(int layoutResId, int sectionHeadResId, List<ExamCourseSection> data) {
super(layoutResId, sectionHeadResId, data);
}
@Override
protected void convertHead(BaseViewHolder helper, ExamCourseSection item) {
helper.setText(R.id.text_header, item.header);
}
@Override
protected void convert(BaseViewHolder helper, ExamCourseSection item) {
ExamInfoBean.ExamDataBean.InfoListBean listBean = item.t;
helper.setText(R.id.text_content, listBean.getTitle());
}
}
Activity的实现
private void initView() {
recyclerView = findViewById(R.id.recyclerview);
noData = LayoutInflater.from(this).inflate(R.layout.recyclerview_empty_view3, (ViewGroup) recyclerView.getParent(), false);
examCourseAdapter = new ExamCourseAdapter(R.layout.view_list_item, R.layout.view_home_list_item, new ArrayList<ExamCourseSection>());
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
recyclerView.setAdapter(examCourseAdapter);
examCourseAdapter.setOnItemClickListener(this);
}
View noData = LayoutInflater.from(this).inflate(R.layout.recyclerview_empty_view3, (ViewGroup) recyclerView.getParent(), false); //加载一个布局,当没有请求到数据时显示
private void initData() {
for (int i = 0; i < 3; i++) {
ExamInfoBean.ExamDataBean dataBean = new ExamInfoBean.ExamDataBean();
dataBean.setTitle("标题" + i);
List<ExamInfoBean.ExamDataBean.InfoListBean> list = new ArrayList<>();
for (int j = 0; j < 10; j++) {
ExamInfoBean.ExamDataBean.InfoListBean listBean = new ExamInfoBean.ExamDataBean.InfoListBean();
listBean.setTitle("内容" + j);
list.add(listBean);
dataBean.setInfoList(list);
}
beanList.add(dataBean);
}
}
initData()方法,模拟网络请求回来的数据
public void setListData() {
if (beanList == null || beanList.size() == 0) {
examCourseAdapter.setEmptyView(noData);
examCourseAdapter.setNewData(new ArrayList<ExamCourseSection>());
} else {
examCourseAdapter.setNewData(initList());
}
}
setListData()方法,当网络请求成功之后调用此方法
examCourseAdapter.setEmptyView(noData); //当beanList为空时加载此布局
当beanList不为空时,调用initList()方法
private List<ExamCourseSection> initList() {
List<ExamCourseSection> list = new ArrayList<>();
if (beanList.size() == 0) {
return list;
}
for (int i = 0; i < beanList.size(); i++) {
ExamCourseSection sectionHeader = new ExamCourseSection(true, beanList.get(i).getTitle());
list.add(sectionHeader);
if (beanList.get(i).getInfoList().size() != 0) {
for (int j = 0; j < beanList.get(i).getInfoList().size(); j++) {
ExamCourseSection section = new ExamCourseSection(beanList.get(i).getInfoList().get(j));
list.add(section);
}
}
}
return list;
}
这样要注意,头部(标题)数据和内容数据new对象时传的数据不一样,看一下上面ExamCourseSection实体类,方法重载
adapter点击事件
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
ExamInfoBean.ExamDataBean.InfoListBean bean = ((ExamCourseSection) adapter.getItem(position)).t;
ToastUtils.showShort(MainActivity.this, "选择了" + bean.getTitle());
}
贴上Activity完整代码
public class MainActivity extends AppCompatActivity implements BaseQuickAdapter.OnItemClickListener {
private RecyclerView recyclerView;
private ExamCourseAdapter examCourseAdapter;
private List<ExamInfoBean.ExamDataBean> beanList = new ArrayList<>();
private View noData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
setListData();
}
private void initData() {
for (int i = 0; i < 3; i++) {
ExamInfoBean.ExamDataBean dataBean = new ExamInfoBean.ExamDataBean();
dataBean.setTitle("标题" + i);
List<ExamInfoBean.ExamDataBean.InfoListBean> list = new ArrayList<>();
for (int j = 0; j < 10; j++) {
ExamInfoBean.ExamDataBean.InfoListBean listBean = new ExamInfoBean.ExamDataBean.InfoListBean();
listBean.setTitle("内容" + j);
list.add(listBean);
dataBean.setInfoList(list);
}
beanList.add(dataBean);
}
}
private void initView() {
recyclerView = findViewById(R.id.recyclerview);
noData = LayoutInflater.from(this).inflate(R.layout.recyclerview_empty_view3, (ViewGroup) recyclerView.getParent(), false);
examCourseAdapter = new ExamCourseAdapter(R.layout.view_list_item, R.layout.view_home_list_item, new ArrayList<ExamCourseSection>());
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
recyclerView.setAdapter(examCourseAdapter);
examCourseAdapter.setOnItemClickListener(this);
}
public void setListData() {
if (beanList == null || beanList.size() == 0) {
examCourseAdapter.setEmptyView(noData);
examCourseAdapter.setNewData(new ArrayList<ExamCourseSection>());
} else {
examCourseAdapter.setNewData(initList());
}
}
private List<ExamCourseSection> initList() {
List<ExamCourseSection> list = new ArrayList<>();
if (beanList.size() == 0) {
return list;
}
for (int i = 0; i < beanList.size(); i++) {
ExamCourseSection sectionHeader = new ExamCourseSection(true, beanList.get(i).getTitle());
list.add(sectionHeader);
if (beanList.get(i).getInfoList().size() != 0) {
for (int j = 0; j < beanList.get(i).getInfoList().size(); j++) {
ExamCourseSection section = new ExamCourseSection(beanList.get(i).getInfoList().get(j));
list.add(section);
}
}
}
return list;
}
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
ExamInfoBean.ExamDataBean.InfoListBean bean = ((ExamCourseSection) adapter.getItem(position)).t;
ToastUtils.showShort(MainActivity.this, "选择了" + bean.getTitle());
}
}