ExpandableCardView
ExpandableCardView copied to clipboard
Every 15th card is expanded in recyclerview
Hi,
I used this library for a recyclerview item and when I click on a card to expand, it expands every 5th card. I have a recyclerview with 400+ items.
The problem is with recyclerview recycling the view holder. If I set
holder.setIsRecyclable(false);
inside onBindViewHolder method
then everything works fine.
Hey Ayusch,
Can you share some of the code? I think the Adapter class would be fine.
Regards,
Alessandro
This is my layout for recyclerview item: car_info_item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/card_margin"
card_view:cardCornerRadius="3dp"
card_view:useCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.alespero.expandablecardview.ExpandableCardView
android:id="@+id/car"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:animationDuration="300"
app:expandOnClick="true"
app:icon="@drawable/ic_car"
app:inner_view="@layout/car_info_inner"
app:startExpanded="false"
app:title="Passengers"
card_view:elevation="6dp"
card_view:useCompatPadding="true" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
This is the inner layout :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/common_padding"
android:paddingLeft="@dimen/padding_medium"
android:paddingRight="@dimen/common_padding"
android:paddingTop="@dimen/common_padding">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/common_margin"
android:orientation="horizontal">
<TextView
style="@style/LabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Address :" />
<TextView
android:id="@+id/car_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/small_margin" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/common_margin"
android:orientation="horizontal">
<TextView
style="@style/LabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Coordinates :" />
<TextView
android:id="@+id/car_coordinates"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/small_margin" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/common_margin"
android:orientation="horizontal">
<TextView
style="@style/LabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Engine Type :" />
<TextView
android:id="@+id/car_engineType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/small_margin" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/common_margin"
android:orientation="horizontal">
<TextView
style="@style/LabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Exterior :" />
<TextView
android:id="@+id/car_exterior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/small_margin" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/common_margin"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
style="@style/LabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fuel :" />
<com.daimajia.numberprogressbar.NumberProgressBar
android:id="@+id/car_fuel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/small_margin"
custom:progress_current="0"
custom:progress_max="100"
custom:progress_reached_bar_height="5dp"
custom:progress_reached_color="#19E070"
custom:progress_text_color="#3498DB"
custom:progress_text_offset="1dp"
custom:progress_text_size="12sp"
custom:progress_text_visibility="visible"
custom:progress_unreached_bar_height="5dp"
custom:progress_unreached_color="#ff4c4c" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/common_margin"
android:orientation="horizontal">
<TextView
style="@style/LabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Interior :" />
<TextView
android:id="@+id/car_interior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/small_margin" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/common_margin"
android:orientation="horizontal">
<TextView
style="@style/LabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name :" />
<TextView
android:id="@+id/car_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/small_margin" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/common_margin"
android:orientation="horizontal">
<TextView
style="@style/LabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Vin :" />
<TextView
android:id="@+id/car_vin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/small_margin" />
</LinearLayout>
</LinearLayout>
Here is the adapter code :
package com.ayusch.wunderassignment.adapters;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.alespero.expandablecardview.ExpandableCardView;
import com.ayusch.wunderassignment.R;
import com.ayusch.wunderassignment.models.cars.CarsInfoResponse;
import com.daimajia.numberprogressbar.NumberProgressBar;
import org.w3c.dom.Text;
import java.util.List;
public class CarInfoAdapter extends RecyclerView.Adapter<CarInfoAdapter.CarsViewHolder> {
List<CarsInfoResponse.PlaceMarks> placeMarksList;
CarClickedListener listener;
Context context;
public CarInfoAdapter(List<CarsInfoResponse.PlaceMarks> placeMarksList, CarClickedListener listener, Context context) {
this.placeMarksList = placeMarksList;
this.listener = listener;
this.context = context;
}
@NonNull
@Override
public CarsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.car_info_item, parent, false);
return new CarsViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull CarsViewHolder holder, int position) {
holder.setIsRecyclable(false);
final CarsInfoResponse.PlaceMarks placeMarks = placeMarksList.get(position);
holder.expandableCardView.setTitle(placeMarks.getAddress());
holder.expandableCardView.setOnExpandedListener(new ExpandableCardView.OnExpandedListener() {
@Override
public void onExpandChanged(View view, boolean isExpanded) {
TextView address = view.findViewById(R.id.car_address);
TextView coordinates = view.findViewById(R.id.car_coordinates);
TextView engineType = view.findViewById(R.id.car_engineType);
TextView exterior = view.findViewById(R.id.car_exterior);
TextView interior = view.findViewById(R.id.car_interior);
TextView name = view.findViewById(R.id.car_name);
TextView vin = view.findViewById(R.id.car_vin);
NumberProgressBar fuel = view.findViewById(R.id.car_fuel);
address.setText(placeMarks.getAddress());
coordinates.setText(String.format("%s , %s", String.valueOf(placeMarks.getCoordinates().get(0)), String.valueOf(placeMarks.getCoordinates().get(1))));
engineType.setText(placeMarks.getEngineType());
exterior.setText(placeMarks.getExterior());
fuel.setProgress(placeMarks.getFuel());
interior.setText(placeMarks.getInterior());
name.setText(placeMarks.getName());
vin.setText(placeMarks.getVin());
}
});
}
@Override
public int getItemCount() {
return placeMarksList.size();
}
public class CarsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ExpandableCardView expandableCardView;
public CarsViewHolder(View itemView) {
super(itemView);
expandableCardView = itemView.findViewById(R.id.car);
}
@Override
public void onClick(View v) {
listener.onCarClicked(placeMarksList.get(getAdapterPosition()));
}
}
public interface CarClickedListener {
void onCarClicked(CarsInfoResponse.PlaceMarks placeMark);
}
}
inside onBindViewHolder
I have set the holder to not recycle.
Let me know if you need any other code. I think the problem is when the view holder is recycled, the card still maintains its state.
Eg. When the first card is clicked, it's states is set to expanded. Then when we scroll, on the 15th element, the same viewholder is used to render data, but the expanded attribute is still maintained. If you could find a callback when the view is destroyed and in that callback just invalidate the View, it could solve the problem.
If I find a solution I will send a PR :)
seems I am bit late for the party! .
I tried using holder.setIsRecyclable(false), I works but at the same time, the top list close automatically when I scroll down the list, Is the solution has been derived ?