您的位置:首页 > 其它

RecyclerView的用法

2017-02-06 19:12 183 查看
回顾ListView

概述

一句话:在有限的空间中显示大量的列表集合的控件


ListView的使用步骤(question)

1.数据集

2.适配器Adapter

备注:其实ListView是一个MVC的模式,

M--Model 数据集
V--View ListView
C--Controller 适配器


RecyclerView的介绍

概述

官方的介绍,该控件用于在有限的窗口中展示大量数据集。正如我们刚才介绍ListView和之前所学过的ListView

Google在2014年I/O大会上提出新的用于取代ListView的组件,相比ListView而言,它更加强大,而且非常灵活

原理以及结构图

官方结构图



RecyclerView描述

与其它的View不一样的地方是RecyclerView不负责子view的展现和布局工作。即子view的位置、大小等都不由RecyclerView自己负责。它所关注的是子view的回收与复用,专注于性能的提升。而其它的工作如布局、子view的布局、子view的装饰、子view的动画都交给了其内部类来负责,下表展示了几个关键的内部类和它们的用途。

RecyclerView的相关类



RecyclerView的初体验

显示类似于ListView的列表

1.首先要用这个控件,你需要在gradle文件中添加包的引用

compile 'com.android.support:recyclerview-v7:21.0.3'


2.在布局文件中用使用它

<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>


3.设置适配器

(1) 准备适配器继承RecyclerView.Adapter

(2)RecyclerView.Adapter中默认必须有ViewHolder,需要在Adapter中写一个内部类继承RecyclerView.ViewHolder

示例代码如下:

* step:
* 1. 继承RecyclerView.Adapter<VH extends ViewHolder>
* 2. 在这个Adapter中写一个类继承RecyclerView.ViewHolder,并且传入Adapter的泛型
* 3. 实现 三个抽象方法
* getItemCount
* onCreateViewHolder
* onBindViewHolder
* 4. 重写构造方法,参数传入 上下文Context 数据集
* *************************************************************
*/
public class LikeListAdapter extends RecyclerView.Adapter<LikeListAdapter.MyViewHolder> {
private List<String> mDatas = new ArrayList<>();
private Context mContext;
private LayoutInflater mInflater;

public LikeListAdapter(Context context, List<String> datas) {
this.mInflater = LayoutInflater.from(context);
mDatas = datas;
this.mContext = context;
}

//返回RecyclerView总共有多少条
@Override
public int getItemCount() {
return mDatas == null ? 0 : mDatas.size();
}

//初始化布局,创建ViewHolder
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//1. 初始化item的布局
View view = mInflater.inflate(R.layout.item_likelist, parent, false);
//2. 创建出来ViewHolder对象
MyViewHolder myViewHolder = new MyViewHolder(view);

return myViewHolder;
}

//绑定ViewHolder中的控件的数据
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
String str = mDatas.get(position);

holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//                Toast.makeText(mContext, "pos:" + position, Toast.LENGTH_SHORT).show();
if (mListener != null) {
mListener.onItemClick(position, holder.itemView);
}
}
});

//瀑布流展示
//        Random random = new Random();
//        int height = random.nextInt(100) + 100;
//        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);
//        ViewGroup.LayoutParams layoutParams = holder.tv_test.getLayoutParams();
//        layoutParams.height = height;
//        holder.tv_test.setLayoutParams(layoutParams);

holder.tv_test.setText(str);
}

public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView tv_test;

public MyViewHolder(View itemView) {
super(itemView);
tv_test = (TextView) itemView.findViewById(R.id.tv_test);
}
}

//增加一条数据
public void insertData(int pos, String data) {
mDatas.add(pos, data);

notifyItemInserted(pos);
}

//删除一条数据
public void removeData(int pos) {
mDatas.remove(pos);
notifyItemRemoved(pos);
}

public interface OnItemClickListener {
void onItemClick(int pos, View view
4000
);
}

private OnItemClickListener mListener;

public void setOnItemClickListener(OnItemClickListener listener) {
this.mListener = listener;
}

}


(4)设置布局管理器LayoutManager

LinearLayoutManager线性布局

GridLayoutManager网格布局

StaggeredGridLayoutManager瀑布流布局

