RecycleView是google为了优化listview,gridview 提供的一个新的控件。
在app的gradle里面加入:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) apt "org.androidannotations:androidannotations:$AAVersion" compile "org.androidannotations:androidannotations-api:$AAVersion" testCompile 'junit:junit:4.12' compile 'com.android.support:recyclerview-v7:23.1.+' compile 'com.android.support:appcompat-v7:23.1.1' }
其中23为sdk版本号。
RecycleView主要功能分为几个模块:
package com.joyfulmath.sample.javanetwork.androidbase.recycleview.view; 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 com.joyfulmath.sample.javanetwork.R; import java.util.ArrayList; /** * @author deman.lu * @version on 2016-03-10 14:19 */ public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.RecycleViewHolder> { private Context context; private ArrayList<String> mDatas; public RecycleAdapter(Context context,ArrayList<String> mStrings) { this.context = context; this.mDatas = mStrings; } @Override public RecycleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecycleViewHolder holder = new RecycleViewHolder(LayoutInflater.from(context) .inflate(R.layout.item_list,parent,false)); return holder; } @Override public void onBindViewHolder(RecycleViewHolder holder, int position) { holder.tv1.setText(mDatas.get(position)); holder.tv2.setText(mDatas.get(position)+" demo"); } @Override public int getItemCount() { return mDatas.size(); } class RecycleViewHolder extends RecyclerView.ViewHolder { TextView tv1; TextView tv2; public RecycleViewHolder(View itemView) { super(itemView); tv1 = (TextView) itemView.findViewById(R.id.tv_1); tv2 = (TextView) itemView.findViewById(R.id.tv_2); } } }
首先 需要定义一个holder,这个holder是用来优化复用recycleview的item的。此与listview已经非常类似。
其次adapter要实现3个方法:
public RecycleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) //viewholder 布局代码
public void onBindViewHolder(RecycleViewHolder holder, int position) 数据处理代码
public int getItemCount() 得到item size
相当熟悉的代码。
RecycleView 默认支持linearlayoutmanager & gridlayoutmanager
其实就是对应listview & gridview
mRcyV.setLayoutManager(new LinearLayoutManager(this));
void afterView() { mPresenter = new RecyclePresenter(); mRcyV.setLayoutManager(new GridLayoutManager(this,4)); mRcyV.setAdapter(new RecycleAdapter(this, mPresenter.getData())); mRcyV.addItemDecoration(new RecycleGridItemDecoration(this)); }
本质上是每个itemview的子view。很多时候用途就是定义为 分隔线使用。
1.listview.
public class RecycleItemDecoration 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 RecycleItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = new ColorDrawable(Color.argb(0xff,0xff,0x22,0x33)); 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+10); 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); } } }
2.gridview 样式:
public class RecycleGridItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[] { android.R.attr.listDivider }; private Drawable mDivider; public RecycleGridItemDecoration(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()); } } }
最后是activity页面:
@EActivity(R.layout.activity_recycleview_demo) public class RecycleViewDemo extends Activity{ @ViewById(R.id.act_solution_1_lv) RecyclerView mRcyV; RecyclePresenter mPresenter; @AfterViews void afterView() { mPresenter = new RecyclePresenter(); mRcyV.setLayoutManager(new GridLayoutManager(this,4)); mRcyV.setAdapter(new RecycleAdapter(this, mPresenter.getData())); mRcyV.addItemDecoration(new RecycleGridItemDecoration(this)); } }
recycleview的每一个item的add & delete都是可配置动画的。DefaultItemAnimator是google提供的默认实现方式。
mRcyV.setItemAnimator(new DefaultItemAnimator());
public void addData(int position) { mDatas.add(position, "Insert One"); notifyItemInserted(position); } public void removeData(int position) { mDatas.remove(position); notifyItemRemoved(position); }
在adapter中实现这2个方法,关键在于notifyItem***, 这2个方法可以触发动画。
recycleview比起listview来说,应该是可以定制更多的东西,尤其是瀑布模式,实现起来效果很炫。
参考:
http://blog.csdn.net/lmj623565791/article/details/45059587