Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

something weird happens while scrolling RecyclerView too fast

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());
        }
    }
}
like image 975
iamkaan Avatar asked Jan 28 '15 12:01

iamkaan


1 Answers

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.

like image 93
iamkaan Avatar answered Oct 22 '22 03:10

iamkaan