public class LikeListActivity extends AppCompatActivity {

private List<String> mDatas = new ArrayList<>();

private RecyclerView mRecyclerView;
private Button btn_add;
private Button btn_remove;
private LikeListAdapter mAdapter;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_likelist);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
btn_add = (Button) findViewById(R.id.btn_add);
btn_remove = (Button) findViewById(R.id.btn_remove);

//1.准备数据集
for (int i = 0; i < 50; i++) {
mDatas.add("data:" + i);
}

//2.初始化Adapter
mAdapter = new LikeListAdapter(this, mDatas);

mRecyclerView.setAdapter(mAdapter);

//3.创建出来LayoutManager

//3.1 线性布局: 第二个参数是 列表展现的方向,有竖直的LinearLayoutManager.VERTICAL 和 水平的LinearLayoutManager.HORIZONTAL
// 第三个参数: 是否 从最后展示
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
//3.2 网格布局:  参数2是 表示这个网格布局的列数 或者行数
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false);
//3.3 瀑布流布局
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(linearLayoutManager);

//给RecyclerView增加一些动画效果
//        mRecyclerView.setItemAnimator(new DefaultItemAnimator());

//1. build.gradle中引入 : compile 'jp.wasabeef:recyclerview-animators:2.2.5'
//2. 添加动画效果 :  setItemAnimator(动画效果的类例如: SlideInLeftAnimator, SlideInRightAnimator);
mRecyclerView.setItemAnimator(new LandingAnimator());
//3. 改变动画的时长:  有四个:
// recyclerView.getItemAnimator().setAddDuration(1000);
//recyclerView.getItemAnimator().setRemoveDuration(1000);
//recyclerView.getItemAnimator().setMoveDuration(1000);
//recyclerView.getItemAnimator().setChangeDuration(1000);

mRecyclerView.getItemAnimator().setAddDuration(3000);
//增加一条数据
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAdapter.insertData(1, "新增加的数据");
}
});
//删除一条数据
btn_remove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAdapter.removeData(1);
}
});

//        mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));

mAdapter.setOnItemClickListener(new LikeListAdapter.OnItemClickListener() {
@Override
public void onItemClick(int pos, View view) {
Toast.makeText(LikeListActivity.this, "pos::" + pos, Toast.LENGTH_SHORT).show();
}
});
}
}


设置动画效果

三方地址

https://github.com/gabrielemariotti/RecyclerViewItemAnimators

具体操作如下:

//给RecyclerView增加一些动画效果
//        mRecyclerView.setItemAnimator(new DefaultItemAnimator());

//1. build.gradle中引入 : compile 'jp.wasabeef:recyclerview-animators:2.2.5'
//2. 添加动画效果 :  setItemAnimator(动画效果的类例如: SlideInLeftAnimator, SlideInRightAnimator);
mRecyclerView.setItemAnimator(new LandingAnimator());
//3. 改变动画的时长:  有四个:
// recyclerView.getItemAnimator().setAddDuration(1000);
//recyclerView.getItemAnimator().setRemoveDuration(1000);
//recyclerView.getItemAnimator().setMoveDuration(1000);
//recyclerView.getItemAnimator().setChangeDuration(1000);


设置分割线

具体操作如下:

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};

public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

private Drawable mDivider;

private int mOrientation;

public DividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}

public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}

@Override
public void onDraw(Canvas c, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}

public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();

final int childCount = parent.getChildCount();

for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}

public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();

final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}

@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}


RecyclerView的高级用法(多布局的实现)

MultiAdapter写法如下

* step:
* 1. 有几种类型,就写几个ViewHolder, Adapter中的泛型传入RecyclerView.ViewHolder
* 2. 有几种类型,就写几种int 类型常量, 一般从0开始
* 3. 覆写方法getItemViewType(int pos) , 返回当前位置到底是那种类型
* 4. 通过onCreateViewHolder(ViewGroup parent, int viewType)  中的 第二个参数 viewType 去创建不同的ViewHolder对象
* *************************************************************
*/
public class MultiAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public Context mContext;
public LayoutInflater mInflater;
public List<HouseBean.DataBean> mDatas;

