android design jar包,Android Study Material Design 二

本文详细介绍了如何使用RecyclerView实现复杂布局,包括ListView和GridView的混排效果。通过创建不同的ViewHolder和适配器,实现了多种类型布局的混排,并提供了优化Model的方法,适合Android开发者学习。
摘要由CSDN通过智能技术生成

本文目标

阅读完本文,你会get如下技能:使用RecyclerView实现复杂布局;

使用RecyclerView实现ListView以及GirdView混排效果;

通过优化Model加深了解通过RecyclerView实现混排效果。

希望通过不断get小技能,让你在Android路上一路畅通无堵~

废话不多说,开车~

一、使用RecyclerView实现复杂布局

首先我们先做一些基本操作,类似于控件放置,初始化(控件,模拟数据)等。

1.1 引用RecyclerView,填充布局1)Android Studio的小伙伴记得引入有关RecyclerView依赖;

2)Eclipse的小伙伴记得拷贝本地SDK下载包含的RecyclerView jar包即可。

布局放置如下:

放置好了一个RecyclerView,下面模拟数据时,来一个Model类。

1.2 设置Model类package com.materialdesignstudy.complexrecycler.itemone;/**

* Created by HLQ on 2017/10/22

*/public class DataModel {    // 状态标识位

public static final int TYPE_ONE = 1;    public static final int TYPE_TWO = 2;    public static final int TYPE_THREE = 3;    public int type; // 类型 针对某种样式文件 也就是布局

public int avatarColor; // 头像颜色

public String name; // 姓名

public String content; // 内容

public int contentColor; // 内容颜色}

1.3 定义item布局

如效果图一般,我们创建如下item布局文件:

item_type_one

item_type_two:

item_layout_three:

1.4 编写对应ViewHolder

由于我们的ViewHolder都需要构造以及数据绑定,由此,我们拓展一个封装ViewHolder类,让其他的ViewHolder直接集成此类即可。

定义封装ViewHolder类:package com.materialdesignstudy.complexrecycler.itemone;import android.support.v7.widget.RecyclerView;import android.view.View;/**

* ViewHolder封装类

* Created by HLQ on 2017/10/22

*/public abstract class TypeAbstractViewHolder extends RecyclerView.ViewHolder {    public TypeAbstractViewHolder(View itemView) {        super(itemView);

}    /**

* 数据绑定

*

* @param dataModel 数据源 由于我们模拟数据实体类暂定为DataModel 这里直接传入这个即可

*                  后期可根据项目实际需求去设置 也可以直接写为T

*/

public abstract void bindHolder(DataModel dataModel);

}

定义Item1对应的ViewHolder:package com.materialdesignstudy.complexrecycler.itemone;import android.graphics.Color;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import com.materialdesignstudy.R;/**

* Created by HLQ on 2017/10/22

*/public class TypeOneViewHolder extends TypeAbstractViewHolder {    public ImageView avatar;    public TextView name;    public TypeOneViewHolder(View itemView) {        super(itemView);        // 初始化控件

avatar = itemView.findViewById(R.id.avatar);

name = itemView.findViewById(R.id.name);        // 为了区分item 这里为item设置背景颜色

itemView.setBackgroundColor(Color.YELLOW);

}    @Override

public void bindHolder(DataModel dataModel) {        // 数据绑定

avatar.setBackgroundResource(dataModel.avatarColor);

name.setText(dataModel.name);

}

}

item2对应ViewHolder:package com.materialdesignstudy.complexrecycler.itemone;import android.graphics.Color;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import com.materialdesignstudy.R;/**

* Created by HLQ on 2017/10/22

*/public class TypeTwoViewHolder extends TypeAbstractViewHolder {    public ImageView avatar;    public TextView name, content;    public TypeTwoViewHolder(View itemView) {        super(itemView);

avatar = itemView.findViewById(R.id.avatar);

name = itemView.findViewById(R.id.name);

content = itemView.findViewById(R.id.content);

itemView.setBackgroundColor(Color.GRAY);

}    @Override

public void bindHolder(DataModel dataModel) {

avatar.setBackgroundResource(dataModel.avatarColor);

name.setText(dataModel.name);

content.setText(dataModel.content);

}

}

item3对应ViewHolder:package com.materialdesignstudy.complexrecycler.itemone;import android.graphics.Color;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import com.materialdesignstudy.R;/**

* Created by HLQ on 2017/10/22

*/public class TypeThreeViewHolder extends TypeAbstractViewHolder {    public ImageView avatar, contentImg;    public TextView name, content;    public TypeThreeViewHolder(View itemView) {        super(itemView);

avatar = itemView.findViewById(R.id.avatar);

name = itemView.findViewById(R.id.name);

content = itemView.findViewById(R.id.content);

contentImg = itemView.findViewById(R.id.contentImg);

itemView.setBackgroundColor(Color.BLUE);

}    @Override

public void bindHolder(DataModel dataModel) {

avatar.setBackgroundResource(dataModel.avatarColor);

name.setText(dataModel.name);

content.setText(dataModel.content);

contentImg.setBackgroundResource(dataModel.contentColor);

}

}

1.5 定义空的Adapter类,初始化控件、模拟数据package com.materialdesignstudy.complexrecycler.itemone;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import com.materialdesignstudy.R;import java.util.ArrayList;import java.util.List;/**

* 复杂布局实现

* Created by HLQ on 2017/10/22

*/public class ComplexOneActivity extends AppCompatActivity {    private RecyclerView mRecyclerView;    private OneAdapter mOneAdapter;    private int mColor[] = {android.R.color.holo_red_light,

android.R.color.holo_green_light,

android.R.color.holo_blue_light};    @Override

protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);

setContentView(R.layout.activity_complec_one);

initItem();

initData();

}    private void initData() {

List dataList = new ArrayList<>();        for (int i = 0; i < 20; i++) {            int type = (int) ((Math.random() * 3) + 1); // 随机type

DataModel dataModel = new DataModel();

dataModel.avatarColor = mColor[type - 1];

dataModel.type = type;

dataModel.name = "name" + i;

dataModel.content = "content:" + i;

dataModel.contentColor = mColor[(type + 1) % 3];

dataList.add(dataModel);

}

mOneAdapter.addList(dataList);

mOneAdapter.notifyDataSetChanged();

}    private void initItem() {

mRecyclerView = findViewById(R.id.id_recy);

mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

mOneAdapter = new OneAdapter(this);

mRecyclerView.setAdapter(mOneAdapter);

}

}

