portfoliobuilder portfoliobuilder - 6 months ago 58
Android Question

Scrolling will cause collapsed items in listView to de-collapse, RecyclerView.Adapter set up issue

I have an adapter that extends RecycleView.Adapter and I am running into an issue where scrolling will cause views to change their visibility. I use visibility of views to simulate a collapsed or de-collapsed state, and scrolling is somehow resetting the visibility of the final and first items only from a list of 15 items.

The items begin with a Title displayed with TextView. Clicking on that item will de-collapse that item to reveal the Description text also displayed with TextView (I just set the visibility of the view that has the Description text to VISIBLE). Clicking the Description text will collapse that item (visibility set to GONE) to reveal only the initial Title text.

How come when I scroll to my last item, it de-collapses even when not pressed. Additionally, if I have my first item de-collapsed scrolling to the bottom will collapse the first item. Here is my setup.

public class TextAdapter extends RecyclerView.Adapter<TextAdapter.ViewHolder> {
private static final String TAG = TextAdapter.class.getSimpleName();
private Context mContext;
private ArrayList<TextDescription> alTextDesc;

public TextAdapter(Context context, ArrayList<TextDescription> textDesc) {
mContext = context;
alTextDesc = textDesc;
}

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

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final TextDescription textDesc = alTextDesc.get(position);

holder.llParent.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View view) {
textDesc.isExpanded = !textDesc.isExpanded;
setExpanded(holder, textDesc);
}
});
setExpanded(holder, textDesc);

}

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

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}

private static void setExpanded(ViewHolder holder, TextDescription textDesc) {
if (textDesc != null) {
if (textDesc.isExpanded) {
// display full description
llContent.setVisibility(View.VISIBLE);
} else {
// display title
llContent.setVisibility(View.GONE);
}
}
}

public static class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout llParent;
LinearLayout llContent;

public ViewHolder(View v) {
super(v);

llParent = (LinearLayout) v.findViewById(R.id.ll_parent);
llContent = (LinearLayout) v.findViewById(R.id.ll_content);
}
}


My TextDescription model class is nothing more than a boolean

public boolean isExpanded;


Any suggestions on what I am doing incorrectly? Thank you in advance!

EDIT
I have also tried updating my ArrayList after changing the attribute expanded value and the results are still the same

holder.llParent.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View view) {
textDesc.isExpanded = !textDesc.isExpanded;
alTextDesc.set(position, textDesc); //tried to update the list with updated value
setExpanded(holder, textDesc);
}
});

Answer

The issue is due to recycling of views. You need to update your list alTextDesc after you change the expanded flag so that when the views are recycled, you have your flag state saved in the list alTextDesc and it will again collapse/expand based on that saved flag state.

    holder.llParent.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            textDesc.isExpanded = !textDesc.isExpanded;//Update the list with the updated object now 
            setExpanded(holder, textDesc);
        }
    });