DarkLeafyGreen
DarkLeafyGreen

Reputation: 70416

RecyclerView does not recycle text view correctly

I have a problem with the RecyclerView and a custom TextView, which just gets a rotate attribute:

public class IconTextView extends TextView {

    boolean rotate = false;

    public IconTextView(Context context) {
        super(context);
    }

    public IconTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public IconTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * Start rotate animation.
     * @param rotate boolean
     */
    public void setRotate(boolean rotate) {
        this.rotate = rotate;
        if (rotate) {
            rotateInfinite();
        }
    }

    private void rotateInfinite() {
        Animation anim = new RotateAnimation(0.0f, 360.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        anim.setDuration(1000);
        anim.setRepeatMode(Animation.INFINITE);
        anim.setRepeatCount(Animation.INFINITE);
        anim.setInterpolator(new LinearInterpolator());
        startAnimation(anim);
    }
}

Adapter:

public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.RotatingViewHolder> {

    public ArrayList<Item> items = new ArrayList<>();

    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public RotatingViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new RotatingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.search_item_single, parent, false));
    }

    @Override
    public void onBindViewHolder(RotatingViewHolder holder, int position) {

        Item item = items.get(position);

        holder.mTextViewIcon.setText(item.icon);
        holder.mTextViewIcon.setRotate(true);
        holder.mTextViewTitle.setText(item.title);
    }

    public static class RotatingViewHolder extends RecyclerView.ViewHolder {

        @Bind(R.id.mTextViewIcon)
        IconTextView mTextViewIcon;

        @Bind(R.id.mTextViewTitle)
        TextView mTextViewTitle;

        public RotatingViewHolder(View mView) {
            super(mView);
            ButterKnife.bind(this, mView);
        }
    }

    public static class Item {

        String icon, title;
        boolean rotating;

        public Item(String icon, String title, boolean rotating) {
            this.icon = icon;
            this.title = title;
            this.rotating = rotating;
        }
    }
}

Activity:

public class MainActivity extends AppCompatActivity {

    @Bind(R.id.recyclerView)
    RecyclerView recyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        ItemAdapter itemAdapter = new ItemAdapter();

        recyclerView.setAdapter(itemAdapter);
        recyclerView.requestFocus();
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setItemAnimator(new DefaultItemAnimator());

        for (int i = 0; i < 40; i++) {
            itemAdapter.items.add(new ItemAdapter.Item("Foo", "Bar", true));
        }

        recyclerView.getAdapter().notifyDataSetChanged();
    }
}

So this actually works and the text is spinning. However, as soon as I scroll down a bit and up again the text views that where hidden have stopped rotating. Any idea what happens?

I pushed the small project to github, try it out: https://github.com/ArtworkAD/RecyclerViewTest

Upvotes: 0

Views: 581

Answers (1)

blizzard
blizzard

Reputation: 5375

The animation is cleared when the viewholder is recycled and the view's onDetachedFromWindow() is called internally. I'd just restarted the animation if rotate is true on view's onAttachedToWindow(). The animation seems to work fine.

IconTextView.java

  @Override protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    if (anim != null && rotate) {
      startAnimation(anim);
    }
  }

Upvotes: 1

Related Questions