以上这些都是很easy的,这里就不过多说明了。关键内容如下,让我们一起瞅瞅Adapter又是如何编写的。

1.6 打造属于you的Adapter

首先,这里需要再次说明一点:getItemViewType():返回当前ItemView类型,而我们将会根据此类型进行相应的业务处理。

嗯那,就是这样,下面直接放出代码:package com.materialdesignstudy.complexrecycler.itemone;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.ViewGroup;import com.materialdesignstudy.R;import java.util.ArrayList;import java.util.List;/**

* Created by HLQ on 2017/10/22

*/public class OneAdapter extends RecyclerView.Adapter {    private LayoutInflater mLayoutInflater;    private List mDataList = new ArrayList<>();    public OneAdapter(Context context) {        this.mLayoutInflater = LayoutInflater.from(context);

}    public void addList(List dataModelList) {        this.mDataList.addAll(dataModelList);

}    @Override

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        // 通过获取不同的viewType,返回对应的ViewHolder以及引入的布局文件进行渲染,从而实现复杂布局实现

switch (viewType) {            case DataModel.TYPE_ONE:                return new TypeOneViewHolder(mLayoutInflater.inflate(R.layout.item_type_one, parent, false));            case DataModel.TYPE_TWO:                return new TypeTwoViewHolder(mLayoutInflater.inflate(R.layout.item_type_two, parent, false));            case DataModel.TYPE_THREE:                return new TypeThreeViewHolder(mLayoutInflater.inflate(R.layout.item_type_three, parent, false));

}        return null;

}    @Override

public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        // 由于子类ViewHolder继承自TypeAbstractViewHolder,这里可以直接通过强制转化去绑定数据

// 这也是我们为什么要对ViewHolder进行封装的一点优势

((TypeAbstractViewHolder) holder).bindHolder(mDataList.get(position));

}    @Override

public int getItemCount() {        return mDataList.size();

}    @Override

public int getItemViewType(int position) {        return mDataList.get(position).type;

}

}

到现在为止,我们已经完成了通过RecyclerView实现复杂布局,不信你可以运行下你现在的代码喽~

二、使用RecyclerView实现ListView以及GirdView混排效果

