Skip to content
Davide Steduto edited this page Jul 8, 2016 · 44 revisions

In this page

  • Prerequisites
  • Simple initialization
    • Implement and customize your item
    • Item layout
  • Advanced/Custom usage
    • Adapter configuration
    • Extending FlexibleAdapter

Prerequisites

Before starting to use the FlexibleAdapter make sure you linked it to your project. You can find more info on setup here: https://github.com/davideas/FlexibleAdapter#setup

Simple initialization

Initialization is done as following:

//Optional but strongly recommended: Compose the initial list
List<IFlexible> myItems = getDatabaseList();

//Initialize the Adapter
FlexibleAdapter<IFlexible> adapter = new FlexibleAdapter<>(myItems);

//Initialize the RecyclerView and attach the Adapter to it as usual
recyclerView.setAdapter(adapter);

Since the Adapter needs the items to implement the IFlexible interface in order to serve all the new functionalities, the list coming from getDatabaseList() should return a @NonNull copy* of the original List and must contain items of type IFlexible.

* = The copy of the list is necessary because the Adapter manipulates it when operations like filter, expanding/collapsing and others special operations are requested.
Note that, only the references of the items are copied, while the instances remain unique:

public List<Item> getDatabaseList() {
	return new ArrayList<>(originalList);
}

Implement and customize your item (MyItem and MyViewHolder classes)

Simple initialization is possible with no customization and no overriding. To use FlexibleAdapter you're required to create the adapter's item class along with it's view holder, both needing to extend certain FlexibleAdapter's interfaces. For a complete knowledge of more specific and advanced items types, please see Item interfaces and their abstract implementation.

A simple item and view holder could be implemented as following:

/**
 * Where AbstractFlexibleItem implements IFlexible!
 */
public class MyItem extends AbstractFlexibleItem<MyItem.MyViewHolder> {

    private String id;
    private String title;

    public MyItem(String id, String title) {
        this.id = id;
        this.title = title;
    }

    /**
     * When an item is equals to another?
     * Write your own concept of equals, mandatory to implement.
     * This will be explained in next Wiki page.
     */
    @Override
    public boolean equals(Object inObject) {
        if (inObject instanceof MyItem) {
            MyItem inItem = (MyItem) inObject;
            return this.id.equals(inItem.id);
        }
        return false;
    }

    /**
     * For the item type we need an int value: the layoutResID is sufficient.
     */
    @Override
    public int getLayoutRes() {
        return R.layout.item_flexible;
    }

    /**
     * The Adapter is provided, because it will become useful for the MyViewHolder.
     * The unique instance of the LayoutInflater is also provided to simplify the
     * creation of the VH.
     */
    @Override
    public MyViewHolder createViewHolder(FlexibleAdapter adapter, LayoutInflater inflater,
                               ViewGroup parent) {
        return new MyViewHolder(inflater.inflate(getLayoutRes(), parent, false), adapter);
    }

    /**
     * Also here the Adapter is provided to get more specific information from it.
     * NonNull Payload is provided as well, you should use it more often.
     */
    @Override
    public void bindViewHolder(FlexibleAdapter adapter, MyViewHolder holder, int position,
                               List payloads) {
        holder.mTitle.setText(title);
        //Appear disabled if item is disabled
        holder.mTitle.setEnabled(isEnabled());
    }

    /**
     * The MyViewHolder used by this item.
     * Extending from FlexibleViewHolder is recommended especially when you will use
     * more advanced features.
     */
    public class MyViewHolder extends FlexibleViewHolder {

        public TextView mTitle;

        public MyViewHolder(View view, FlexibleAdapter adapter) {
            super(view, adapter);
            mTitle = (TextView) view.findViewById(R.id.title);
        }
    }
}

Note that the definition of MyItem extends the AbstractFlexibleItem, an abstract utility class which requires a type of the view holder you'd be using passed as a generic parameter. Despite this example, MyViewHolder doesn't need to be declared as a inner class of MyItem.

MyViewHolder in turn extends the FlexibleViewHolder, another utility class provided for easy setup with FlexibleAdapter. It is recommended to extend this class to enable more advanced functionalities (described later).

Item layout

Within the getLayoutRes function you specify the item's layout (layout/item_flexible.xml), which in this basic case is in the format of:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="4dp">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Medium Text"/>

    </LinearLayout>

