a android 5.0新特性 RecyclerView使用初级
b Group分组列表的实现 RecyclerView ,实现不同类型的item组合列表
public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
private final int mLeft;
private final int mTop;
private final int mRight;
private final int mBottom;
/**
* @param left padding in pixel
* @param top padding in pixel
* @param right padding in pixel
* @param bottom padding in pixel
*/
public SpaceItemDecoration(int left, int top, int right, int bottom) {
mLeft = left;
mTop = top;
mRight = right;
mBottom = bottom;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(mLeft, mTop, mRight, mBottom);
}
}
参考 http://blog.csdn.net/cjm2484836553/article/details/53439751
其实很简单,就是在每个item下面绘制一条带颜色的矩形即为分割线。
public class MyDeviderDecoration extends RecyclerView.ItemDecoration {
private int mydevider;
private Paint dividerPaint;
public MyDeviderDecoration(Context context) {
dividerPaint = new Paint();
//设置分割线颜色
dividerPaint.setColor(context.getResources().getColor(R.color.colorAccent));
//设置分割线宽度
mydevider = context.getResources().getDimensionPixelSize(R.dimen.divider_bottom);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.bottom = mydevider;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
int childCount = parent.getChildCount();
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < childCount - 1; i++) {
View view = parent.getChildAt(i);
float top = view.getBottom();
float bottom = view.getBottom() + mydevider;
c.drawRect(left, top, right, bottom, dividerPaint);
}
}
}
将VM放在holder就好。
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_NORMAL) {
...
} else {
//更多
MoreItemVM viewModel = new ListMoreItemVM(...);
// 初始化binding
binding = BindingUtils.inflate(...)
...
binding.setViewModel(viewModel);
return new ViewHolder(binding.getRoot(), viewModel, binding);
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//
if (getItemViewType(position) == VIEW_TYPE_NORMAL) {
holder.setData(...);
} else {
holder.setData(...);
}
holder.mBinding.executePendingBindings();
}
@Override
public int getItemViewType(int position) {
if (position < getItemCount() - 1) {
return VIEW_TYPE_NORMAL;
} else {
return VIEW_TYPE_MORE;
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private ListItemVM mItemViewModel;
private ListMoreItemVM mMoreItemVM;
public final ViewDataBinding mBinding;
public ViewHolder(View itemView, ListItemVM itemViewModel, ViewDataBinding binding) {
super(itemView);
mItemViewModel = itemViewModel;
mItemViewModel.reset();
mBinding = binding;
}
public ViewHolder(View itemView, ListMoreItemVM itemViewModel, ViewDataBinding binding) {
super(itemView);
mMoreItemVM = itemViewModel;
mBinding = binding;
}
public void setData(RunningAlbumInfo runningAlbumInfo) {
mItemViewModel.setData(runningAlbumInfo);
}
public void setData(Category category) {
mMoreItemVM.setData(category);
}
}
这个问题,即是说如何拿到当前选中的item。思路很简单,先拿到holder,然后通过holder拿到对应的VM。恩,其实这里的popwindow该放在adpter中show的,统一的逻辑都该adpter来做,VM只负责展示。
if (mRecyclerView != null && mLinearLayoutManager != null) {
int pos = mRecyclerView.getCurrentPosition();
View view = mLinearLayoutManager.getChildAt(pos);
if (view != null) {
ListAdapter.ViewHolder holder =
(ListAdapter.ViewHolder) mRecyclerView.getChildViewHolder(view);
if (holder.mBinding != null && (holder.mBinding instanceof xxxBinding)
&& ((xxxBinding) holder.mBinding).getViewModel().isShowing()) {
((xxxBinding) holder.mBinding).getViewModel().dismiss();
return true;
}
}
}
这里有几套方案,
我在这里调了整整一天,都出现google的issue。原来初始化的基类,在onViewCreated中调用,让我造成了这个isssue,重新异步请求刷新了一遍数据。
基本上看stackoverflow和issue下面的回答,有帮助的大意是:recyclerView 的数据刷新不同步(导致滚动位置无法定位或调用scrollToPosition时不同步)。解决方法是检查下有木有重复的比较连续刷新数据,刷新数据和定位几乎同时调用。
http://www.jianshu.com/p/4535442d568f
该文中已提出一个workaround
这里由于产品需要,recyclerView的item的高度为动态的wrap_content(建议不要使用,recyclerView由于得不到具体宽高,会多次调用getView方法),又要求recyclerView的item进行折叠。当recyclerView的数据项不满一屏时,且此时recyclerView的item由展开到折叠,此时存在视觉上的ui缓存。即该折叠项依然占据展开式的位置。此时,进行点击事件或滑动事件时,缓存的数据消失。 而采用stackoverflow上消去drawingcache 的方法没有作用:
在listView或此处,我使用的workaround均为Handler post方法解决。
刷新单个item的时候,出现闪屏现象。(比较常见的是,item做动画时,就存在这个问题)
2 http://stackoverflow.com/questions/29331075/recyclerview-blinking-after-notifydatasetchanged
这个查了网上的一些方案,对我起作用的ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}