本小节内容主要关注于LayoutManager的setSpanSizeLookup()方法,下面对其进行简述。

> setSpanSizeLookup(): 主要使用这个方法来展示不同的 item 屏幕跨度

>

> * spanCount:在创建 GridLayoutManager 对象的时候构造方法需要传入这个参数,也就是设置每行排列 item 个数。

>

> * spanSize:在 setSpanSizeLookup() 方法中,这个方法返回的是当前位置的 item 跨度大小。

>

嗯哼,简单了解后,我们撸码呗`package com.materialdesignstudy.complexrecycler.itemtwo;import android.graphics.Rect;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.GridLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;import com.materialdesignstudy.R;import com.materialdesignstudy.complexrecycler.itemone.DataModel;import com.materialdesignstudy.complexrecycler.itemone.OneAdapter;import java.util.ArrayList;import java.util.List;/**

* 使用RecyclerView实现ListView+GridView混排效果

* create by heliquan at 2017年10月23日

* 重点关注setSpanSizeLookup即可 获取当前跨度

*/public class ComplexTwoActivity extends AppCompatActivity {    private RecyclerView mRecyclerView;    private OneAdapter mOneAdapter;    private int mColor[] = {android.R.color.holo_red_light,

android.R.color.holo_green_light,

android.R.color.holo_blue_light};    @Override

protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);

setContentView(R.layout.activity_complec_one);

initItem();

initData();

}    private void initData() {

List dataList = new ArrayList<>();        for (int i = 0; i < 30; i++) {            // 模拟不同itemType

int type;            if (i  15 && i < 20)) {

type = 1;

} else if (i  20) {

type = 2;

} else {

type = 3;

}

DataModel dataModel = new DataModel();

dataModel.avatarColor = mColor[type - 1];

dataModel.type = type;

dataModel.name = "name" + i;

dataModel.content = "content:" + i;

dataModel.contentColor = mColor[(type + 1) % 3];

dataList.add(dataModel);

}

mOneAdapter.addList(dataList);

mOneAdapter.notifyDataSetChanged();

}    private void initItem() {

mRecyclerView = findViewById(R.id.id_recy);        // 更换显示布局样式为GirdLayoutManager

final GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);

gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {            @Override

public int getSpanSize(int position) {                // 获取当前位置下的ItemViewType

int type = mRecyclerView.getAdapter().getItemViewType(position);                // 由于item1和item2可以正常显示 而item3需要横跨2列

// 所以需要在这里对item3进行单独处理

if (type == DataModel.TYPE_THREE) {                    return gridLayoutManager.getSpanCount(); // item3需要横跨2列

} else {                    return 1;

}

}

});

mRecyclerView.setLayoutManager(gridLayoutManager);

mOneAdapter = new OneAdapter(this);

mRecyclerView.setAdapter(mOneAdapter);        // 为了显示效果更好 在此添加分割线

mRecyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {            @Override

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {

GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams) view.getLayoutParams();                int spanSize = layoutParams.getSpanSize(); // 获取当前位置的 item 跨度大小

int spanIndex = layoutParams.getSpanIndex(); // 获取每行排列 item 个数

outRect.top = 20;                // 如果当前跨度不等于当前索引 表示当前不属于item3

if (spanSize != gridLayoutManager.getSpanCount()) { // 针对item1,item2做分割线处理

if (spanIndex == 1) {

outRect.left = 10;

} else {

outRect.right = 10;

}

}

}

});

}

}

其实这部分的关键点就是在于那个方法,大家有时间可以细致了解。

好了,到现在为止,第二小节也over了。Nice。

三、复杂Model应对之策

以上俩点都是基于相同的Model,那么在实际开发中,我们Model也许各不相同,那么这时候该如何处理呢?

这里为大家提供下思路,可以顺着延伸下。改造ViewHolder封装类,之前我们直接采用固定Model,而今替换T即可,而对应子类ViewHolder继承时需要指定Model类型;

Adapter中却需要记录当前itemType对应包含List.size()以及itemType对应类型。原因在于我们需要将数据进行组合,因为后台的数据不可能会按照我们所想的来,只能进行二次拼接。

关键内容如上,下面就简单贴出关键代码,完整代码请在下方查看GitHub。

3.1 改造后的ViewHolder封装类package com.materialdesignstudy.complexrecycler.itemthree;import android.support.v7.widget.RecyclerView;import android.view.View;import com.materialdesignstudy.complexrecycler.itemone.DataModel;/**

* Created by HLQ on 2017/10/22

*/public abstract class TypeAbstractViewHolder extends RecyclerView.ViewHolder {    public TypeAbstractViewHolder(View itemView) {        super(itemView);

}    public abstract void bindHolder(T dataModel);

}

3.2 改造后的数据初始化private void initData() {

List oneList = new ArrayList<>();        for (int i = 0; i < 10; i++) {

DataModelOne dataModel = new DataModelOne();

dataModel.name = "name" + i;

dataModel.avatatColor = mColor[0];

oneList.add(dataModel);

}

List twoList = new ArrayList<>();        for (int i = 0; i < 10; i++) {

DataModelTwo dataModel = new DataModelTwo();

dataModel.name = "name" + i;

dataModel.avatatColor = mColor[1];

dataModel.content = "content:" + i;

twoList.add(dataModel);

}

List threeList = new ArrayList<>();        for (int i = 0; i < 10; i++) {

DataModelThree dataModel = new DataModelThree();

dataModel.name = "name" + i;

dataModel.avatatColor = mColor[2];

dataModel.content = "content:" + i;

dataModel.contentColor = mColor[2];

threeList.add(dataModel);

}

mOneAdapter.addList(oneList,twoList,threeList);

mOneAdapter.notifyDataSetChanged();

}

3.3 改造后的Adapterpackage com.materialdesignstudy.complexrecycler.itemthree;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.ViewGroup;import com.materialdesignstudy.R;import com.materialdesignstudy.complexrecycler.itemone.DataModel;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/**

* Created by HLQ on 2017/10/22

*/public class TwoAdapter extends RecyclerView.Adapter {    public static final int TYPE_ONE = 1;    public static final int TYPE_TWO = 2;    public static final int TYPE_THREE = 3;    private LayoutInflater mLayoutInflater;    private List mTypes = new ArrayList<>(); // 存放type

private Map mPositions = new HashMap<>(); // 存放type下包含数据itemCount

private List mOneList = new ArrayList<>();    private List mTwoList = new ArrayList<>();    private List mThreeList = new ArrayList<>();    public TwoAdapter(Context context) {        this.mLayoutInflater = LayoutInflater.from(context);

}    public void addList(List oneList, List twoList, List threeList) {

addListByType(TYPE_ONE, oneList);

addListByType(TYPE_TWO, twoList);

addListByType(TYPE_THREE, threeList);        this.mOneList = oneList;        this.mTwoList = twoList;        this.mThreeList = threeList;

}    private void addListByType(int type, List list) {

mPositions.put(type, mTypes.size());        for (int i = 0; i < list.size(); i++) {

mTypes.add(type);

}

}    @Override

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        switch (viewType) {            case DataModel.TYPE_ONE:                return new TypeOneViewHolder(mLayoutInflater.inflate(R.layout.item_type_one, parent, false));            case DataModel.TYPE_TWO:                return new TypeTwoViewHolder(mLayoutInflater.inflate(R.layout.item_type_two, parent, false));            case DataModel.TYPE_THREE:                return new TypeThreeViewHolder(mLayoutInflater.inflate(R.layout.item_type_three, parent, false));

}        return null;

}    @Override

public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        int viewType = getItemViewType(position);        int realPosition = position - mPositions.get(viewType);        switch (viewType) {            case DataModel.TYPE_ONE:

((TypeAbstractViewHolder) holder).bindHolder(mOneList.get(realPosition));                break;            case DataModel.TYPE_TWO:

((TypeAbstractViewHolder) holder).bindHolder(mTwoList.get(realPosition));                break;            case DataModel.TYPE_THREE:

((TypeAbstractViewHolder) holder).bindHolder(mThreeList.get(realPosition));                break;

}

}    @Override

public int getItemCount() {        return mTypes.size();

}    @Override

public int getItemViewType(int position) {        return mTypes.get(position);

}

}

到此,RecyclerView实现复杂布局结束了,还是希望大家有时间多看多敲,多去理解。

GitHub地址

学习地址

结束

我们沿着前人的路慢慢前行,只要坚持,就会有收获,可能目前的现状有些不尽人意,但是只要坚持下去,希望的曙光始终会照亮前行的路~

致自己,致坚持看完本文的你~加油~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值