</android.support.v7.widget.CardView>

Having the MyItem declared, you can use FlexibleAdapter.

To see the FlexibleAdapter working, you may temporarily populate the item list by modifying the getDatabaseList as follows:

public List<IFlexible> getDatabaseList() {
    ArrayList<IFlexible> l = new ArrayList<>();
    l.add(new MyItem("1", "Hello"));
    l.add(new MyItem("2", "World"));
    return l;
}

Advanced/Custom usage

Adapter configuration

FlexibleAdapter has many options that can be enabled/disabled at runtime. The options listed below are just a non-exhaustive example, for the full list with the explanations please refer to the API, JavaDoc or the dedicated Wiki page per functionality.

//Compose the initial list
List<IFlexible> items = getDatabaseList();

//Initialize the Adapter with the callbacks event listener
FlexibleAdapter<IFlexible> adapter = new FlexibleAdapter<>(items, ObjectListeners**);

//Non-exhaustive configuration that don't need RV instance
adapter.initializeListeners(ObjectListeners**)//If you didn't use the Constructor
	.setDisplayHeadersAtStartUp(true)//Show Headers at startUp!
	.expandItemsAtStartUp()//Items must be pre-initialized with expanded=true
	.setAutoCollapseOnExpand(false)//Closes all others expandable item before expanding a new one
	.setMinCollapsibleLevel(1)//Auto-collapse only items with level >= 1 (Don't collapse level 0)
	.setAutoScrollOnExpand(true)//Needs a SmoothScrollXXXLayoutManager
	.setAnimationOnScrolling(true)//Enable Adapter Animation: entry + forward scrolling
	.setAnimationOnReverseScrolling(true);//Enable Animation for reverse scrolling

//Initialize the RecyclerView and attach the Adapter to it as usual
recyclerView.setAdapter(adapter);

//Non-exhaustive configuration that need RV instance
adapter.setFastScroller(fastScroller)//Add FastScroller
	.setLongPressDragEnabled(true)//Enable long press to drag items
	.setHandleDragEnabled(true)//Enable handle drag
	.setSwipeEnabled(true)//Enable swipe items
	.enableStickyHeaders()//Make headers sticky (headers need to be shown)!
	.setEndlessScrollListener(listener, new ProgressItem())//Endless scroll
	.setEndlessScrollThreshold(1);//Default=1

** = ObjectListeners usually is the Activity or the Fragment, but it can be any object of your preference that handles all the event coming from the Adapter and ViewHolders. The wiki page Callbacks will show in the details the available listener that you can implement.

Extending FlexibleAdapter

You can always extend the FlexibleAdapter to override and customize some methods.

public class CustomAdapter extends FlexibleAdapter<IFlexible***> {

	public CustomAdapter(List<IFlexible***> items, Object listeners) {
		super(items, listeners);
	}
	...
}
public class FlexibleAdapter<T extends IFlexible***>
		extends AnimatorAdapter
		implements ItemTouchHelperCallback.AdapterCallback {
}

*** = Pay attention of the multiple item types the Adapter will handle: if you have more items to display, they all must eventually implement IFlexible as most common interface. For instance, the most common class in the following example, Header item with its Child item, is AbstractFlexibleItem so you can declare it in the class signature of CustomAdapter:

public class HeaderItem extends AbstractHeaderItem<HeaderItem.HeaderViewHolder> {
}

public class ChildItem extends AbstractSectionableItem<ChildItem.ViewHolder, HeaderItem> {
}

public class CustomAdapter extends FlexibleAdapter<AbstractFlexibleItem> {
}

Where AbstractHeaderItem, AbstractSectionableItem and AbstractFlexibleItem (all explained in the next Wiki page) are defined as following:

public abstract class AbstractHeaderItem<VH extends FlexibleViewHolder>
		extends AbstractFlexibleItem<VH>
		implements IHeader<VH> {
}

public abstract class AbstractSectionableItem<VH extends RecyclerView.ViewHolder, H extends IHeader>
		extends AbstractFlexibleItem<VH>
		implements ISectionable<VH, H> {
}

public abstract class AbstractFlexibleItem<VH extends RecyclerView.ViewHolder>
		implements IFlexible<VH> {
}

As you see, IFlexible interface is inherited from the chain of the implementation of the abstract classes.

Clone this wiki locally