//有几种类型 就写一个常量去标记
private static final int TYPE_SPECIAL = 0;
private static final int TYPE_NORMAL = 1;
private static final int TYPE_BIG = 2;

public MultiAdapter
cd42
(Context context, List<HouseBean.DataBean> datas) {
this.mContext = context;
this.mInflater = LayoutInflater.from(context);
this.mDatas = datas;
}

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

//返回当前位置的类型
@Override
public int getItemViewType(int position) {
String type = mDatas.get(position).type;
if ("100".equals(type)) {
return TYPE_SPECIAL;
} else if ("0".equals(type)) {
return TYPE_NORMAL;
} else {
return TYPE_BIG;
}
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_SPECIAL:
//                View view = mInflater.inflate(R.layout.item_multi_special, parent, false);
//                return new SpecialHolder(view);
return new SpecialHolder(mInflater.inflate(R.layout.item_multi_special, parent, false));
case TYPE_NORMAL:
return new NormalHolder(mInflater.inflate(R.layout.item_multi_normal, parent, false));
case TYPE_BIG:
return new BigImgHolder(mInflater.inflate(R.layout.item_multi_big, parent, false));
}
return null;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int itemViewType = getItemViewType(position);
HouseBean.DataBean bean = mDatas.get(position);
switch (itemViewType) {
case TYPE_SPECIAL:
SpecialHolder specialHolder = (SpecialHolder) holder;
specialHolder.tv_title.setText(bean.title);
specialHolder.tv_desc.setText(bean.summary);
Picasso.with(mContext)
.load(bean.groupthumbnail)
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(specialHolder.iv_special);
break;
case TYPE_NORMAL:
NormalHolder normalHolder = (NormalHolder) holder;
normalHolder.tv_title.setText(bean.title);
normalHolder.tv_desc.setText(bean.summary);
Picasso.with(mContext)
.load(bean.groupthumbnail)
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(normalHolder.iv_normal);
break;
case TYPE_BIG:
BigImgHolder bigImgHolder = (BigImgHolder) holder;
bigImgHolder.tv_title.setText(bean.title);
Picasso.with(mContext)
.load(bean.groupthumbnail)
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(bigImgHolder.iv_big);
break;
}
}

class SpecialHolder extends RecyclerView.ViewHolder {
private ImageView iv_special;
private TextView tv_title;
private TextView tv_desc;

public SpecialHolder(View itemView) {
super(itemView);

iv_special = (ImageView) itemView.findViewById(R.id.iv_show);
tv_title = (TextView) itemView.findViewById(R.id.tv_title);
tv_desc = (TextView) itemView.findViewById(R.id.tv_desc);
}
}

class NormalHolder extends RecyclerView.ViewHolder {
private ImageView iv_normal;
private TextView tv_title;
private TextView tv_desc;

public NormalHolder(View itemView) {
super(itemView);
iv_normal = (ImageView) itemView.findViewById(R.id.iv_show);
tv_title = (TextView) itemView.findViewById(R.id.tv_title);
tv_desc = (TextView) itemView.findViewById(R.id.tv_desc);
}
}

class BigImgHolder extends RecyclerView.ViewHolder {
private ImageView iv_big;
private TextView tv_title;

public BigImgHolder(View itemView) {
super(itemView);
iv_big = (ImageView) itemView.findViewById(R.id.iv_big);
tv_title = (TextView) itemView.findViewById(R.id.tv_title);
}
}
}


MultiActivity写法如下:

* step:
* 1. 从网络获得到数据源
* <p>
* 2. 准备适配器
* <p>
* 3. 布局管理器
* *************************************************************
*/
public class MultiActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;

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

mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);

RequestQueue requestQueue = Volley.newRequestQueue(this);
StringRequest request = new StringRequest(Request.Method.GET, UrlString.URL_SEEHOUSE, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//TODO 得到数据 解析 显示到RecyclerView

HouseBean houseBean = new Gson().fromJson(response, HouseBean.class);

mRecyclerView.setAdapter(new MultiAdapter(MultiActivity.this, houseBean.data));

mRecyclerView.setLayoutManager(new LinearLayoutManager(MultiActivity.this));
}
}, null);
requestQueue.add(request);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  listview