ExpandableCardView icon indicating copy to clipboard operation
ExpandableCardView copied to clipboard

Every 15th card is expanded in recyclerview

Open Ayusch opened this issue 6 years ago • 3 comments

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.

Ayusch avatar Aug 15 '18 11:08 Ayusch

Hey Ayusch,

Can you share some of the code? I think the Adapter class would be fine.

Regards,

Alessandro

AleSpero avatar Aug 15 '18 22:08 AleSpero

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 :)

Ayusch avatar Aug 16 '18 06:08 Ayusch

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 ?

DoctorcodeV07 avatar Feb 15 '21 08:02 DoctorcodeV07