0

I have successfully implemented RecyclerView in my app. The RecyclerView has three items, viz. title (TextView), ImageButton, description(TextView).

The title and ImageButton are always visible while the visibility of the description (set GONE by default) is toggled by clicking the ImageButton.

The problem I have is that when you click the ImageButton in one item and the description becomes visible, when you scroll down or up, the fifth (up or down) item has it description visible even when I didn't click the ImageButton to make it visible.

MY CODES:

book_card.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardCornerRadius="4dp"
    card_view:cardElevation="4dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/book_image"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:id="@+id/book_title"
            android:textStyle="bold"/>

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_arrow_name"
            android:id="@+id/arrow_button"
            android:layout_below="@+id/book_title"
            android:layout_centerHorizontal="true"
            android:onClick="onArrowClick"
            android:padding="5dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/arrow_button"
            android:visibility="gone"
            android:id="@+id/book_descrip"/>

    </RelativeLayout>

</android.support.v7.widget.CardView>

BookItem

public class BookItems implements Parcelable, Collection<BookItems> {
    private String book_title;
    private String book_descrip;

    public String getBook_title() {
        return book_title;
    }

    public void setBook_title(String book_title) {
        this.book_title = book_title;
    }

    public String getBook_descrip() {
        return book_descrip;
    }

    public void setBook_descrip(String book_descrip) {
        this.book_descrip = book_descrip;
    }
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.book_title);
        dest.writeString(this.book_descrip);
    }

    public BookItems() {
    }

    protected BookItems(Parcel in) {
        this.book_title = in.readString();
        this.book_descrip = in.readString();
    }

    public static final Parcelable.Creator<BookItems> CREATOR = new Parcelable.Creator<BookItems>() {
        @Override
        public BookItems createFromParcel(Parcel source) {
            return new BookItems(source);
        }

        @Override
        public BookItems[] newArray(int size) {
            return new BookItems[size];
        }
    };

    @Override
    public boolean add(BookItems object) {
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends BookItems> collection) {
        return false;
    }

    @Override
    public void clear() {

    }

    @Override
    public boolean contains(Object object) {
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> collection) {
        return false;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @NonNull
    @Override
    public Iterator<BookItems> iterator() {
        return null;
    }

    @Override
    public boolean remove(Object object) {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> collection) {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> collection) {
        return false;
    }

    @Override
    public int size() {
        return 0;
    }

    @NonNull
    @Override
    public Object[] toArray() {
        return new Object[0];
    }

    @NonNull
    @Override
    public <T> T[] toArray(T[] array) {
        return null;
    }
}

BookAdapter

public class BookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

    private Context mContext;
    private OnItemClickedListener mItemClickedListener;

    //List of books
    private List<BookItems> mBookItems;

    private int lastPosition = -1;


    public BookAdapter(List<BookItems> bookItems, Context context) {
        super();

        //Getting all books
        this.mBookItems = bookItems;
        this.mContext = context;
        this.mItemClickedListener = null;
    }

    public void setItemClickedListener (OnItemClickedListener onItemClickedListener) {
        this.mItemClickedListener = onItemClickedListener;
    }


    @Override
    public RecyclerView.ViewHolder  onCreateViewHolder (ViewGroup parent, int viewType) {
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.book_card, parent, false);
            return new CardViewHolder(v);
    }


    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            final BookItems bookList = mBookItems.get(position);
            ((CardViewHolder) holder).bookTitle.setText(Html.fromHtml(bookList.getBook_title()));
            ((CardViewHolder) holder).bookDescrip.setText(Html.fromHtml(bookList.getBook_descrip()));

            ((CardViewHolder) holder).bookDescrip.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mItemClickedListener != null) {
                        mItemClickedListener.onItemClicked(bookList.getBookId(), "Book");
                    }
                }
            });

            ((CardViewHolder) holder).bookTitle.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mItemClickedListener != null) {
                        mItemClickedListener.onItemClicked(bookList.getBookId(), "Book");
                    }
                }
            });
            setAnimation(holder.itemView, position);
    }

    private void setAnimation(View viewToAnimate, int position) {
        if (position > lastPosition) {
            Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.recycler_anim_up);
            viewToAnimate.startAnimation(animation);
            lastPosition = position;
        }
    }

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

    @Override
    public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder) {
        holder.itemView.clearAnimation();
    }

    public class CardViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        @BindView(R.id.book_title) TextView bookTitle;
        @BindView(R.id.book_descrip) TextView bookDescrip;
        @BindView(R.id.arrow_button) ImageButton imageButton;

        public CardViewHolder (final View bookView) {
            super(bookView);
            ButterKnife.bind(this, bookView);
            imageButton.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if (v.getId() == imageButton.getId()) {
                int visibility = bookDescrip.getVisibility();
                if (visibility == View.VISIBLE) {
                    bookDescrip.setVisibility(View.GONE);

                } else {
                    bookDescrip.setVisibility(View.VISIBLE);
                }
            }
        }

    }
}

Please is there anyway to stop this misbehavour?

X09
  • 3,827
  • 10
  • 47
  • 92
  • You can set a Tag and then check the state of it. Then its a simple case of (if tag == 1 view gone) -- check here on how to set and get a tag for a view http://stackoverflow.com/questions/26889361/getting-a-reference-to-viewholder-on-recyclerview-click -- if you have an array for your items you can do the same as the tag e.g add an array item (imgvis = no) uppon click (holder.imgvis=yes) then you do the if check as the tags (if iholder.mgvis == yes view gone) – Tasos Sep 10 '16 at 08:44
  • Thanks, I don't seem to understand you. Please can you explain further? – X09 Sep 10 '16 at 08:46
  • Its simple -- In your adapter click for the image button -- when you click to show the discription set the description view with a tag eg (description.setTag(1);) add a check in the adapter (if description.getTag() == 1 set discription view Visible else make GONE) --- when you make Invisible again set the tag to 0 -- Tags just store some data for each view. Or if you have an array for your items you can do the same as the tags. Store info and then set it as you click and then check if else do wahtever – Tasos Sep 10 '16 at 08:53
  • Sorry, please can you show me a practical example in code? – X09 Sep 10 '16 at 08:57

1 Answers1

0

I followed Tasos suggestion and this is how it was fixed.

In BookItem I added this:

private boolean descVisible = false;

public boolean isDescVisible() {
    return descVisible;
}

public void setDescVisible(boolean descVisible) {
    this.descVisible = descVisible;
}

Then in BookAdapter onBindViewHolder, I did this:

if (bookList.isVisible()) {
            ((CardViewHolder) holder).bookDescrip.setVisibility(View.VISIBLE);
        } else {
            ((CardViewHolder) holder).bookDescrip.setVisibility(View.GONE);
        }

        ((CardViewHolder) holder).imageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (bookList.isDescVisible()) {
                    ((CardViewHolder) holder).bookDescrip.setVisibility(View.GONE);
                    bookList.setDescVisible(false);

                } else {
                    ((CardViewHolder) holder).bookBody.setVisibility(View.VISIBLE);
                    bookList.setDescVisible(true);
                }
            }
        });
X09
  • 3,827
  • 10
  • 47
  • 92