Expandable RecyclerView List
The example below will create an expandable list which can expand and collapse when one of the list item is clicked.
The expand and collapse utility class.
import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.Transformation; public class ExpandableUtil { /** * Expand the view to its normal height * @param v The view to be expanded * @param from The initial height before it is expanded * @param to The final height after it is expanded */ public static void expand(final View v, Integer from, Integer to) { if (v == null) return; final int initialHeight = from == null ? 0 : from.intValue(); final int finalHeight = to; final int expandAmount = finalHeight - initialHeight; v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); v.getLayoutParams().height = initialHeight; if (v.getVisibility() != View.VISIBLE) v.setVisibility(View.VISIBLE); Animation a = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { if (interpolatedTime == 1) { v.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; } else { v.getLayoutParams().height = initialHeight + (int)(expandAmount * interpolatedTime); } v.requestLayout(); } @Override public boolean willChangeBounds() { return true; } }; a.setDuration((int)(finalHeight / v.getContext().getResources().getDisplayMetrics().density)); v.startAnimation(a); } /** * Collapse the view by the collapseAmount value * @param v The view to be collapsed * @param baseHeight The height to be maintained */ public static void collapse(final View v, final Integer collapseAmount) { if (v == null) return; final int initialHeight = v.getMeasuredHeight(); Animation a = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { Log.d("pye", "collapse collapseAmount: " + collapseAmount + " initialHeight: " + initialHeight); if (interpolatedTime == 1) { if (collapseAmount == initialHeight) { v.setVisibility(View.INVISIBLE); } } v.getLayoutParams().height = initialHeight - (int)(collapseAmount * interpolatedTime); v.requestLayout(); } @Override public boolean willChangeBounds() { return true; } }; a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density)); v.startAnimation(a); } /** * Collapse the view by the collapseAmount value with no animation * @param v The view to be collapsed * @param collapseAmount The height amount to be collapsed */ public static void collapseWithNoAnimation(final View v, Integer collapseAmount) { if (v == null) return; final int initialHeight = v.getMeasuredHeight(); v.getLayoutParams().height = initialHeight - collapseAmount; v.requestLayout(); } }
The layout activity_expandable_list.xml
The layout for the items on the list, activity_place_item.xml
The Activity, ExpandableListActivity.java
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.CardView; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import com.example.expandablerecyclerview.R; import java.util.ArrayList; public class ExpandableListActivity extends AppCompatActivity implements ListItemListener { ArrayListplaces; CardView cvContainer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_expandable_list); places = new ArrayList<>(); for (int i=0; i<6; i++) { places.add(new Place("place " + i)); } cvContainer = (CardView) findViewById(R.id.card_background); RecyclerView rvList = (RecyclerView) findViewById(R.id.rv_list); PlaceArrayAdapter placeArrayAdapter = new PlaceArrayAdapter(places); rvList.setLayoutManager(new LinearLayoutManager(this)); rvList.setItemAnimator(new DefaultItemAnimator()); rvList.setAdapter(placeArrayAdapter); placeArrayAdapter.setListItemListener(this); rvList.post(new Runnable() { @Override public void run() { int baseHeight = Math.round(getResources().getDimension(R.dimen.place_item_height)); int collapseAmount = baseHeight * (places.size() - 1); ExpandableUtil.collapseWithNoAnimation(cvContainer, collapseAmount); } }); } @Override public void onExpand() { int from = Math.round(getResources().getDimension(R.dimen.place_item_height)); int to = from * places.size(); ExpandableUtil.expand(cvContainer, from, to); } @Override public void onCollapse() { int baseHeight = Math.round(getResources().getDimension(R.dimen.place_item_height)); int collapseAmount = baseHeight * (places.size() - 1); ExpandableUtil.collapse(cvContainer, collapseAmount); } }
The ListItemListener.java
public interface ListItemListener { void onExpand(); void onCollapse(); }
The RecyclerView Adapter
import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.example.expandablerecyclerview.R; import java.util.ArrayList; public class PlaceArrayAdapter extends RecyclerView.Adapter{ private ArrayList places; private ListItemListener listItemListener; private boolean isExpanded = false; public PlaceArrayAdapter(ArrayList places) { this.places = places; } public void setListItemListener(ListItemListener listItemListener) { this.listItemListener = listItemListener; } // get the size of the list @Override public int getItemCount() { return places == null ? 0 : places.size(); } // specify the row layout file and click for each row @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_place_item, parent, false); ViewHolder myViewHolder = new ViewHolder(view); return myViewHolder; } // load data in each row element @Override public void onBindViewHolder(final ViewHolder holder, final int listPosition) { TextView item = holder.item; item.setText(places.get(listPosition).getName()); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isExpanded) { listItemListener.onCollapse(); isExpanded = false; } else { listItemListener.onExpand(); isExpanded = true; } } }); } // Static inner class to initialize the views of rows class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public TextView item; public ViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(this); item = (TextView) itemView.findViewById(R.id.row_item); } @Override public void onClick(View view) { Log.d("onclick", "onClick " + getLayoutPosition() + " " + item.getText()); } } }
The Place.java
public class Place { private String name; public Place(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Search within Codexpedia
Custom Search
Search the entire web
Custom Search
Related Posts