Manabu-GT / ExpandableTextView

Android's TextView that can expand/collapse like the Google Play's app description
Apache License 2.0
4.08k stars 791 forks source link

Expand/Collapse Bug with recyclerview #14

Open slidenerd opened 9 years ago

slidenerd commented 9 years ago

testgif Hi, first of all , awesome library because yours probably is the only one that does this. I am using your library with a recyclerview in my code. I set 3 lines to be displayed in my custom_item snap 2015-03-13 at 12 50 19

As you saw the issue, some items expand once, the collapse incorrectly and never expand again, any ideas ,if you need any more source files , please let me know, thanks in advance for your help

public class AdapterFeed extends UltimateViewAdapter { private Context mContext; private ArrayList mListFeed = new ArrayList<>(); private LayoutInflater mLayoutInflater; private EventListener mEventListener; private SparseBooleanArray mTogglePositions = new SparseBooleanArray();

public AdapterFeed(Context context) {
    this.mContext = context;
    mLayoutInflater = LayoutInflater.from(context);
    setHasStableIds(true);
}

public void setFeed(ArrayList<Post> listFeed) {
    if (listFeed != null && listFeed.size() > 0) {
        mListFeed = listFeed;
        notifyItemRangeChanged(0, listFeed.size());
    }
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof HolderFeed) {
        Post currentPost = mListFeed.get(position);
        HolderFeed holderFeed = (HolderFeed) holder;
        holderFeed.textPost.setText(Post.isNotEmptyMessage(currentPost) ? currentPost.getMessage() : "No Text", mTogglePositions, position);

    }
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
    View layout = mLayoutInflater.inflate(R.layout.item_feed, viewGroup, false);
    HolderFeed holderFeed = new HolderFeed(layout);
    return holderFeed;
}

@Override
public int getAdapterItemCount() {
    return mListFeed.size();
}

static class HolderFeed extends RecyclerView.ViewHolder {

    private ExpandableTextView textPost;

    public HolderFeed(View itemView) {
        super(itemView);
        textPost = (ExpandableTextView) itemView.findViewById(R.id.expand_text_view);
    }

}

}

slidenerd commented 9 years ago

I forgot to mention one thing, I am using your library with this https://github.com/cymcsg/UltimateRecyclerView could that be any reason for a clash? Do let me know thanks

slidenerd commented 9 years ago

I may have figured out whats causing this, unlike the ListView where the getView will be called every time and you are the one whose deciding if the view should be recycled or not, thats not the case with a recyclerview, the onCreateViewHolder and onBindViewHolder are called initially when no recycled views are available but later the only method that gets triggered is the onBindViewHolder, does this have something to do with the SparseBooleanArray because I am binding it inside the onBindViewHolder, so the thing is, items that are towards the end of the list or the ones that are being created from recyled views expand and collapse correctly but not the ones at the beginning, take a look at this screenshot, the one at the start incurs both the onCreateViewHolder and the onBindViewHolder whereas the one at the bottom is simply recycled directly with the onBindViewHolder testgif

Manabu-GT commented 9 years ago

Thanks for the info. I will take a look this weekend and get back to you.

fengshenzhu commented 9 years ago

I met a problem when I set ExpandableTextView's orientation horizontal:

<com.netease.cartoonreader.view.ExpandableTextView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:expandableTextView="http://schemas.android.com/apk/res-auto"
        android:id="@+id/expand_text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        expandableTextView:animAlphaStart="1"
        expandableTextView:animDuration="200"
        expandableTextView:maxCollapsedLines="4">

        <TextView
            android:id="@id/expandable_text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <ImageButton
            android:id="@id/expand_collapse"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent" />
    </com.netease.cartoonreader.view.ExpandableTextView>

In a item of RecyclerView, when the state of ExpandableTextView is expandle, and scroll the RecyclerView to make this item rebind(onBindViewHolder again), click the ExpandableTextView will make the text invisible. The problem is solved by setting TextView's layout_width "wrap_content". But I don't know why.

aaronweihe commented 8 years ago

I had similar issue with ExpandableTextview in AOSP which this library is based on.

I solved it by simply using the plain old TextView and keeping expanded status my self. Whenever the onBindViewHolder is called, check the expanded status, and then setMaxLines to Integer.MAX_VALUE when it should be expanded or max lines you want when it should be collapsed. You may also opt-in for animation by calling notifyItemChanged(int position).

Hope this is helpful. :smiley_cat: Ref #18

mohanraj546 commented 8 years ago

is the issue fixed which was mentioned by slidenerd....?

nangsan commented 7 years ago

44 This thread has the proper solution to this issue

CleverMod commented 7 years ago

Encountered the same problem, how to solve?

Mixiaomi commented 7 years ago

@wmq389122157 @mohanraj546 @slidenerd @aaronhe42 If the content of the TextView is long enough, you can set mAnimationDuration = 0, setDuration (mAnimationDuration), and cancel the animation

CleverMod commented 7 years ago

@Mixiaomi Thank you very much. The problem is settled. Thanks again!

monikagupta94 commented 6 years ago

@Mixiaomi Thank you. It Worked.

pk4393 commented 5 years ago

Hi, I am also facing an issue. While using the ExpandableTextView inside RecyclerView, whenever I am trying to collapse the TextView it becomes invisible.

Greatkingcj commented 5 years ago

i solve this problem. when this view detach from window , animion might not finish。you can use ValueAnimator。here is the code: `@Override public void onClick(View view) {

    if (mStateTv.getVisibility() != View.VISIBLE) {
        return;
    }

    mCollapsed = !mCollapsed;
    mStateTv.setText(mCollapsed ? mExpandString : mCollapsedString);

// mStateTv.setCompoundDrawablesWithIntrinsicBounds(mCollapsed ? mExpandDrawable : mCollapseDrawable, null, null, null);

    if (mCollapsedStatus != null) {
        mCollapsedStatus.put(mPosition, mCollapsed);
    }

    // mark that the animation is in progress
    mAnimating = true;

    //Animation animation;
    if (mCollapsed) {
        finalHeight = mCollapsedHeight;
    } else {
        finalHeight = getHeight() +
                mTextHeightWithMaxLines - mTv.getHeight();
    }

    animateExpandView(this, getHeight(), finalHeight);
}

private void animateExpandView(View mTargetView, int mStartHeight, int mEndHeight) {
    mAnimating = true;
    ValueAnimator animator = ValueAnimator.ofInt(mStartHeight, mEndHeight);
    animator.setInterpolator(new AccelerateDecelerateInterpolator());
    animator.setDuration(mAnimationDuration);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            final int newHeight = (int) animation.getAnimatedValue();
            mTv.setMaxHeight(newHeight - mMarginBetweenTxtAndBottom);
            mTargetView.getLayoutParams().height = newHeight;
            mTargetView.requestLayout();
        }
    });
    animator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {
            Utils.Log.e("Expand animator onAnimationEnd");
            clearAnimation();
            // clear the animation flag
            mAnimating = false;
            Utils.Log.e("Expand onAnimationEnd");
            // notify the listener
            if (mListener != null) {
                mListener.onExpandStateChanged(mTv, !mCollapsed);
            }
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
    animator.start();
}

`