I am trying to make expandable CardView using Recyclerview. I am able to see the list but when I click on some cardview and scroll then some other view is also expanded. Like when I click on position'0' and scrolls then position '17' also gets expanded..
Here is my code:
My chapter_cardview.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:id="@+id/cv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginEnd="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/chapter_detail"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="TextView"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/chapter_title" />
<TextView
android:id="@+id/chapter_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:text="TextView"
app:layout_constraintBottom_toTopOf="@+id/chapter_detail"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
</android.support.constraint.ConstraintLayout>
My MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
static private List<chapter_title>mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public CardView mCardView;
private TextView mchapter_tile;
private TextView mchapter_detail;
public ViewHolder(View itemview) {
super(itemview);
mCardView = itemView.findViewById(R.id.cv);
mchapter_tile = itemview.findViewById(R.id.chapter_title);
mchapter_detail = itemview.findViewById(R.id.chapter_detail);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<chapter_title> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
ViewHolder vh = null;
View view = (View) LayoutInflater.from(parent.getContext())
.inflate(R.layout.chapter_cardview, parent, false);
vh = new ViewHolder(view);
Log.e("viewType: ", ""+viewType);
if (viewType == 1)
vh.mchapter_detail.setVisibility(View.VISIBLE);
else
vh.mchapter_detail.setVisibility(View.GONE);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mchapter_tile.setText(mDataset.get(position).title);
holder.mCardView.setTag(position);
holder.mCardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = (Integer)v.getTag();
boolean isShown = MyAdapter.mDataset.get(position).isExpanded;
Log.e("Clicked on:", ""+ position);
if(isShown)
{
MyAdapter.mDataset.get(position).isExpanded = false;
((CardView)v).findViewById(R.id.chapter_detail).setVisibility(View.GONE);
}
else
{
((CardView)v).findViewById(R.id.chapter_detail).setVisibility(View.VISIBLE);
MyAdapter.mDataset.get(position).isExpanded = true;
}
}
});
}
@Override
public int getItemViewType(int position)
{
// Log.e("getItemType, position", position+"");
if(mDataset.get(position).isExpanded==true)
return 1;
else
return 0;
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
// Log.e("list size", mDataset.size()+"");
return mDataset.size()-50;
}
}
`
There are a few changes in the adapter file. While binding the view we first check for isExpanded according to the result we setVisibility of the view. Below is the code for Adapter.
public class MyAdapter extends RecyclerView.Adapter { private List mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public CardView mCardView;
private TextView mchapter_tile;
private TextView mchapter_detail;
public ViewHolder(View itemview) {
super(itemview);
mCardView = itemView.findViewById(R.id.cv);
mchapter_tile = itemview.findViewById(R.id.chapter_title);
mchapter_detail = itemview.findViewById(R.id.chapter_detail);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<chapter_title> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
ViewHolder vh = null;
View view = (View) LayoutInflater.from(parent.getContext())
.inflate(R.layout.stack_question_2, parent, false);
vh = new ViewHolder(view);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
final chapter_title chapter_title = mDataset.get(position);
holder.mchapter_tile.setText(chapter_title.title);
holder.mCardView.setTag(position);
if (chapter_title.isExpanded)
holder.mchapter_detail.setVisibility(View.VISIBLE);
else
holder.mchapter_detail.setVisibility(View.GONE);
holder.mCardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mDataset.get(position).isExpanded)
{
mDataset.get(position).isExpanded = false;
((CardView)v).findViewById(R.id.chapter_detail).setVisibility(View.GONE);
}
else
{
((CardView)v).findViewById(R.id.chapter_detail).setVisibility(View.VISIBLE);
mDataset.get(position).isExpanded = true;
}
//notifyDataSetChanged();
notifyItemChanged(position);
}
});
}
@Override
public int getItemViewType(int position)
{
// Log.e("getItemType, position", position+"");
if(mDataset.get(position).isExpanded==true)
return 1;
else
return 0;
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
// Log.e("list size", mDataset.size()+"");
return mDataset.size();
}
}
Hope that helps.