一、为什么叫做RecyclerView?
1、不关心Item是否显示在正确的位置,如何显示;(LayoutManager)
2、不关心Item间如何分割;(ItemDecoration)
3、不关注Item增加与删除的动画效果;(ItemAnimator)
4、仅仅关注如何回收与复用View。
(1)通过设置LayoutManager的不同实例来设计RecyclerView的风格;
(2)通过设置ItemDecoration来设计RecyclerView的分割方式;
(3)通过设置ItemAnimator来设计RecyclerView的动画效果。
二、与RecyclerView相关的重要类
1、Adapter
2、ViewHolder
3、LayoutManager
4、ItemDecoration
5、ItemAnimator
三、RecyclerView能干什么?
1、ListView(LayoutManager)
2、GridView(LayoutManager)
3、横向ListView(LayoutManager)
4、横向GridView(LayoutManager)
5、瀑布流(LayoutManager)
6、定制Item增加与删除动画(ItemAnimator)
(1)实现ListView
1>写布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.qf.day_03.Main3Activity">
<android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
2>查找控件
private void initViews() { mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); }
3>获取数据
private void initDatas() {
mDatas = new ArrayList<>();
for (int i = 'A'; i <'z' ; i++) {
mDatas.add("" + (char) i);
}
}
4>自定义适配器
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
/**
* 适配器
*/
public class SimpleAdapter extends RecyclerView.Adapter<MyViewHolder> {
private LayoutInflater mInflater;
private Context mContext;
private List<String> mDatas;
public SimpleAdapter(Context context, List<String> datas) {
mContext = context;
mDatas = datas;
mInflater=LayoutInflater.from(mContext);
}
/**
* 创建ViewHolder
* @param parent
* @param viewType
* @return
*/
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView = mInflater.inflate(R.layout.item_single, parent, false);
MyViewHolder mViewHolder = new MyViewHolder(mView);
return mViewHolder;
}
/**
* 绑定数据
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mTextView.setText(mDatas.get(position));
}
/**
* 返回条目数
* @return
*/
@Override
public int getItemCount() {
return mDatas.size();
}
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView mTextView;
public MyViewHolder(View itemView) {
super(itemView);
mTextView= (TextView) itemView.findViewById(R.id.id_tv);
}
}
5>写Item布局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="#4f00"
android:layout_height="72dp">
<TextView
android:id="@+id/id_tv"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
6>设置适配器
mAdapter = new SimpleAdapter(this, mDatas); mRecyclerView.setAdapter(mAdapter);
7>为RecyclerView设置布局管理
//设置RecyclerView的布局管理 mRecyclerView.setLayoutManager(new LinearLayoutManager(Main3Activity.this,LinearLayoutManager.VERTICAL,false));
8>为RecyclerView的Item设置分割线
//设置RecyclerView的Item间的分割线 mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));
9>设置RecyclerView的Item间分割线的类
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* 设置RecyclerView的Item之间间隔的类
*/
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);
android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
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);
}
}
}
10>秒变GridView
mRecyclerView.setLayoutManager(new GridLayoutManager(Main3Activity.this,3));
//mRecyclerView.setLayoutManager(new GridLayoutManager(this,3,GridLayoutManager.HORIZONTAL,false));
(2)实现瀑布流布局
1>写布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.qf.day_03.Main3Activity">
<android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
2>查找控件
private void initViews() { mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); }
3>获取数据
private void initDatas() {
mDatas = new ArrayList<>();
for (int i = 'A'; i <'z' ; i++) {
mDatas.add("" + (char) i);
}
}
4>自定义适配器
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* 瀑布流适配器
*/
public class StaggeredAdapter extends RecyclerView.Adapter<StaggeredAdapter.MyViewHolder>{
private LayoutInflater mInflater;
private Context mContext;
private List<String> mDatas;
private List<Integer> mHeights;
public StaggeredAdapter(Context context, List<String> datas) {
mContext = context;
mDatas = datas;
mInflater=LayoutInflater.from(mContext);
mHeights = new ArrayList<>();
for (int i = 0; i < mDatas.size(); i++) {
mHeights.add((int) (100 + Math.random() * 300));
}
}
/**
* 创建ViewHolder
* @param parent
* @param viewType
* @return
*/
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView = mInflater.inflate(R.layout.item_single, parent, false);
MyViewHolder mViewHolder = new MyViewHolder(mView);
return mViewHolder;
}
/**
* 绑定数据
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
ViewGroup.LayoutParams mParams = holder.itemView.getLayoutParams();
mParams.height = mHeights.get(position);
holder.itemView.setLayoutParams(mParams);
holder.mTextView.setText(mDatas.get(position));
}
/**
* 返回条目数
* @return
*/
@Override
public int getItemCount() {
return mDatas.size();
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView mTextView;
public MyViewHolder(View itemView) {
super(itemView);
mTextView= (TextView) itemView.findViewById(R.id.id_tv);
}
}
}
5>写Item布局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="#4f00"
android:layout_height="72dp">
<TextView
android:id="@+id/id_tv"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
6>设置适配器
mAdapter = new StaggeredAdapter(this, mDatas); mRecyclerView.setAdapter(mAdapter);
7>为RecyclerView设置布局管理
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
(3)增加和删除Item的动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
(4)设置Item监听事件
4.1>在适配器中定义点击事件的接口
/**
* 设置点击事件的接口
*/
public interface OnItemClickListener{
void onItemClick(View view, int position);
void onItemLongClick(View view,int position);
}
private OnItemClickListener mOnItemClickListener;
public void setOnItemClickListener(OnItemClickListener listener) {
this.mOnItemClickListener = listener;
}
4.2>在适配器的onBindViewHolder方法中设置Item的点击事件
if (mOnItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取布局上的位置
int mPosition = holder.getLayoutPosition();
mOnItemClickListener.onItemClick(holder.itemView,mPosition);
}
});
//longclick
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
//获取布局上的位置(在有Item增加和减少的时候有用)
int mPosition = holder.getLayoutPosition();
mOnItemClickListener.onItemLongClick(holder.itemView,mPosition);
return false;
}
});
}
4.3>在Activity中为适配器设置点击事件
mAdapter.setOnItemClickListener(new SimpleAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(Main3Activity.this, "click:"+position, Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position) {
Toast.makeText(Main3Activity.this, "longclick:"+position, Toast.LENGTH_SHORT).show();
}
});
四、注意事项
1、ItemAnimator在使用的时候,不要使用notifyItemChanged(),而是要使用notifyItemInserted();和notifyItemMoved();。
2、RecyclerView没有提供Item的Click事件,所以需要手动在Adapter中提供ItemClick/longClick的回调。
3、RecyclerView可以实现在ListView、GridView、横向ListView、横向 GridView、瀑布流之间的灵活切换。
共同学习,写下你的评论
评论加载中...
作者其他优质文章