RecyclerView大家都使用过的话会有些不方便,现在对其封装一下,让其可以:
1.可以像ListView一样方便使用OnItemClickListener;
2.可省去ViewHolder,快速开发;
3.分割线问题,即提供万能分割线。
贴上如何使用:
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
rvHorizontal.setLayoutManager(layoutManager);
RecyclerViewDivider divder = new RecyclerViewDivider(false); // 创业分割,false为HORIZONTAL
divder.setColor(0xff5ED0F2); // 分割线颜色
divder.setMargin(this, 0, 15, 0, 15); // 分割线边距
divder.setDividerHeight(this, 1);// 分割线宽度
rvHorizontal.addItemDecoration(divder);
DataAdapter dataAdapter = new DataAdapter(this);
rvHorizontal.setAdapter(dataAdapter);
// layoutManager = new LinearLayoutManager(this);
// layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
// rvVertical.setLayoutManager(layoutManager);
// divder = new RecyclerViewDivider(true);// 创业分割,true为VERTICAL
// divder.setMargin(10, 10, 10, 10); // 分割线边距
// divder.setDividerHeight(50);// 分割线宽度 50要大于(10+10)
// // 分割线Drawable
// divder.setDrawable(ContextCompat.getDrawable(this, R.drawable.circle_bg));
// rvVertical.addItemDecoration(divder);
// DataAdapter dataAdapter1 = new DataAdapter(this);
// rvVertical.setAdapter(dataAdapter1);
OnItemClickListener listener = new OnItemClickListener() {
@Override
public void onItemClick(RecyclerHolder holder, int position) {
Toast.makeText(MainActivity.this, String.valueOf(position), Toast.LENGTH_LONG).show();
}
};
// 设置监听
dataAdapter.setOnItemClickListener(listener);
dataAdapter1.setOnItemClickListener(listener);
如何方便定义RecyclerAdatper:
public class DataAdapter extends RecyclerAdatper<Data> {
public DataAdapter(Context context, List list) {
super(context, list);
}
public DataAdapter(Context context) {
super(context);
for (int i = 0; i < 20; i++) {
Data data = new Data();
data.setName("Name:" + i);
getList().add(data);
}
}
@Override
public int getContentView(int viewType) {
return R.layout.item_main_data;
}
@Override
public void onInitView(RecyclerHolder holder, Data object, int position) {
holder.setText(R.id.tv_item_main_name, object.getName());
}
}
涉及到的circle_bg.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#56f53f"/>
<corners android:radius="6dp"/>
shape>
demo地址:
TAO CODE: http://code.taobao.org/p/RecyclerViewDemo/src/
GitHub: https://github.com/scorpioyou/RecyclerViewDemo
主要由以下类:
OnItemClickListener
RecyclerAdatper
RecyclerHolder
RecyclerViewDivider
OnItemClickListener:
package com.recycler.lib;
/**
* creater:cyy
* time:2017/2/8
* describe:定义{@link android.support.v7.widget.RecyclerView}OnItemClickListener点击事件
*/
public interface OnItemClickListener {
/**
* @param holder 操作的ViewHolder
* @param position 点击item的位置
*/
void onItemClick(RecyclerHolder holder, int position);
}
RecyclerAdatper:
package com.recycler.lib;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
/**
* creater:cyy
* time:2017/2/8
* describe:定义{@link android.support.v7.widget.RecyclerView}OnItemClickListener万能适配器
*/
public abstract class RecyclerAdatper extends RecyclerView.Adapter {
private Context mContext;
private List mList;
private OnItemClickListener mOnItemClickListener;
public RecyclerAdatper(Context context) {
this(context, new ArrayList());
}
public RecyclerAdatper(Context context, List list) {
mContext = context;
mList = list;
}
public Context getContext() {
return mContext;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.mOnItemClickListener = onItemClickListener;
}
@Override
public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new RecyclerHolder(getLayoutInflater().inflate(getContentView(viewType), parent,
false));
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
@Override
public void onBindViewHolder(final RecyclerHolder holder, final int position) {
onInitView(holder, getItem(position), position);
if (null != mOnItemClickListener) { // 实现item点击事件回调
holder.getView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnItemClickListener.onItemClick(holder, position);
}
});
}
}
@Override
public int getItemCount() {
if (null != mList) {
return mList.size();
}
return 0;
}
//---------------------------------abstract--------------------------------
/**
* item布局ID
*
* @param viewType 类别
* @return item布局ID
*/
public abstract int getContentView(int viewType);
/**
* item刷新的回调
*
* @param holder ViewHolder
* @param object Item数据对象
* @param position 刷新的位置
*/
public abstract void onInitView(RecyclerHolder holder, T object, int position);
//---------------------------------List--------------------------------
public List getList() {
return mList;
}
public void setList(List list) {
this.mList = list;
notifyDataSetChanged();
}
public void clear() {
this.mList.clear();
notifyDataSetChanged();
}
public void remove(int location) {
if (location >= 0 && mList.size() > location) {
this.mList.remove(location);
notifyDataSetChanged();
}
}
public void add(int location, T object) {
if (object != null) {
this.mList.add(location, object);
notifyDataSetChanged();
}
}
public void addLast(T object) {
if (object != null) {
this.mList.add(object);
notifyDataSetChanged();
}
}
public void addHead(T object) {
if (object != null) {
this.mList.add(0, object);
notifyDataSetChanged();
}
}
public void addAll(List list) {
if (list != null) {
this.mList.addAll(list);
notifyDataSetChanged();
}
}
public T getItem(int position) {
return mList.get(position);
}
//---------------------------------other--------------------------------
protected LayoutInflater getLayoutInflater() {
return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
protected int getColor(int id) {
return ContextCompat.getColor(getContext(), id);
}
protected String getString(int id) {
return getContext().getResources().getString(id);
}
protected float getDimension(int id) {
return getContext().getResources().getDimension(id);
}
protected Drawable getDrawable(int id) {
return ContextCompat.getDrawable(getContext(), id);
}
}
RecyclerHolder:
package com.recycler.lib;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.text.util.Linkify;
import android.util.SparseArray;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.Checkable;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.TextView;
/**
* creater:cyy
* time:2017/2/8
* describe:
*/
public class RecyclerHolder extends RecyclerView.ViewHolder {
private View convertView;
public RecyclerHolder(View itemView) {
super(itemView);
convertView = itemView;
}
public T getView(int viewId) {
return retrieveView(viewId);
}
protected T retrieveView(int viewId) {
SparseArray viewHolder = (SparseArray) convertView.getTag();
if (null == viewHolder) {
viewHolder = new SparseArray();
convertView.setTag(viewHolder);
}
View childView = viewHolder.get(viewId);
if (null == childView) {
childView = convertView.findViewById(viewId);
viewHolder.put(viewId, childView);
}
return (T) childView;
}
public RecyclerHolder setText(int viewId, CharSequence value) {
TextView view = retrieveView(viewId);
if (TextUtils.isEmpty(value)) {
view.setText("");
} else {
view.setText(value);
}
return this;
}
public RecyclerHolder setImageResource(int viewId, int imageResId) {
ImageView view = retrieveView(viewId);
view.setImageResource(imageResId);
return this;
}
public RecyclerHolder setBackgroundColor(int viewId, int color) {
View view = retrieveView(viewId);
view.setBackgroundColor(color);
return this;
}
public RecyclerHolder setBackgroundRes(int viewId, int backgroundRes) {
View view = retrieveView(viewId);
view.setBackgroundResource(backgroundRes);
return this;
}
public RecyclerHolder setTextColor(int viewId, int textColor) {
TextView view = retrieveView(viewId);
view.setTextColor(textColor);
return this;
}
public RecyclerHolder setTextColorRes(int viewId, int textColorRes) {
TextView view = retrieveView(viewId);
view.setTextColor(ContextCompat.getColor(view.getContext(), textColorRes));
return this;
}
public RecyclerHolder setImageDrawable(int viewId, Drawable drawable) {
ImageView view = retrieveView(viewId);
view.setImageDrawable(drawable);
return this;
}
public RecyclerHolder setImageBitmap(int viewId, Bitmap bitmap) {
ImageView view = retrieveView(viewId);
view.setImageBitmap(bitmap);
return this;
}
@SuppressLint("NewApi")
public RecyclerHolder setAlpha(int viewId, float value) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
retrieveView(viewId).setAlpha(value);
} else {
// Pre-honeycomb hack to set Alpha value
AlphaAnimation alpha = new AlphaAnimation(value, value);
alpha.setDuration(0);
alpha.setFillAfter(true);
retrieveView(viewId).startAnimation(alpha);
}
return this;
}
public RecyclerHolder setVisible(int viewId, boolean visible) {
View view = retrieveView(viewId);
view.setVisibility(visible ? View.VISIBLE : View.GONE);
return this;
}
public RecyclerHolder setVisible(int viewId, int visibility) {
View view = retrieveView(viewId);
view.setVisibility(visibility);
return this;
}
/**
* Add links into a TextView.
*
* @param viewId The id of the TextView to linkify.
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder linkify(int viewId) {
TextView view = retrieveView(viewId);
Linkify.addLinks(view, Linkify.ALL);
return this;
}
/**
* Apply the typeface to the given viewId, and enable subpixel rendering.
*/
public RecyclerHolder setTypeface(int viewId, Typeface typeface) {
TextView view = retrieveView(viewId);
view.setTypeface(typeface);
view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
return this;
}
/**
* Apply the typeface to all the given viewIds, and enable subpixel
* rendering.
*/
public RecyclerHolder setTypeface(Typeface typeface, int... viewIds) {
for (int viewId : viewIds) {
TextView view = retrieveView(viewId);
view.setTypeface(typeface);
view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
}
return this;
}
/**
* Sets the progress of a ProgressBar.
*
* @param viewId The view id.
* @param progress The progress.
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setProgress(int viewId, int progress) {
ProgressBar view = retrieveView(viewId);
view.setProgress(progress);
return this;
}
/**
* Sets the progress and max of a ProgressBar.
*
* @param viewId The view id.
* @param progress The progress.
* @param max The max value of a ProgressBar.
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setProgress(int viewId, int progress, int max) {
ProgressBar view = retrieveView(viewId);
view.setMax(max);
view.setProgress(progress);
return this;
}
/**
* Sets the range of a ProgressBar to 0...max.
*
* @param viewId The view id.
* @param max The max value of a ProgressBar.
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setMax(int viewId, int max) {
ProgressBar view = retrieveView(viewId);
view.setMax(max);
return this;
}
/**
* Sets the rating (the number of stars filled) of a RatingBar.
*
* @param viewId The view id.
* @param rating The rating.
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setRating(int viewId, float rating) {
RatingBar view = retrieveView(viewId);
view.setRating(rating);
return this;
}
/**
* Sets the rating (the number of stars filled) and max of a RatingBar.
*
* @param viewId The view id.
* @param rating The rating.
* @param max The range of the RatingBar to 0...max.
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setRating(int viewId, float rating, int max) {
RatingBar view = retrieveView(viewId);
view.setMax(max);
view.setRating(rating);
return this;
}
/**
* Sets the tag of the view.
*
* @param viewId The view id.
* @param tag The tag;
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setTag(int viewId, Object tag) {
View view = retrieveView(viewId);
view.setTag(tag);
return this;
}
/**
* Sets the tag of the view.
*
* @param viewId The view id.
* @param key The key of tag;
* @param tag The tag;
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setTag(int viewId, int key, Object tag) {
View view = retrieveView(viewId);
view.setTag(key, tag);
return this;
}
/**
* Sets the checked status of a checkable.
*
* @param viewId The view id.
* @param checked The checked status;
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setChecked(int viewId, boolean checked) {
Checkable view = (Checkable) retrieveView(viewId);
view.setChecked(checked);
return this;
}
/**
* Sets the adapter of a adapter view.
*
* @param viewId The view id.
* @param adapter The adapter;
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setAdapter(int viewId, Adapter adapter) {
AdapterView view = retrieveView(viewId);
view.setAdapter(adapter);
return this;
}
/**
* Sets the on click listener of the view.
*
* @param viewId The view id.
* @param listener The on click listener;
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setOnClickListener(int viewId, View.OnClickListener listener) {
View view = retrieveView(viewId);
view.setOnClickListener(listener);
return this;
}
public RecyclerHolder setOnCheckedChangeListener(int viewId, CompoundButton.OnCheckedChangeListener listener) {
CompoundButton view = retrieveView(viewId);
view.setOnCheckedChangeListener(listener);
return this;
}
/**
* Sets the on touch listener of the view.
*
* @param viewId The view id.
* @param listener The on touch listener;
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setOnTouchListener(int viewId, View.OnTouchListener listener) {
View view = retrieveView(viewId);
view.setOnTouchListener(listener);
return this;
}
/**
* Sets the on long click listener of the view.
*
* @param viewId The view id.
* @param listener The on long click listener;
* @return The BaseAdapterHelper for chaining.
*/
public RecyclerHolder setOnLongClickListener(int viewId, View.OnLongClickListener listener) {
View view = retrieveView(viewId);
view.setOnLongClickListener(listener);
return this;
}
/**
* Retrieve the convertView
*/
public View getView() {
return convertView;
}
}
RecyclerViewDivider:
package com.recycler.lib;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.LinearLayout;
/**
* creater:cyy
* time:2017/2/8
* describe:
*/
public class RecyclerViewDivider extends RecyclerView.ItemDecoration {
private Drawable mDivider;
private int mDividerHeight = 0;
private Paint mPaint;
private int mOrientation;
private final Rect mBounds = new Rect();
private Rect mMarginBounds;
public RecyclerViewDivider() {
mOrientation = LinearLayout.VERTICAL;
}
public RecyclerViewDivider(boolean isVertical) {
if (isVertical) {
mOrientation = LinearLayout.VERTICAL;
} else {
mOrientation = LinearLayout.HORIZONTAL;
}
}
public void setDividerHeight(int px) {
this.mDividerHeight = px;
}
public void setDividerHeight(Context c, int dp) {
this.mDividerHeight = (int) (dp * c.getResources().getDisplayMetrics().density);
}
public void setDrawable(@NonNull Drawable drawable) {
mDivider = drawable;
}
public void setColor(int color) {
mPaint = new Paint();
mPaint.setColor(color);
}
public void setColor(Context c, @ColorRes int colorId) {
setColor(ContextCompat.getColor(c, colorId));
}
public void setMargin(int left, int top, int right, int bottom) {
mMarginBounds = new Rect();
mMarginBounds.left = left;
mMarginBounds.top = top;
mMarginBounds.right = right;
mMarginBounds.bottom = bottom;
}
public void setMargin(Context c, int leftDp, int topDp, int rightDp, int bottomDp) {
float density = c.getResources().getDisplayMetrics().density;
mMarginBounds = new Rect();
mMarginBounds.left = (int) (leftDp * density);
mMarginBounds.top = (int) (topDp * density);
mMarginBounds.right = (int) (rightDp * density);
mMarginBounds.bottom = (int) (bottomDp * density);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (parent.getLayoutManager() == null) {
return;
}
if (mOrientation == LinearLayout.VERTICAL) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
@SuppressLint("NewApi")
private void drawVertical(Canvas canvas, RecyclerView parent) {
canvas.save();
final int left;
final int right;
if (parent.getClipToPadding()) {
left = parent.getPaddingLeft();
right = parent.getWidth() - parent.getPaddingRight();
canvas.clipRect(left, parent.getPaddingTop(), right,
parent.getHeight() - parent.getPaddingBottom());
} else {
left = 0;
right = parent.getWidth();
}
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, mBounds);
final int bottom = mBounds.bottom + Math.round(ViewCompat.getTranslationY(child));
int top = bottom - mDividerHeight;
if (null != mDivider) {
int sicWidth = mDivider.getIntrinsicWidth();
if (sicWidth > 0) {
top = bottom - sicWidth;
}
if (null != mMarginBounds) {
mDivider.setBounds(left + mMarginBounds.left, top + mMarginBounds.top,
right - mMarginBounds.right, bottom - mMarginBounds.bottom);
} else {
mDivider.setBounds(left, top, right, bottom);
}
mDivider.draw(canvas);
}
if (mPaint != null) {
if (null != mMarginBounds) {
canvas.drawRect(left + mMarginBounds.left, top + mMarginBounds.top,
right - mMarginBounds.right, bottom - mMarginBounds.bottom, mPaint);
} else {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}
canvas.restore();
}
@SuppressLint("NewApi")
private void drawHorizontal(Canvas canvas, RecyclerView parent) {
canvas.save();
final int top;
final int bottom;
if (parent.getClipToPadding()) {
top = parent.getPaddingTop();
bottom = parent.getHeight() - parent.getPaddingBottom();
canvas.clipRect(parent.getPaddingLeft(), top,
parent.getWidth() - parent.getPaddingRight(), bottom);
} else {
top = 0;
bottom = parent.getHeight();
}
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
parent.getLayoutManager().getDecoratedBoundsWithMargins(child, mBounds);
int right = mBounds.right + Math.round(ViewCompat.getTranslationX(child));
int left = right - mDividerHeight;
if (null != mDivider) {
int sicWidth = mDivider.getIntrinsicWidth();
if (sicWidth > 0) {
left = right - sicWidth;
}
if (null != mMarginBounds) {
mDivider.setBounds(left + mMarginBounds.left, top + mMarginBounds.top,
right - mMarginBounds.right, bottom - mMarginBounds.bottom);
} else {
mDivider.setBounds(left, top, right, bottom);
}
mDivider.draw(canvas);
}
if (mPaint != null) {
if (null != mMarginBounds) {
canvas.drawRect(left + mMarginBounds.left, top + mMarginBounds.top,
right - mMarginBounds.right, bottom - mMarginBounds.bottom, mPaint);
} else {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}
canvas.restore();
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
if (mOrientation == LinearLayout.VERTICAL) {
if (0 == mDividerHeight && null != mDivider) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, 0, mDividerHeight);
}
} else {
if (0 == mDividerHeight && null != mDivider) {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
} else {
outRect.set(0, 0, mDividerHeight, 0);
}
}
}
}