Bivin
Bivin

Reputation: 373

Android recycler view row item duplicates on scroll while view expanding relative layout

Recycler view contains two textfields in each row. When we click on one textview it expands an expandable layout.This expandable layout duplicates on scrolling.

Here is my adaptor class

public class AlbumsAdapter extends RecyclerView.Adapter<AlbumsAdapter.MyViewHolder> {

private Context mContext;
private List<Album> albumList;

RecyclerView rv;
public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView title, count;
    public ImageView thumbnail, overflow;
    ExpandableRelativeLayout expandableLayout11;


    public MyViewHolder(final View view) {
        super(view);
        title = (TextView) view.findViewById(R.id.title);
        count = (TextView) view.findViewById(R.id.count);
        thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
        expandableLayout11 = (ExpandableRelativeLayout)view. findViewById(R.id.expandableLayout11);


    }
}



public AlbumsAdapter(Context mContext, List<Album> albumList ) {
    this.mContext = mContext;
    this.albumList = albumList;

}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.album_card, parent, false);

    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
    final Album album = albumList.get(position);
    holder.title.setText(album.getName());
    holder.count.setText(album.getNumOfSongs() + " songs");

holder.title.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
          holder.expandableLayout11.toggle();

    }

});


   }

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

}

My main activity is

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    initCollapsingToolbar();

    recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

    albumList = new ArrayList<>();
    adapter = new AlbumsAdapter(this, albumList );

    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.addItemDecoration(new GridSpacingItemDecoration(1, dpToPx(10), true));
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setAdapter(adapter);

    prepareAlbums();

    try {
        Glide.with(this).load(R.drawable.cover).into((ImageView) findViewById(R.id.backdrop));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * Initializing collapsing toolbar
 * Will show and hide the toolbar title on scroll
 */
private void initCollapsingToolbar() {
    final CollapsingToolbarLayout collapsingToolbar =
            (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
    collapsingToolbar.setTitle("Developer List");
    AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
    appBarLayout.setExpanded(true);

    // hiding & showing the title when toolbar expanded & collapsed
    appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
        boolean isShow = false;
        int scrollRange = -1;

        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            if (scrollRange == -1) {
                scrollRange = appBarLayout.getTotalScrollRange();
            }
            if (scrollRange + verticalOffset == 0) {
                collapsingToolbar.setTitle("Developer List");
                isShow = true;
            } else if (isShow) {
                collapsingToolbar.setTitle("Developer List");
                isShow = false;
            }
        }
    });
}


private void prepareAlbums() {
    int[] covers = new int[]{
            R.drawable.album1,
            R.drawable.album2,
            R.drawable.album3,
            R.drawable.album4,
            R.drawable.album5,
            R.drawable.album6,
            R.drawable.album7,
            R.drawable.album8,
            R.drawable.album9,
            R.drawable.album10,
            R.drawable.album11};

    Album a = new Album("True Romance", 13, covers[0]);
    albumList.add(a);

    a = new Album("Xscpae", 8, covers[1]);
    albumList.add(a);

    a = new Album("Maroon 5", 11, covers[2]);
    albumList.add(a);

    a = new Album("Born to Die", 12, covers[3]);
    albumList.add(a);

    a = new Album("Honeymoon", 14, covers[4]);
    albumList.add(a);

    a = new Album("I Need a Doctor", 1, covers[5]);
    albumList.add(a);

    a = new Album("Loud", 11, covers[6]);
    albumList.add(a);

    a = new Album("Legend", 14, covers[7]);
    albumList.add(a);

    a = new Album("Hello", 11, covers[8]);
    albumList.add(a);

    a = new Album("Greatest Hits", 17, covers[9]);
    albumList.add(a);

    adapter.notifyDataSetChanged();
}
}

Upvotes: 1

Views: 1086

Answers (2)

Gaurav Singh
Gaurav Singh

Reputation: 2340

In your Album model class add a boolean flag say: isExpanded and add getter setter for the same lets assume them as :

// Getter for isExpanded flag
public boolean isExpanded() {
 return isExpanded;
}

// setter for isExpanded flag
public void setIsExpanded(boolean flag) {
 isExpanded = flag;
}

Then do following in your onBindViewHolder method:

@Override
public void onBindViewHolder(final MyViewHolder holder, final int position){

 final Album album = albumList.get(position);
 holder.title.setText(album.getName());
 holder.count.setText(album.getNumOfSongs() + " songs");

 if(album.isExpanded()) {

   holder.expandableLayout11.expand();

   } else {

   holder.expandableLayout11.collapse();
   }

 holder.title.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
      // toggle view
      holder.expandableLayout11.toggle();
      // toggle isExpanded flag
      album.setIsExpanded( ! album.isExpanded() )
  }
}

Upvotes: 2

Linh
Linh

Reputation: 61039

Items in RecyclerView is reused. So you should save the position of expandable items.
Then change the state of expandableLayout when row load

int[] expandablePositionArray; // define int array for save all position of expandable items

public AlbumsAdapter(Context mContext, List<Album> albumList ) {
    this.mContext = mContext;
    this.albumList = albumList;
    // init int array
    expandablePositionList = new int[albumList.size()];
}

@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
   ...

   // expand or collapse expandableLayout11 when row load base on expandable position 
   if(expandablePositionList[position] == 1){
       holder.expandableLayout11.expand();
   }else{
       holder.expandableLayout11.collapse();
   }

    holder.title.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
          holder.expandableLayout11.toggle();

          // save the position of expandable row
          if(expandablePositionList[position] == 1){
               expandablePositionList[position] = 0;
          }else{
               expandablePositionList[position] = 1;
          }
    }
}

Upvotes: 0

Related Questions