<commit_before>[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-FlexibleAdapter-green.svg?style=flat)](https://android-arsenal.com/details/1/2207)

# Flexible Adapter

###### A pattern for every RecyclerView - Master branch: v4 of 2015.10.18

#### Main functionalities
* Base item selection (but also SINGLE & MULTI selection mode) in the Recycler View with ripple effect.
* Undo the deleted items with custom animations.
* Customizable FastScroller (imported library, see change log for details).
* SearchFilter with string selection in Item titles and subtitles.

#### How is made
The base functionality is taken from different Blogs (see at the bottom of the page), merged and methods have been improved for speed and scalability, for all Activities that use a RecyclerView.

* At lower class there is SelectableAdapter that provides selection functionalities and it's able to _maintain the state_ after the rotation, you just need to call the onSave/onRestore methods from the Activity!
* Then, the class FlexibleAdapter handles the content paying attention at the animations (calling notify only for the position. _Note:_ you still need to set your animation to the RecyclerView when you create it in the Activity).
* Then you need to extend over again this class. Here you add and implement methods as you wish for your own ViewHolder and your Domain/Model class (data holder).

I've put the Set click listeners at the creation and not in the Binding method, because onBindViewHolder is called at each invalidate (each notify..() methods).

Finally note that, this adapter handles the basic clicks: _single_ and _long clicks_. If you need a double tap you need to implement the android.view.GestureDetector.

# Screenshots
![Main screen](/screenshots/main_screen.png) ![Multi Selection](/screenshots/multi_selection.png)
![Search screen](/screenshots/search.png) ![Undo Screen](/screenshots/undo.png)

#Setup
Ultra simple:
No needs to create and import a library for just 2 files, so just *copy* SelectableAdapter.java & FlexibleAdapter.java in your *common* package and start to *extend* FlexibleAdapter from your custom Adapter (see my ExampleAdapter).

Remember to initialize `mItems` (List already included in FlexibleAdapter) in order to manage list items. Method `updateDataSet(..)` can help in this.

#### Pull requests / Issues / Improvement requests
Feel free to contribute and ask!

# Usage for Single Selection
See [Wiki](../../wiki) for full details! In your Activity/Fragment creation set the Mode SINGLE.
In onListItemClick, call *toggleSeletion* to register the selection on that position:
``` java
public class MainActivity extends AppCompatActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		...
		mAdapter = new YoursAdapter(..., ..., ...);
		mAdapter.setMode(YoursAdapter.MODE_SINGLE);
		...
	}

	@Override
	public boolean onListItemClick(int position) {
		toggleSelection(position);
	}
}
```

# Usage for Multi Selection
See [Wiki](../../wiki) for full details! In your Activity/Fragment change the Modes for the _ActionMode_ object.
``` java
public class MainActivity extends AppCompatActivity implements
		ActionMode.Callback {
	...
	@Override
	public boolean onCreateActionMode(ActionMode mode, Menu menu) {
		mode.getMenuInflater().inflate(R.menu.menu_context, menu);
		mAdapter.setMode(YourAdapterClass.MODE_MULTI);
		return true;
	}
	
	@Override
	public void onDestroyActionMode(ActionMode mode) {
		mAdapter.setMode(YourAdapterClass.MODE_SINGLE);
		mAdapter.clearSelection();
		mActionMode = null;
	}
}
```

# Usage for Undo
See [Wiki](../../wiki) for full details!
``` java
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
	switch (item.getItemId()) {
		...
		case R.id.action_delete:
			for (int i : mAdapter.getSelectedItems()) {
				//Remove items from your Database. Example:
				DatabaseService.getInstance().removeItem(mAdapter.getItem(i));
			}

			//Keep synchronized the Adapter: Remove selected items from Adapter
			mAdapter.removeItems(mAdapter.getSelectedItems());

			//Start countdown with startUndoTimer(millisec)
			mAdapter.startUndoTimer(7000); //Default 5''
			mActionMode.finish();
			return true;
	}
}
```

# Usage for FastScroller
See [Wiki](../../wiki) for full details! First add the drawable files to the project, then the layout, finally add the implementation for the Adapter and Activity/Fragment:
``` java
public class ExampleAdapter extends FlexibleAdapter<ExampleAdapter.SimpleViewHolder, Item>
		implements FastScroller.BubbleTextGetter {
	...
	@Override
	public String getTextToShowInBubble(int position) {
		return getItem(position).getTitle().substring(0,1).toUpperCase();
	}
}
```
``` java
public class MainActivity extends AppCompatActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		...
		FastScroller fastScroller = (FastScroller) findViewById(R.id.fast_scroller);
		fastScroller.setRecyclerView(mRecyclerView);
		fastScroller.setViewsToUse(R.layout.fast_scroller, R.id.fast_scroller_bubble, R.id.fast_scroller_handle);
	}
	...
}
```

# Change Log
###### v4 - 2015.10.18
- Added **FilterAsyncTask** to asynchronously load the list (This might not work well and binding is excluded from Async)
- Enabled **Search** filter through _updateDataSet_ method (Note: as the example is made, the search regenerate the list!)
- Included some ItemAnimators from https://github.com/wasabeef/recyclerview-animators
  (in the example SlideInRightAnimator is used), but all need to be adapted if used with Support v23.1.0
- Included and customized **FastScroller** library from https://github.com/AndroidDeveloperLB/LollipopContactsRecyclerViewFastScroller
  My version has FrameLayout extended instead of LinearLayout, and a friendly layout.
- Added **SwipeRefreshLayout**, just an usage example
- Use of Handler instead of TimerTask while Undo
- _FlexibleAdapter_ can now return deleted items before they are removed from memory
- _SelectableAdapter.selectAll()_ can now skip selection on one specific ViewType
- Adapted MainActivity

###### Old releases
See [releases](../../releases) for old versions.

v3.1 - 2015.08.18 | v3.0 - 2015.07.29
v2.2 - 2015.07.20 | v2.1 - 2015.07.03
v2.0 - 2015.06.19 | v1.0 - 2015.05.03
<commit_msg>A better Readme with supporting Wikis and Releases. Fixed some comments.<commit_after>[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-FlexibleAdapter-green.svg?style=flat)](https://android-arsenal.com/details/1/2207)

# Flexible Adapter

###### A pattern for every RecyclerView - Master branch: v4 of 2015.10.18

#### Main functionalities
* Base item selection (but also SINGLE & MULTI selection mode) in the Recycler View with ripple effect.
* Undo the deleted items with custom animations.
* Customizable FastScroller (imported library, see change log for details).
* SearchFilter with string selection in Item titles and subtitles.

#### How is made
The base functionality is taken from different Blogs (see at the bottom of the page), merged and methods have been improved for speed and scalability, for all Activities that use a RecyclerView.

* At lower class there is SelectableAdapter that provides selection functionalities and it's able to _maintain the state_ after the rotation, you just need to call the onSave/onRestore methods from the Activity!
* Then, the class FlexibleAdapter handles the content paying attention at the animations (calling notify only for the position. _Note:_ you still need to set your animation to the RecyclerView when you create it in the Activity).
* Then you need to extend over again this class. Here you add and implement methods as you wish for your own ViewHolder and your Domain/Model class (data holder).

I've put the Set click listeners at the creation and not in the Binding method, because onBindViewHolder is called at each invalidate (each notify..() methods).

Finally note that, this adapter handles the basic clicks: _single_ and _long clicks_. If you need a double tap you need to implement the android.view.GestureDetector.

# Screenshots
![Main screen](/screenshots/main_screen.png) ![Multi Selection](/screenshots/multi_selection.png)
![Search screen](/screenshots/search.png) ![Undo Screen](/screenshots/undo.png)

#Setup
Ultra simple:
No needs to create and import a library for just 2 files, so just *copy* SelectableAdapter.java & FlexibleAdapter.java in your *common* package and start to *extend* FlexibleAdapter from your custom Adapter (see my ExampleAdapter).

Remember to initialize `mItems` (List already included in FlexibleAdapter) in order to manage list items. Method `updateDataSet(..)` can help in this.

#### Pull requests / Issues / Improvement requests
Feel free to contribute and ask!

# Usage for Single Selection
See [Wiki](https://github.com/davideas/FlexibleAdapter/wiki) for full details! In your Activity/Fragment creation set the Mode SINGLE.
In onListItemClick, call *toggleSeletion* to register the selection on that position:
``` java
public class MainActivity extends AppCompatActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		...
		mAdapter = new YoursAdapter(..., ..., ...);
		mAdapter.setMode(YoursAdapter.MODE_SINGLE);
		...
	}

	@Override
	public boolean onListItemClick(int position) {
		toggleSelection(position);
	}
}
```

# Usage for Multi Selection
See [Wiki](https://github.com/davideas/FlexibleAdapter/wiki) for full details! In your Activity/Fragment change the Modes for the _ActionMode_ object.
``` java
public class MainActivity extends AppCompatActivity implements
		ActionMode.Callback {
	...
	@Override
	public boolean onCreateActionMode(ActionMode mode, Menu menu) {
		mode.getMenuInflater().inflate(R.menu.menu_context, menu);
		mAdapter.setMode(YourAdapterClass.MODE_MULTI);
		return true;
	}
	
	@Override
	public void onDestroyActionMode(ActionMode mode) {
		mAdapter.setMode(YourAdapterClass.MODE_SINGLE);
		mAdapter.clearSelection();
		mActionMode = null;
	}
}
```

# Usage for Undo
See [Wiki](https://github.com/davideas/FlexibleAdapter/wiki) for full details!
``` java
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
	switch (item.getItemId()) {
		...
		case R.id.action_delete:
			for (int i : mAdapter.getSelectedItems()) {
				//Remove items from your Database. Example:
				DatabaseService.getInstance().removeItem(mAdapter.getItem(i));
			}

			//Keep synchronized the Adapter: Remove selected items from Adapter
			mAdapter.removeItems(mAdapter.getSelectedItems());

			//Start countdown with startUndoTimer(millisec)
			mAdapter.startUndoTimer(7000); //Default 5''
			mActionMode.finish();
			return true;
	}
}
```

# Usage for FastScroller
See [Wiki](https://github.com/davideas/FlexibleAdapter/wiki) for full details! First add the drawable files to the project, then the layout, finally add the implementation for the Adapter and Activity/Fragment:
``` java
public class ExampleAdapter extends FlexibleAdapter<ExampleAdapter.SimpleViewHolder, Item>
		implements FastScroller.BubbleTextGetter {
	...
	@Override
	public String getTextToShowInBubble(int position) {
		return getItem(position).getTitle().substring(0,1).toUpperCase();
	}
}
```
``` java
public class MainActivity extends AppCompatActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		...
		FastScroller fastScroller = (FastScroller) findViewById(R.id.fast_scroller);
		fastScroller.setRecyclerView(mRecyclerView);
		fastScroller.setViewsToUse(R.layout.fast_scroller, R.id.fast_scroller_bubble, R.id.fast_scroller_handle);
	}
	...
}
```

# Change Log
###### v4 - 2015.10.18
- Added **FilterAsyncTask** to asynchronously load the list (This might not work well and binding is excluded from Async)
- Enabled **Search** filter through _updateDataSet_ method (Note: as the example is made, the search regenerate the list!)
- Included some ItemAnimators from https://github.com/wasabeef/recyclerview-animators
  (in the example SlideInRightAnimator is used), but all need to be adapted if used with Support v23.1.0
- Included and customized **FastScroller** library from https://github.com/AndroidDeveloperLB/LollipopContactsRecyclerViewFastScroller
  My version has FrameLayout extended instead of LinearLayout, and a friendly layout.
- Added **SwipeRefreshLayout**, just an usage example
- Use of Handler instead of TimerTask while Undo
- _FlexibleAdapter_ can now return deleted items before they are removed from memory
- _SelectableAdapter.selectAll()_ can now skip selection on one specific ViewType
- Adapted MainActivity

###### Old releases
See [releases](https://github.com/davideas/FlexibleAdapter/releases) for old versions.

v3.1 - 2015.08.18 | v3.0 - 2015.07.29
v2.2 - 2015.07.20 | v2.1 - 2015.07.03
v2.0 - 2015.06.19 | v1.0 - 2015.05.03

{'fraction_non_alphanumeric': 0.0923400607807995, 'fraction_numerical': 0.015117275773396712, 'mean_word_length': 4.80986871887732, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 13, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '994933', 'n_tokens_mistral': 3944, 'n_tokens_neox': 3569, 'n_words': 1332}