10

I'm using RecyclerView for a long list and when i scroll too fast, something weird happens. There are two problems.

First one is the one in the image below. One of items (like red bordered one in the image) sticks on some random part of the screen and blocks other items. It disappears when the real version of that item becomes visible on the screen.

screenshot

Another problem about scrolling this long RecyclerView too fast is sticking onClick effect. Some of items become visible like someone is pressing on them.

Are these problems about my adapter or are they common problems about RecyclerView? Here is my adapter:

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());
        }
    }
}
iamkaan
  • 1,495
  • 2
  • 23
  • 43
  • Any particular reason you're not using a regular ListView to display a list? Add your adapter code and we'll take a look. – G_V Jan 28 '15 at 13:08
  • because there are too many items and it makes app slow to use regular ListView /: i'll share my adapter now – iamkaan Jan 28 '15 at 13:18
  • Is the Holder supposed to be static? I am not too experienced with recyclerview myself but in ListView a static holder will cause unpredictable behaviour. – G_V Jan 28 '15 at 14:03
  • this is how i saw in developer.android.com. let me try to change it. – iamkaan Jan 28 '15 at 14:35
  • I see the example uses a static, but not final. Final means it can be assigned once and only once. Try it without the final, see what it does. I'm trying to help you but I'm not an expert with this component either. – G_V Jan 28 '15 at 14:57
  • 3
    Have you tried without animating the item view? – rciovati Jan 28 '15 at 16:34
  • 2
    removing animation solved problem. so is animating items not a good idea? – iamkaan Jan 29 '15 at 08:59
  • I have the same pb and removing animation solved the pb ! @rciovati , you can make a real answer and iamkaan can set it at "Resolved" – Cocorico Mar 11 '15 at 15:27
  • Have same issue, resolved the same way – Nick Felker May 02 '15 at 16:46

1 Answers1

6

Here is what resolved my problem:

Animating somehow causes a problem on RecyclerView. So the solution for me was removing the following line:

setAnimation(holder.itemView, position);

I didn't try to add animation again but if you really need it, here is something that can be useful: How to animate RecyclerView items when they appear.

Community
  • 1
  • 1
iamkaan
  • 1,495
  • 2
  • 23
  • 43