Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView Viewholder reusing

I am creating a RecyclerView which will expand itself when the user touches it and closes itself when the user touches it again. Below is my code:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecViewHolder> {
    ArrayList<String> values;
    ArrayList<Integer> expandedPosition;
    public static class RecViewHolder extends RecyclerView.ViewHolder {
        ...
        private boolean resultsOpened = false;
        ...
        RelativeLayout favHeaderLayout;
        RelativeLayout favResultsLayout;

        public RecViewHolder (View itemView) {
            super(itemView);
            favHeaderLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!resultsOpened) {
                        expandLayout();
                    } else {
                        favResultsLayout.setVisibility(View.GONE);
                        resultsOpened = false;
                    }
                }
            });

        }

        public void expandLayout() {
            favResultsLayout.setVisibility(View.VISIBLE);
            resultsOpened = true;
            //I populate my expanded layout here
        }
    }

    public RecyclerViewAdapter (Context context, ArrayList<String> values) {
        this.context = context;
        this.values= values;
    }

    @Override
    public RecViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_file, parent, false);
        RecViewHolder recViewHolder= new RecViewHolder(v);
        return recViewHolder;
    }

    @Override
    public void onBindViewHolder(RecViewHolder recViewHolder , int position) {
    }

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

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

}

When I touch the first view, it should expand itself. However, when the adapter has more data and I touch the first view, the view expands and another view at the bottom of the RecyclerView (e.g. the 8th view) expands too. How do I ensure that only the view that have been touched expand the the other stays close?

EDIT

I've tried storing the expanded Views position in an arraylist and in onBindViewHolder, check which views are expanded and expand them only:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecViewHolder> {
    ArrayList<String> values;
    ArrayList<Integer> expandedPosition;
    public static class RecViewHolder extends RecyclerView.ViewHolder {
        ...
        private boolean resultsOpened = false;
        ...
        RelativeLayout favHeaderLayout;
        RelativeLayout favResultsLayout;

        public RecViewHolder (View itemView) {
            super(itemView);


        }

    }

    public RecyclerViewAdapter (Context context, ArrayList<String> values) {
        this.context = context;
        this.values= values;
    }

    @Override
    public RecViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_file, parent, false);
        RecViewHolder recViewHolder= new RecViewHolder(v);
        return recViewHolder;
    }

    @Override
    public void onBindViewHolder(RecViewHolder recViewHolder , int position) {
        recViewHolder.favResultsLayout.setVisibility(View.GONE);
        for(int i= 0; i < expandedPosition.size(); i ++){
            recViewHolder.favResultsLayout.setVisibility(View.VISIBLE);
        }
        recViewHolder.favHeaderLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                     if (!expandedPosition.contains(position)) {
                        expandLayout(recViewHolder);
                        expandedPosition.add(position);
                    } else {
                        recViewHolder.favResultsLayout.setVisibility(View.GONE);
                        for(int i = 0; i < expandedPosition.size(); i ++){
                            if (expandedPosition.get(i) == position){
                                    expandedPosition.remove(i);
                            }
                        }
                    }
                }
            });
    }
    public void expandLayout() {
            favResultsLayout.setVisibility(View.VISIBLE);
            //I populate my expanded layout here
        }
    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
    }

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

}

Still no luck :(

like image 817
SpencerRoi Avatar asked Nov 01 '22 02:11

SpencerRoi


1 Answers

As the class name says it is all about recycling ...

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecViewHolder> {
    ArrayList<String> values;
    SparseBooleanArray expanded = new SparseBooleanArray();
    public static class RecViewHolder extends RecyclerView.ViewHolder {
        //EDIT!!!!!
        public RecViewHolder (View itemView, final RecyclerViewAdapter adapter) {
        //rest of the code ...
        favHeaderLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) { 
                final int currentPosition = getAdapterPosition();
                //is a view at current position expanded?
                if(adapter.expanded.get(currentPosition ))
                    //if so it shouldn't be
                    adapter.expanded.delete(getAdapterPosition(currentPosition));
                else
                    //if not, expand
                    adapter.expanded.put(currentPosition, true);
                //wheeee inform the adapter to rebind
                adapter.notifyItemChanged(currentPosition);
                //setupExpanded(expanded.get(currentPosition)); 
            }
        });
        }
        protected void setupExpanded(boolean state) {
        //ONLY hide show layouts based on state
        }
    }
    @Override
    public RecViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_file, parent, false);
        RecViewHolder recViewHolder= new RecViewHolder(v, this);
        return recViewHolder;
    }

    @Override
    public void onBindViewHolder(RecViewHolder recViewHolder , int position)    {
        //this line should be self explanatory
        recViewHolder.setupExpanded(expanded.get(position));
    }

    //rest of the code
}
like image 99
Selvin Avatar answered Nov 09 '22 16:11

Selvin