延续上篇接着来玩RecyclerView控件,综合运用LayoutManager,根据洪洋的视频教程简单的分析RecyclerView相关流程图。
分割线的自定义,构造函数读取分割线drawable资源,根据列表方向测量分割线的范围以及绘制在水平和垂直各个方向的分割线条
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;//item间隔图片资源
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) {
Log.v("recy-itemdecoration", "onDraw()");
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);
RecyclerView v = new 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.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
/**
* 提供绘制的分割线
* @param outRect
* @param itemPosition
* @param parent
*/
@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);
}
}
}
关于Divider的位置测量,通过下一幅图相信你一定能理解!!!
以前adapter的用法getView现在被拆分位两部分onCreateViewHolder、onBindViewHolder,绑定ViewHolder和内容视图赋值。对于内容视图的点击响应事件可以通过设置内部定义接口OnItemClickListener进行回调
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.item_single_textview, parent, false);
MyViewHolder viewHolder = new MyViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.tv.setText(mDatas.get(position));
//设置点击事件回调
if (mOnItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int layoutPostion = holder.getLayoutPosition();
mOnItemClickListener.onItemClick(holder.itemView, layoutPostion);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int layoutPostion = holder.getLayoutPosition();
mOnItemClickListener.onItemLongClick(holder.itemView, layoutPostion);
return false;
}
});
}
}
添加一条数据和删除一条数据不能再用以前的notifyDataChange了,需要使用新的api
public void addDatas(int position) {
mDatas.add(position, "Insert One");
notifyItemInserted(position);
}
public void deleteDatas(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
}
MyStaggeredAdapter只是一个模拟的随机高度,就略过了,有一点必须的说明:OnItemClickListener这里的回调函数对应的参数position不能直接传入position,在add delete后直接传入的position是混乱的,这里需要用到
position = holder.getLayoutPosition();
mAdapter = new MySimpleAdapter(this, mDatas);
mRecyclerview.setAdapter(mAdapter);
//设置RecyclerView的布局管理
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerview.setLayoutManager(linearLayoutManager);
mRecyclerview.setItemAnimator(new DefaultItemAnimator());
//设置RecyclerView的Item间分割线
//mRecyclerview.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
mAdapter.setOnItemClickListener(new MySimpleAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, "click:" + position, Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position) {
Toast.makeText(MainActivity.this, "long click:" + position, Toast.LENGTH_SHORT).show();
}
});
如果想RecyclerView想变成GridView改变manager就可以了
mRecyclerview.setLayoutManager(new GridLayoutManager(this, 3));
以上源码地址:https://github.com/NewOrin/RecyclerViewDemo,个人感觉源码里面的Divider有点问题如果你用了你就知道,O(∩_∩)O~