使用RecyclerView实现两种不同Item布局
程序员文章站
2022-03-13 17:05:29
...
先上图看看效果:
实现中间一个轮播图,下面多个相同Item的布局。我们都知道ListView有一个方法可以添加头布局,但是RecyclerView并没有提供这样的方法。那么怎么来实现呢???
一、Item布局代码,这里我分了两个Item
轮播图布局:
<?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="wrap_content"
>
<!--<FrameLayout-->
<!--android:id="@+id/ff_viewpager"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="180dp">-->
<!--<android.support.v4.view.ViewPager-->
<!--android:id="@+id/viewpager"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--/>-->
<!--<LinearLayout-->
<!--android:id="@+id/ll_dot"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="20dp"-->
<!--android:orientation="horizontal"-->
<!--android:layout_gravity="bottom|center"-->
<!--android:gravity="center"-->
<!-->-->
<!--</LinearLayout>-->
<!--</FrameLayout>-->
<com.jude.rollviewpager.RollPagerView
android:id="@+id/rollpagerview"
android:layout_width="match_parent"
android:layout_height="180dp">
</com.jude.rollviewpager.RollPagerView>
</RelativeLayout>
可以看到,我最开始是准备使用View Pager来实现我的轮播图的,但是太浪费我的时间了。现在有很多很成熟的轮播图开源框架了,为什么不用呢!这里主要是讲RecyclerView的实现,所以并不会涉及这个轮播图实现的方法,如果有需要可以在我的博客里面找找,我在之后也会写一篇博客来讲一下RollPagerView轮播图框架的简单使用方法。
相同Item的布局代码:
<?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="wrap_content"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="120dp">
<ImageView
android:id="@+id/rcitem_icon"
android:layout_width="130dp"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_centerVertical="true"
android:src="@mipmap/ic_launcher"
/>
<RelativeLayout
android:id="@+id/rcitem_ll_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/rcitem_icon"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
>
<TextView
android:id="@+id/rcitem_text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="真的会笑死吗?"
android:textColor="@color/dataTextColor"
android:textSize="15dp"
android:layout_marginTop="30dp"
android:layout_marginBottom="10dp"
/>
<RelativeLayout
android:id="@+id/rcitem_ll_text_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/rcitem_text_title"
>
<TextView
android:id="@+id/rcitem_text_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2017-09-12"
android:textSize="10dp"
/>
<TextView
android:id="@+id/rcitem_text_dividingline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="|"
android:textColor="@color/dataTextColor"
android:textSize="10dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_toRightOf="@id/rcitem_text_time"
/>
<TextView
android:id="@+id/rcitem_text_readcount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="阅读:16642"
android:textColor="@color/dataTextColor"
android:textSize="10dp"
android:layout_toRightOf="@id/rcitem_text_dividingline"
/>
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
二、Holder类的的实现
abstract 父类的实现:
public abstract class TypeAbstractViewHolder extends RecyclerView.ViewHolder{
public TypeAbstractViewHolder(View itemView) {
super(itemView);
}
public void bindModel(SlideshowBean slideshowBeen, Context context){
}
public void bindModel(List<SlideshowBean> slideshowBeenList, Context context){
}
}
可以看到我定义了一个abstract 的类来继承了RecyclerView.ViewHolder,然后我添加了两个非抽象的类,用来绑定数据,子类可以选择实现或者不实现。
子类HolderOne:
package vunke.com.android.interviewtest.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.bumptech.glide.Glide;
import com.jude.rollviewpager.RollPagerView;
import com.jude.rollviewpager.hintview.ColorPointHintView;
import java.util.ArrayList;
import java.util.List;
import vunke.com.android.interviewtest.R;
import vunke.com.android.interviewtest.adapter.SlideshowAdapter;
import vunke.com.android.interviewtest.model.SlideshowBean;
/**
* Created by 大家都说名字长不会被发现 on 2017/9/14.
*/
public class TypeOneHolder extends TypeAbstractViewHolder{
public RollPagerView rollPagerView;
// public ViewPager viewPager;
public LinearLayout linearLayout;
private List<View> viewList = new ArrayList<View>();
public TypeOneHolder(View itemView) {
super(itemView);
//找到轮播View
rollPagerView = (RollPagerView) itemView.findViewById(R.id.rollpagerview);
}
//在这个方法中实现设置数据的操作
@Override
public void bindModel(List<SlideshowBean> slideshowBeenList, Context context) {
for (int i = 0;i < slideshowBeenList.size();i++){
//获取集合数据
SlideshowBean slideshowBeen = slideshowBeenList.get(i);
//创建一个View集合
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
//获取图片地址
String picUrl = slideshowBeen.getPicUrl();
//创建一个Imageview对象
ImageView imageView = new ImageView(context);
//设置ImageView的宽高
imageView.setLayoutParams(params);
//加载图片
Glide.with(context).load(picUrl).into(imageView);
//将ImageView添加到集合当中
viewList.add(imageView);
//设置数据适配器
rollPagerView.setPlayDelay(2000);
rollPagerView.setHintView(new ColorPointHintView(context, Color.YELLOW,Color.WHITE));
SlideshowAdapter slideshowAdapter = new SlideshowAdapter(viewList);
rollPagerView.setAdapter(slideshowAdapter);
}
}
}
子类HolderTwo:
package vunke.com.android.interviewtest.view;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.List;
import vunke.com.android.interviewtest.R;
import vunke.com.android.interviewtest.model.SlideshowBean;
/**
* Created by 大家都说名字长不会被发现 on 2017/9/14.
*/
public class TypeTwoHolder extends TypeAbstractViewHolder{
public ImageView rcitem_icon;
public TextView rcitem_text_title;
public TextView rcitem_text_time;
public TextView rcitem_text_readcount;
public TypeTwoHolder(View itemView) {
super(itemView);
rcitem_icon = (ImageView) itemView.findViewById(R.id.rcitem_icon);
rcitem_text_title = (TextView) itemView.findViewById(R.id.rcitem_text_title);
rcitem_text_time = (TextView) itemView.findViewById(R.id.rcitem_text_time);
rcitem_text_readcount = (TextView) itemView.findViewById(R.id.rcitem_text_readcount);
}
@Override
public void bindModel(SlideshowBean slideshowBeen, Context context) {
//获取字段数据
String chineseTitle = slideshowBeen.getChineseTitle();
String picUrl = slideshowBeen.getPicUrl();
String creatTime = slideshowBeen.getCreatTime();
String readCount = slideshowBeen.getReadCount();
//给Holder绑定数据
Glide.with(context).load(picUrl).into(rcitem_icon);
rcitem_text_title.setText(chineseTitle);
rcitem_text_time.setText(creatTime);
//组拼字符串
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(readCount);
stringBuilder.insert(0,"阅读:");
rcitem_text_readcount.setText(stringBuilder.toString());
}
}
可以看到Holder中的操作都是一样,找到控件并设置数据。
三、Adapter的实现
package vunke.com.android.interviewtest.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import vunke.com.android.interviewtest.R;
import vunke.com.android.interviewtest.model.SlideshowBean;
import vunke.com.android.interviewtest.view.TypeAbstractViewHolder;
import vunke.com.android.interviewtest.view.TypeOneHolder;
import vunke.com.android.interviewtest.view.TypeTwoHolder;
/**
* Created by 大家都说名字长不会被发现 on 2017/9/14.
*/
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private Context context;
private List<SlideshowBean> slideshowBeanList;
private int HEADER_TYPE = 1;
private int BONTOM_TYPE = 2;
public RecyclerViewAdapter(Context context,List<SlideshowBean> slideshowBeenList) {
this.context = context;
this.slideshowBeanList = slideshowBeenList;
}
//这里很重要
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//这里需要注意,LayoutInflater.from需要提取出来,不能在case里面每case一次去资源文件中去找布局,因为这里这里是比较消耗内存资源的。
LayoutInflater layoutInflater = LayoutInflater.from(context);
//这里可以看到我们根据不同的ViewType来返回不同的布局
switch (viewType){
case 1:
//轮播图View
View viewOne = layoutInflater.inflate(R.layout.mainfragment_recyclerviewpager_item, parent, false);
TypeOneHolder oneHolder = new TypeOneHolder(viewOne);
return oneHolder;
case 2:
//相同Item布局View
View viewTwo = layoutInflater.inflate(R.layout.mainfragment_recyclerviewcontent_item, parent, false);
TypeTwoHolder twoHolder = new TypeTwoHolder(viewTwo);
return twoHolder;
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//根据Position去调用不同的Holder类设置数据
if (position == 0){
((TypeAbstractViewHolder)holder).bindModel(slideshowBeanList,context);
}else{
((TypeAbstractViewHolder)holder).bindModel(slideshowBeanList.get(position-1),context);//在这里我将传递过来的position-1,这样数据就正常了
}
}
//返回显示Item的数量,我们集合大小只有4,但是我们要显示显示5个Item
@Override
public int getItemCount() {
return slideshowBeanList.size()+1;//我在Size的基础上+1
}
//这里也很重要,这里我们需要做一个判断
@Override
public int getItemViewType(int position) {
//当position为0的时候,那个我们需要显示的是轮播图,所以我定义两个常量来标识
if (position == 0){
//==0的情况
return HEADER_TYPE;
}else {
//!==0的时候就返回全是相同的Item
return BONTOM_TYPE;
}
}
}
这种方法并不是很好,因为影响性能。这里我推荐鸿洋大神的实现方法,如果可以看懂就使用他那种方法,如果看不懂,那就用我这种方法吧。