您的位置:首页 > 其它

RecyclerView详细介绍-----多item布局(三)

2016-11-11 21:17 309 查看

1.前言

前面两篇文章主要介绍了recyclerview的基本使用,接下来介绍复杂一点的需求。

我们之前用listview的时候肯定遇到itemType>1的时候,我们定义多套item布局,借助getItemViewType()实现多套布局。但是如果像淘宝首页,上面是listview的一个一个item,下面确是一个GridView的话,我们如何实现呢?当然之前有人会把GridView用ListView来实现,及一个Listview的item来代替GridView的两个item,只是数据集我们要自己做处理,总之很麻烦。现在有了recyclerview,这些就变得很简单。

2.实现效果



上图既有listview的列表,下方又有gridview,如何实现呢?

3.具体实现过程:

1)跟listview一样,recyclerview借助getItemViewType(int position)实现多套布局判断,然后根据itemtype实现多套布局的创建跟赋值,具体代码如下:

public class MultiItemAdapter extends RecyclerView.Adapter<MultiItemAdapter.ViewHolder> {

public static final int ONE_TEXT_VIEW_TYPE = 0;

public static final int TWO_TEXT_VIEW_TYPE = 1;

public static final int GRID_VIEW_TYP = 2;

private ArrayList<Person> data;

private Context context;

public MultiItemAdapter(Context context, ArrayList<Person> data) {
this.data = data;
this.context = context;
}

@Override
public int getItemViewType(int position) {
if (data.get(position).getType() == ONE_TEXT_VIEW_TYPE) {
return ONE_TEXT_VIEW_TYPE;
} else if (data.get(position).getType() == TWO_TEXT_VIEW_TYPE) {
return TWO_TEXT_VIEW_TYPE;
} else if (data.get(position).getType() == GRID_VIEW_TYP) {
return GRID_VIEW_TYP;
}else {
return  ONE_TEXT_VIEW_TYPE;
}
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View itemView = null;
switch (viewType) {
case ONE_TEXT_VIEW_TYPE:
itemView = LayoutInflater.from(this.context).inflate(R.layout.multi_item_one, null);
break;
case TWO_TEXT_VIEW_TYPE:
itemView = LayoutInflater.from(this.context).inflate(R.layout.multi_item_two, null);
break;
case GRID_VIEW_TYP:
itemView = LayoutInflater.from(this.context).inflate(R.layout.multi_item_three, null);
break;
}
return new ViewHolder(itemView);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
int itemViewType = getItemViewType(position);
switch (itemViewType) {
case ONE_TEXT_VIEW_TYPE:
showOneTextView(holder, position);
break;
case TWO_TEXT_VIEW_TYPE:
showTwoTextView(holder, position);
break;
case GRID_VIEW_TYP:
showGridView(holder, position);
break;
}
}

/**
* 赋值
*
* @param holder
* @param position
*/
private void showOneTextView(ViewHolder holder, int position) {
TextView textview = (TextView) holder.findViewById(R.id.item_text);
textview.setText(data.get(position).getName());
}

private void showTwoTextView(ViewHolder holder, int position) {
TextView item_text_one = (TextView) holder.findViewById(R.id.item_text_one);
TextView item_text_two = (TextView) holder.findViewById(R.id.item_text_two);
item_text_one.setText(data.get(position).getName());
item_text_two.setText(data.get(position).getType() + "");
}

private void showGridView(ViewHolder holder, int position) {
TextView textview = (TextView) holder.findViewById(R.id.item_text);
textview.setText(data.get(position).getName());
}

@Override
public int getItemCount() {
return data == null ? 0 : data.size();
}

//自定义的ViewHolder,持有每个Item的的所有界面元素
public static class ViewHolder extends RecyclerView.ViewHolder {

private Map<Integer, View> mCacheView;

public ViewHolder(View itemView) {
super(itemView);
mCacheView = new HashMap<>();
}

public View findViewById(int resId) {
View view;
if (mCacheView.containsKey(resId)) {
view = mCacheView.get(resId);
} else {
view = itemView.findViewById(resId);
mCacheView.put(resId, view);
}
return view;
}
}
}


这里需要说一下,ViewHolder 我们这边统一做了封装,抽出findViewById方法,内部做了缓存处理,而简单的具体实例化交给各个具体item,方便使用。

2)我们知道普通的listview只有一列,而gridview是多列,recyclerview如何做到呢?其实是用到了layoutManager.setSpanSizeLookup方法.

public class MultiItemActivity extends AppCompatActivity {

/**
* view
*/
private RecyclerView recyclerView;

/**
* 用来确定每一个item如何进行排列摆放,何时展示和隐藏
*/
private GridLayoutManager layoutManager;

/**
* 适配器
*/
private MultiItemAdapter mAdapter;

private ArrayList<Person> data = new ArrayList<Person>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initView();
initData();
}

/**
* 初始化布局组件
*/
private void initView() {
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
//创建默认的线性LayoutManager
layoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(layoutManager);
//如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
recyclerView.setHasFixedSize(true);
}

/**
* 初始化数据
*/
private void initData() {
for (int i = 0; i < 10; i++) {
Person person = new Person();
person.setName(i + "abc" + 1);
if (i < 3) {
person.setType(MultiItemAdapter.ONE_TEXT_VIEW_TYPE);
} else if (i < 6) {
person.setType(MultiItemAdapter.TWO_TEXT_VIEW_TYPE);
} else {
person.setType(MultiItemAdapter.GRID_VIEW_TYP);
}
data.add(person);
}
//创建并设置Adapter
mAdapter = new MultiItemAdapter(this, data);
recyclerView.setAdapter(mAdapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (mAdapter.getItemViewType(position)
== MultiItemAdapter.GRID_VIEW_TYP) {
return 1;
} else {
return 2;
}
}
});
}
}


在上面的基本设置中,我们的spanCount为2,setSpanSizeLookup可以让你根据position来设置spanCount,spanCount可以想象成布局里面的weight(比重),原先通过layoutManager = new GridLayoutManager(this, 2);设置成一个item占比为2,那么如果根据setSpanSizeLookup设置的spanCount为1的话,那么一行就是2列,这样才能满足一行的比重为2;如果spanCount为2的话,则说明一行一列。

通过上面的代码,我们就轻松的实现了多itemtype甚至listview跟gridview混合的情况。

4.完整代码下载地址如下所示:

demo下载链接

欢迎一起交流讨论

群号:469890293
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息