RecycleView
那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。
- 你想要控制其显示的方式,请通过布局管理器LayoutManager
- 你想要控制Item间的间隔(可绘制),请通过ItemDecoration
- 你想要控制Item增删的动画,请通过ItemAnimator
- 你想要控制点击、长按事件,请自己写(擦,这点尼玛。)
//设置布局管理器
mRecyclerView.setLayoutManager(layout);
//设置adapter
mRecyclerView.setAdapter(adapter)
//设置Item增加、移除动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.HORIZONTAL_LIST));
RecyclerView.LayoutManager吧,这是一个抽象类,好在系统提供了3个实现类:
- LinearLayoutManager 现行管理器,支持横向、纵向。
- GridLayoutManager 网格布局管理器
- StaggeredGridLayoutManager 瀑布就式布局管理器
http://blog.****.net/lmj623565791/article/details/45059587;
推荐【张鸿洋的博客】
demo一粒 注释相当的全面 以供以后参考使用
RecycleAdapter
- package com.example.ban.myapplication;
- 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;
- /**
- * Created by ban on 2016/11/24.
- * <p>
- * 创建适配器类继承RecycleView的Adapter,步骤为:
- * <p>
- * 1、继承RecyclerView.Adapter,并且在Adapter里面声明ViewHolder类继承RecyclerView
- * .ViewHolder,最后把自己的ViewHolder类丢进自己的Adapter类的泛型中去。
- * 2、在自定义ViewHolder类的构造方法中可以通过ID找到布局的控件,控件需要声明为自定义ViewHolder类的成员变量。
- * 3、实现RecyclerView.Adapter的所有未实现的函数,onCreateViewHolder主要负责加载布局
- * (加载的时候注意要把父布局写到参数里去),创建自定义ViewHolder
- * 类的对象;onBindViewHolder主要负责把数据设置到Item的控件中;getItemCount主要负责得到数据的数目。
- * 4、最好把数据声明为成员变量,在构造函数里面传进来。
- * 5、由于RecycleView原生不支持点击事件,需要自己添加接口进行回调。
- */
- public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.MyViewHolder> {
- List<String> mDatas = null;
- Context mContext = null;
- //构造方法,这里还是和使用BaseAdapter的行为习惯一直
- //通过构造函数把要显示的数据读取进来
- public RecycleAdapter(List<String> mDatas, Context mContext) {
- this.mDatas = mDatas;
- this.mContext = mContext;
- }
- /**
- * 创建泛型中的ViewHolder的方法
- *
- * @param parent 父布局
- * @param viewType Item类型,根据类型可以指定不同的显示布局,重写getItemViewType()方法
- * @return 泛型中的ViewHolder对象
- * <p>
- * 补充:关于viewType
- * 可以通过Adapter的getViewType(int position)方法实现多种不同的条目。
- * 具体做法是根据position的不同例如奇数偶数,或者特定值,然后根据viewType参数的不同去inflate不同的item布局即可
- */
- //负责加载布局 //相当于ListView中的getView()方法
- @Override
- public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- //加载布局的时候需要注意要把parent传进去
- return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout
- .item_view, parent, false));
- }
- /**
- * 创建完成ViewHolder之后需要进行绑定,相当于为每个Item进行赋值,绘制Item的
- *
- * @param holder onCreateViewHolder()方法创建出来的泛型中的ViewHolder
- * @param position 位置
- */
- // 把数据设置到item的控件中 //在这里需要设置显示的数据
- @Override
- public void onBindViewHolder(MyViewHolder holder, int position) {
- holder.tv_num.setText(mDatas.get(position));
- }
- /**
- * 获取条目数量
- *
- * @return 数量
- */
- //主要负责得到数据的数目。
- @Override
- public int getItemCount() {
- return mDatas.size();
- }
- //自定义ViewHolder必须继承RecyclerView.ViewHolder,在构造函数中进行ID绑定控件,条目监听等
- public class MyViewHolder extends RecyclerView.ViewHolder {
- TextView tv_num;
- public MyViewHolder(final View itemView) {
- super(itemView);
- tv_num = (TextView) itemView.findViewById(R.id.tv);
- tv_num.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (onItemClickListener != null) {
- onItemClickListener.onItemClick(itemView, getLayoutPosition(), mDatas.get
- (getLayoutPosition()));
- }
- }
- });
- }
- }
- //自定义监听
- private OnItemClickListener onItemClickListener;
- //定义一个接口
- public interface OnItemClickListener {
- void onItemClick(View v, int position, String data);
- }
- public void setOnItemClickListener(OnItemClickListener listener) {
- this.onItemClickListener = listener;
- }
- public void addData(int position, String data) {
- mDatas.add(position, data);
- notifyItemInserted(position);
- }
- public void removeData(int position) {
- mDatas.remove(position);
- notifyItemRemoved(position);
- }
- }
RecycleDemoActivity
- package com.example.ban.myapplication;
- import android.app.Activity;
- import android.os.Bundle;
- import android.support.v7.widget.DefaultItemAnimator;
- import android.support.v7.widget.GridLayoutManager;
- import android.support.v7.widget.LinearLayoutManager;
- import android.support.v7.widget.RecyclerView;
- import android.support.v7.widget.StaggeredGridLayoutManager;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.view.View;
- import android.widget.Toast;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by ban on 2016/11/24.
- * Activity中需要处理的核心的步骤
- * <p>
- * 1、通过ID找到RecyclerView。
- * 2、RecyclerView设置Adapter。
- * 3、RecyclerView设置布局管理器,常用的布局管理器有LinearLayoutManager:线性布局,
- * 4、LayoutManager的实现类,类型包括Vertical和HorizontalGridLayoutManager;格子布局,继承自LinearLayoutManager
- * ,实现效果类似GridView;StaggeredGridLayoutManager交错的格子布局,同样也是LayoutManager的实现类,类型包括Vertical
- * 和Horizontal,与GridLayoutManager很相似,不过是交错的格子,也就是宽高不等的格子视图,类似瀑布流的效果。
- * 5、RecyclerView设置数据插入、删除的时候的动画效果,这里使用默认的。下面的网址是GitHub上面的开源动画效果:
- * https://github.com/gabrielemariotti/RecyclerViewItemAnimators
- * 6、RecyclerView设置Item之间的装饰器,这里也是使用GitHub提供的装饰器,代码会在附件中给出。
- */
- public class RecycleDemoActivity extends Activity {
- List<String> datas = null;
- private RecyclerView recyclerView;
- private RecycleAdapter myAdapter;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.recycle);
- initData();
- recyclerView = (RecyclerView) findViewById(R.id.recycleview);
- //设置RecycleView的适配器
- myAdapter = new RecycleAdapter(datas, this);
- recyclerView.setAdapter(myAdapter);
- //设置布局管理器,以渲染出不同的效果
- recyclerView.setLayoutManager(new LinearLayoutManager(this));
- //设置插入、删除数据的动画效果(这里使用默认的动画)
- recyclerView.setItemAnimator(new DefaultItemAnimator());
- //设置每个Item之间的装饰(这里设置为分隔线)
- recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration
- .VERTICAL_LIST));
- myAdapter.setOnItemClickListener(new RecycleAdapter.OnItemClickListener() {
- @Override
- public void onItemClick(View v, int position, String data) {
- Toast.makeText(RecycleDemoActivity.this, data, Toast.LENGTH_SHORT).show();
- }
- });
- }
- private void initData() {
- datas = new ArrayList<>();
- for (int i = 0; i < 300; i++) {
- datas.add(i + "===");
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_main, menu);
- return super.onCreateOptionsMenu(menu);
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_add:
- myAdapter.addData(0, "new data");
- recyclerView.scrollToPosition(0);
- break;
- case R.id.action_delete:
- myAdapter.removeData(0);
- break;
- case R.id.action_gridview:
- recyclerView.setLayoutManager(new GridLayoutManager(this, 4));
- break;
- case R.id.action_listview:
- recyclerView.setLayoutManager(new LinearLayoutManager(this));
- break;
- case R.id.action_staggeredgridview:
- recyclerView.setLayoutManager(new StaggeredGridLayoutManager(6,
- StaggeredGridLayoutManager.VERTICAL));
- break;
- }
- return true;
- }
- }
DividerGridItemDecoration
- package com.example.ban.myapplication;
- 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.GridLayoutManager;
- import android.support.v7.widget.RecyclerView;
- import android.support.v7.widget.StaggeredGridLayoutManager;
- import android.view.View;
- /**
- * Created by ban on 2016/11/24.
- */
- public class DividerGridItemDecoration extends RecyclerView.ItemDecoration
- {
- private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
- private Drawable mDivider;
- public DividerGridItemDecoration(Context context)
- {
- final TypedArray a = context.obtainStyledAttributes(ATTRS);
- mDivider = a.getDrawable(0);
- a.recycle();
- }
- @Override
- public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)
- {
- drawHorizontal(c, parent);
- drawVertical(c, parent);
- }
- private int getSpanCount(RecyclerView parent)
- {
- // 列数
- int spanCount = -1;
- RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
- if (layoutManager instanceof GridLayoutManager)
- {
- spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
- } else if (layoutManager instanceof StaggeredGridLayoutManager)
- {
- spanCount = ((StaggeredGridLayoutManager) layoutManager)
- .getSpanCount();
- }
- return spanCount;
- }
- public void drawHorizontal(Canvas c, RecyclerView parent)
- {
- 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.getLeft() - params.leftMargin;
- final int right = child.getRight() + params.rightMargin
- + mDivider.getIntrinsicWidth();
- final int top = child.getBottom() + params.bottomMargin;
- final int bottom = top + mDivider.getIntrinsicHeight();
- mDivider.setBounds(left, top, right, bottom);
- mDivider.draw(c);
- }
- }
- public void drawVertical(Canvas c, RecyclerView parent)
- {
- 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.getTop() - params.topMargin;
- final int bottom = child.getBottom() + params.bottomMargin;
- final int left = child.getRight() + params.rightMargin;
- final int right = left + mDivider.getIntrinsicWidth();
- mDivider.setBounds(left, top, right, bottom);
- mDivider.draw(c);
- }
- }
- private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
- int childCount)
- {
- RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
- if (layoutManager instanceof GridLayoutManager)
- {
- if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
- {
- return true;
- }
- } else if (layoutManager instanceof StaggeredGridLayoutManager)
- {
- int orientation = ((StaggeredGridLayoutManager) layoutManager)
- .getOrientation();
- if (orientation == StaggeredGridLayoutManager.VERTICAL)
- {
- if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
- {
- return true;
- }
- } else
- {
- childCount = childCount - childCount % spanCount;
- if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
- return true;
- }
- }
- return false;
- }
- private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
- int childCount)
- {
- RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
- if (layoutManager instanceof GridLayoutManager)
- {
- childCount = childCount - childCount % spanCount;
- if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
- return true;
- } else if (layoutManager instanceof StaggeredGridLayoutManager)
- {
- int orientation = ((StaggeredGridLayoutManager) layoutManager)
- .getOrientation();
- // StaggeredGridLayoutManager 且纵向滚动
- if (orientation == StaggeredGridLayoutManager.VERTICAL)
- {
- childCount = childCount - childCount % spanCount;
- // 如果是最后一行,则不需要绘制底部
- if (pos >= childCount)
- return true;
- } else
- // StaggeredGridLayoutManager 且横向滚动
- {
- // 如果是最后一行,则不需要绘制底部
- if ((pos + 1) % spanCount == 0)
- {
- return true;
- }
- }
- }
- return false;
- }
- @Override
- public void getItemOffsets(Rect outRect, int itemPosition,
- RecyclerView parent)
- {
- int spanCount = getSpanCount(parent);
- int childCount = parent.getAdapter().getItemCount();
- if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
- {
- outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
- } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
- {
- outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
- } else
- {
- outRect.set(0, 0, mDivider.getIntrinsicWidth(),
- mDivider.getIntrinsicHeight());
- }
- }
- }
DividerItemDecoration
- package com.example.ban.myapplication;
- 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;
- /**
- * Created by ban on 2016/11/24.
- */
- 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);
- }
- }
- }
源码地址:http://download.****.net/detail/u010566681/9692767
https://blog.****.net/u010566681/article/details/52064791