In my previous article we discuss about 3D effect and SlidingRoot drawer animation and many more animations libraries but today i come with ExpandingCollection Android Library which is a card peek/pop controller. For more you can see demo above :
Requirements
- Android 4.0 IceCreamSandwich (API lvl 14) or greater
- Your favorite IDE
Installation
maven repo:
Gradle:
'com.ramotion.expandingcollection:expanding-collection:0.9.0'
SBT:
libraryDependencies += "com.ramotion.expandingcollection" % "expanding-collection" % "0.9.0"
Maven:
<dependency> <groupId>com.ramotion.expandingcollection</groupId> <artifactId>expanding-collection</artifactId> <version>0.9.0</version> </dependency>
How to Add ExpandingCollection Android Library
Add a background switcher element ECBackgroundSwitcherView
and a main pager element ECPagerView
to your layout. ECPagerView
should always have match_parent
width and wrap_content
height. You can adjust the vertical position yourself using alignment/gravity or top margin. ECBackgroundSwitcherView
is the dynamic background switcher, so you probably want it to be as big as its parent.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.ramotion.expandingcollection.ECBackgroundSwitcherView android:id="@+id/ec_bg_switcher_element" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.ramotion.expandingcollection.ECPagerView android:id="@+id/ec_pager_element" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true"/> </RelativeLayout>
Tune ECPagerView
: setup size of card in collapsed state and height of header in expanded state.
<com.ramotion.expandingcollection.ECPagerView xmlns:ec="http://schemas.android.com/apk/res-auto" android:id="@+id/ec_pager_element" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" ec:cardHeaderHeightExpanded="150dp" ec:cardHeight="200dp" ec:cardWidth="250dp" />
Expanded card contains two parts: a header part with a background (initially visible when card is collapsed) and a ListView element as content (visible only when card is expanded), so you need an xml layout for the list items.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list_item_text" android:layout_width="match_parent" android:layout_height="100dp" android:layout_gravity="center_vertical|center_horizontal" android:background="@color/colorPrimary" android:textAlignment="center" /> </FrameLayout>
Also, you need to implement a custom list adapter for the list items by extending the parametrized com.ramotion.expandingcollection.ECCardContentListItemAdapter.java
class, where T
is type of datasource object for list items inside the card. In the example below, T
is just a string object. It’s a pretty straightforward implementation with a common view holder pattern.
public class CardListItemAdapter extends ECCardContentListItemAdapter<String> { public CardListItemAdapter(@NonNull Context context, @NonNull List<String> objects) { super(context, R.layout.list_item, objects); } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { ViewHolder viewHolder; View rowView = convertView; if (rowView == null) { LayoutInflater inflater = LayoutInflater.from(getContext()); rowView = inflater.inflate(R.layout.list_item, null); viewHolder = new ViewHolder(); viewHolder.itemText = (TextView) rowView.findViewById(R.id.list_item_text); rowView.setTag(viewHolder); } else { viewHolder = (ViewHolder) rowView.getTag(); } String item = getItem(position); if (item != null) { viewHolder.itemText.setText(item); } return rowView; } static class ViewHolder { TextView itemText; } }
Your data class must implement the com.ramotion.expandingcollection.ECCardData.java
interface where T
is type of datasource object for list items inside the card.
public class CardDataImpl implements ECCardData<String> { private String cardTitle; private Integer mainBackgroundResource; private Integer headBackgroundResource; private List<String> listItems; @Override public Integer getMainBackgroundResource() { return mainBackgroundResource; } @Override public Integer getHeadBackgroundResource() { return headBackgroundResource; } @Override public List<String> getListItems() { return listItems; } }
Almost done! The last thing we need to do is provide our dataset to a pager element through a pager adapter. It’s just an implementation of the abstract class com.ramotion.expandingcollection.ECPagerViewAdapter.java
with one abstract method, so it can be easily implemented inside your activity.
public class MainActivity extends Activity { private ECPagerView ecPagerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Get pager from layout ecPagerView = (ECPagerView) findViewById(R.id.ec_pager_element); // Generate example dataset List<ECCardData> dataset = CardDataImpl.generateExampleData(); // Implement and pager adapter and set it to pager view ecPagerView.setPagerViewAdapter(new ECPagerViewAdapter(getApplicationContext(), dataset) { @Override public void instantiateCard(LayoutInflater inflaterService, ViewGroup head, ListView list, ECCardData data) { // Data object for current card CardDataImpl cardData = (CardDataImpl) data; // Set adapter and items to current card content list list.setAdapter(new CardListItemAdapter(getApplicationContext(), cardData.getListItems())); // Also some visual tuning can be done here list.setBackgroundColor(Color.WHITE); // Here we can create elements for head view or inflate layout from xml using inflater service TextView cardTitle = new TextView(getApplicationContext()); cardTitle.setText(cardData.getCardTitle()); cardTitle.setTextSize(COMPLEX_UNIT_DIP, 20); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT); layoutParams.gravity = Gravity.CENTER; head.addView(cardTitle, layoutParams); // Card toggling by click on head element view head.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { ecPagerView.toggle(); } }); } }); // Add background switcher to pager view ecPagerView.setBackgroundSwitcherView((ECBackgroundSwitcherView) findViewById(R.id.ec_bg_switcher_element)); } // Card collapse on back pressed @Override public void onBackPressed() { if (!ecPagerView.collapse()) super.onBackPressed(); } }
You can find this and other, more complex, examples in this repository .
Hope you like this tutorial then please comment us with your thoughts.
Share your thoughts