滚动 RecyclerView 太快时会发生一些奇怪的事情
something weird happens while scrolling RecyclerView too fast
我正在为一个长列表使用 RecyclerView,当我滚动得太快时,会发生一些奇怪的事情。有两个问题。
第一个就是下图中的那个。其中一个项目(如图像中的红色边框)粘在屏幕的某个随机部分并阻挡其他项目。当该项目的真实版本在屏幕上可见时,它就会消失。
滚动这么长的 RecyclerView 太快的另一个问题是卡住 onClick 效果。有些项目变得可见,就像有人在按它们一样。
这些问题是关于我的适配器还是关于 RecyclerView 的常见问题?这是我的适配器:
public class SimpleListItemRecyclerAdapter extends RecyclerView.Adapter<SimpleListItemRecyclerAdapter.ListItemViewHolder> {
Context context;
ArrayList<RecyclerItemModel> list;
OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
private int lastPosition = -1;
private boolean isClickable;
public SimpleListItemRecyclerAdapter(ArrayList<RecyclerItemModel> list, _FragmentTemplate fragment) {
this.list = list;
this.context = fragment.getActivity();
try {
this.onRecyclerViewItemClickListener = (OnRecyclerViewItemClickListener) fragment;
isClickable = true;
} catch (ClassCastException e) {
isClickable = false;
}
setHasStableIds(true);
}
@Override
public ListItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).
inflate(R.layout.item_sub_main_list_single_text,
parent,
false);
return new ListItemViewHolder(itemView, onRecyclerViewItemClickListener, isClickable, list.get(0).getHeight());
}
@Override
public void onBindViewHolder(ListItemViewHolder holder, int position) {
final RecyclerItemModel recyclerItem = list.get(position);
if (recyclerItem.isBackgroundColorSpecified())
holder.itemView.setBackgroundResource(recyclerItem.getBackgroundColorResource());
else {
final int[] backgroundColors = Preferences.backgroundSelectorsGrey;
holder.itemView.setBackgroundResource(backgroundColors[position % backgroundColors.length]);
}
holder.textMain.setText(recyclerItem.getTextMain());
if (recyclerItem.isImageRightAvailable()) {
if (recyclerItem.isProgressBarAvailable())
if (recyclerItem.shouldShowDoneImage())
setDrawableFromSVG(holder.imageRight, recyclerItem.getImageRightResourceDone());
else
setDrawableFromSVG(holder.imageRight, recyclerItem.getImageRightResource());
} else
holder.imageRight.setVisibility(View.GONE);
if (recyclerItem.isTextMainBottomAvailable())
holder.textMainBottom.setText(recyclerItem.getTextMainBottom());
else
holder.textMainBottom.setVisibility(View.GONE);
if (recyclerItem.isTextRightTopAvailable())
holder.textRightTop.setText(recyclerItem.getTextRightTop());
else
holder.textRightTop.setVisibility(View.GONE);
if (recyclerItem.isTextRightBottomAvailable())
holder.textRightBottom.setText(recyclerItem.getTextRightBottom());
else
holder.textRightBottom.setVisibility(View.GONE);
if (recyclerItem.isProgressBarAvailable())
holder.progressBar.setProgress(recyclerItem.getProgress());
else
holder.progressBar.setVisibility(View.GONE);
setAnimation(holder.itemView, position);
}
@Override
public long getItemId(int position) {
return list.get(position).hashCode();
}
@Override
public int getItemCount() {
return list.size();
}
private void setAnimation(View viewToAnimate, int position) {
if (position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(context, R.anim.appear);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
public Drawable setDrawableFromSVG(ImageView imageView, int resource) {
SVG svg = new SVGBuilder()
.readFromResource(context.getResources(), resource)
.build();
imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
imageView.setImageDrawable(svg.getDrawable());
return svg.getDrawable();
}
public final static class ListItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
TextView textMain, textMainBottom, textRightTop, textRightBottom;
ImageView imageRight;
ProgressBar progressBar;
View itemView;
public ListItemViewHolder(View itemView, OnRecyclerViewItemClickListener onRecyclerViewItemClickListener,
boolean isClickable, int height) {
super(itemView);
this.itemView = itemView;
this.onRecyclerViewItemClickListener = onRecyclerViewItemClickListener;
textMain = (TextView) itemView.findViewById(R.id.list_item_text_main);
imageRight = (ImageView) itemView.findViewById(R.id.list_item_image_right);
textRightTop = (TextView) itemView.findViewById(R.id.list_item_text_right_top);
textRightBottom = (TextView) itemView.findViewById(R.id.list_item_text_right_bottom);
textMainBottom = (TextView) itemView.findViewById(R.id.list_item_text_main_bottom);
progressBar = (ProgressBar) itemView.findViewById(R.id.list_item_progress_bar);
switch (height) {
case RecyclerItemModel.HEIGHT_FULL:
itemView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, Preferences.squareLength));
break;
case RecyclerItemModel.HEIGHT_HALF:
itemView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, Preferences.squareLength / 2));
}
if (isClickable)
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
onRecyclerViewItemClickListener.onRecyclerViewItemClick(getPosition());
}
}
}
这是解决我的问题的方法:
动画以某种方式导致 RecyclerView 出现问题。所以我的解决方案是删除以下行:
setAnimation(holder.itemView, position);
我没有尝试再次添加动画,但如果您真的需要它,这里有一些有用的东西:How to animate RecyclerView items when they appear。
我正在为一个长列表使用 RecyclerView,当我滚动得太快时,会发生一些奇怪的事情。有两个问题。
第一个就是下图中的那个。其中一个项目(如图像中的红色边框)粘在屏幕的某个随机部分并阻挡其他项目。当该项目的真实版本在屏幕上可见时,它就会消失。
滚动这么长的 RecyclerView 太快的另一个问题是卡住 onClick 效果。有些项目变得可见,就像有人在按它们一样。
这些问题是关于我的适配器还是关于 RecyclerView 的常见问题?这是我的适配器:
public class SimpleListItemRecyclerAdapter extends RecyclerView.Adapter<SimpleListItemRecyclerAdapter.ListItemViewHolder> {
Context context;
ArrayList<RecyclerItemModel> list;
OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
private int lastPosition = -1;
private boolean isClickable;
public SimpleListItemRecyclerAdapter(ArrayList<RecyclerItemModel> list, _FragmentTemplate fragment) {
this.list = list;
this.context = fragment.getActivity();
try {
this.onRecyclerViewItemClickListener = (OnRecyclerViewItemClickListener) fragment;
isClickable = true;
} catch (ClassCastException e) {
isClickable = false;
}
setHasStableIds(true);
}
@Override
public ListItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).
inflate(R.layout.item_sub_main_list_single_text,
parent,
false);
return new ListItemViewHolder(itemView, onRecyclerViewItemClickListener, isClickable, list.get(0).getHeight());
}
@Override
public void onBindViewHolder(ListItemViewHolder holder, int position) {
final RecyclerItemModel recyclerItem = list.get(position);
if (recyclerItem.isBackgroundColorSpecified())
holder.itemView.setBackgroundResource(recyclerItem.getBackgroundColorResource());
else {
final int[] backgroundColors = Preferences.backgroundSelectorsGrey;
holder.itemView.setBackgroundResource(backgroundColors[position % backgroundColors.length]);
}
holder.textMain.setText(recyclerItem.getTextMain());
if (recyclerItem.isImageRightAvailable()) {
if (recyclerItem.isProgressBarAvailable())
if (recyclerItem.shouldShowDoneImage())
setDrawableFromSVG(holder.imageRight, recyclerItem.getImageRightResourceDone());
else
setDrawableFromSVG(holder.imageRight, recyclerItem.getImageRightResource());
} else
holder.imageRight.setVisibility(View.GONE);
if (recyclerItem.isTextMainBottomAvailable())
holder.textMainBottom.setText(recyclerItem.getTextMainBottom());
else
holder.textMainBottom.setVisibility(View.GONE);
if (recyclerItem.isTextRightTopAvailable())
holder.textRightTop.setText(recyclerItem.getTextRightTop());
else
holder.textRightTop.setVisibility(View.GONE);
if (recyclerItem.isTextRightBottomAvailable())
holder.textRightBottom.setText(recyclerItem.getTextRightBottom());
else
holder.textRightBottom.setVisibility(View.GONE);
if (recyclerItem.isProgressBarAvailable())
holder.progressBar.setProgress(recyclerItem.getProgress());
else
holder.progressBar.setVisibility(View.GONE);
setAnimation(holder.itemView, position);
}
@Override
public long getItemId(int position) {
return list.get(position).hashCode();
}
@Override
public int getItemCount() {
return list.size();
}
private void setAnimation(View viewToAnimate, int position) {
if (position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(context, R.anim.appear);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
public Drawable setDrawableFromSVG(ImageView imageView, int resource) {
SVG svg = new SVGBuilder()
.readFromResource(context.getResources(), resource)
.build();
imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
imageView.setImageDrawable(svg.getDrawable());
return svg.getDrawable();
}
public final static class ListItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
OnRecyclerViewItemClickListener onRecyclerViewItemClickListener;
TextView textMain, textMainBottom, textRightTop, textRightBottom;
ImageView imageRight;
ProgressBar progressBar;
View itemView;
public ListItemViewHolder(View itemView, OnRecyclerViewItemClickListener onRecyclerViewItemClickListener,
boolean isClickable, int height) {
super(itemView);
this.itemView = itemView;
this.onRecyclerViewItemClickListener = onRecyclerViewItemClickListener;
textMain = (TextView) itemView.findViewById(R.id.list_item_text_main);
imageRight = (ImageView) itemView.findViewById(R.id.list_item_image_right);
textRightTop = (TextView) itemView.findViewById(R.id.list_item_text_right_top);
textRightBottom = (TextView) itemView.findViewById(R.id.list_item_text_right_bottom);
textMainBottom = (TextView) itemView.findViewById(R.id.list_item_text_main_bottom);
progressBar = (ProgressBar) itemView.findViewById(R.id.list_item_progress_bar);
switch (height) {
case RecyclerItemModel.HEIGHT_FULL:
itemView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, Preferences.squareLength));
break;
case RecyclerItemModel.HEIGHT_HALF:
itemView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, Preferences.squareLength / 2));
}
if (isClickable)
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
onRecyclerViewItemClickListener.onRecyclerViewItemClick(getPosition());
}
}
}
这是解决我的问题的方法:
动画以某种方式导致 RecyclerView 出现问题。所以我的解决方案是删除以下行:
setAnimation(holder.itemView, position);
我没有尝试再次添加动画,但如果您真的需要它,这里有一些有用的东西:How to animate RecyclerView items when they appear。