Skip to content

Instantly share code, notes, and snippets.

@Suleiman19
Last active June 27, 2019 14:31
Show Gist options
  • Save Suleiman19/833c4a6a83464e711f96ac653fead0fc to your computer and use it in GitHub Desktop.
Save Suleiman19/833c4a6a83464e711f96ac653fead0fc to your computer and use it in GitHub Desktop.
Sample code snippets for using mikepenz/FastAdapter library and its various features
public class Header extends AbstractItem<Header, Header.ViewHolder> {
String title;
public Header(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
// FastAdapter AbstractItem methods
@Override
public int getType() {
return R.id.header_text;
}
@Override
public int getLayoutRes() {
return R.layout.header_item;
}
@Override
public void bindView(ViewHolder holder) {
super.bindView(holder);
holder.textView.setText(title);
}
protected static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.header_text) TextView textView;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/header_text"
style="@style/TextAppearance.AppCompat.Caption"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:paddingLeft="@dimen/activity_margin"
android:paddingStart="@dimen/activity_margin"
tools:background="#EFEFEF"
tools:text="Header">
</TextView>
public class HeaderActivity extends AppCompatActivity {
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.recycler) RecyclerView recyclerView;
private FastItemAdapter fastAdapter;
private HeaderAdapter<Header> headerAdapter;
private List<Mango> mangoes;
private FooterAdapter<ProgressItem> footerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("With Header");
mangoes = new DummyData(this).generateData(); //Populating our Mangoes list
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(new DefaultItemAnimator());
fastAdapter = new FastItemAdapter<>();
fastAdapter.setHasStableIds(true);
fastAdapter.withSelectable(true);
headerAdapter = new HeaderAdapter<>();
footerAdapter = new FooterAdapter<>(); // help manage load more progress
recyclerView.setAdapter(footerAdapter.wrap(headerAdapter.wrap(fastAdapter)));
int half = mangoes.size() / 2;
fastAdapter.add(0, new Header("First half").withIdentifier(1));
fastAdapter.add(1, mangoes.subList(0, half));
fastAdapter.add(half + 1, new Header("Second half").withIdentifier(2));
fastAdapter.add(half + 2, mangoes.subList(0, half));
fastAdapter.withOnClickListener(new FastAdapter.OnClickListener<IItem>() {
@Override
public boolean onClick(View v, IAdapter<IItem> adapter, IItem item, int position) {
if (item instanceof Mango) {
Mango mango = (Mango) item;
// Do what you want with your Mango here
}
return true;
}
});
recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener() {
@Override
public void onLoadMore(int currentPage) {
footerAdapter.clear();
footerAdapter.add(new ProgressItem().withEnabled(false));
// Faking a network load
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
footerAdapter.clear();
List<Mango> newMangoes = mangoes.subList(0, 3);
fastAdapter.add(newMangoes);
}
}, 2000);
}
});
fastAdapter.withSavedInstanceState(savedInstanceState);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState = fastAdapter.saveInstanceState(outState);
super.onSaveInstanceState(outState);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/item_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selector_card"
android:clickable="true"
android:orientation="horizontal">
<ImageView
android:id="@+id/item_image"
android:layout_width="0dp"
android:layout_height="88dp"
android:layout_weight="0.3"
android:scaleType="centerCrop"
tools:background="@color/colorAccent"/>
<TextView
android:id="@+id/item_title"
style="@style/TextAppearance.AppCompat.Subhead"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.7"
android:gravity="center_vertical"
android:padding="@dimen/activity_margin"
tools:text="Mango"/>
</LinearLayout>
public class MainActivity extends AppCompatActivity implements ItemAdapter.ItemFilterListener, ItemTouchCallback {
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.recycler) RecyclerView recyclerView;
private List<Mango> mangoes;
private FastItemAdapter<Mango> fastAdapter;
private SimpleDragCallback dragCallback;
private ItemTouchHelper touchHelper;
private ActionModeHelper actionModeHelper;
private UndoHelper undoHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
toolbar.setTitle("Mangoes");
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
/**
* See <a href="https://gist.github.com/alexfu/0f464fc3742f134ccd1e">DividerItemDecoration</a>
*/
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
recyclerView.setItemAnimator(new DefaultItemAnimator());
mangoes = new DummyData(this).generateData(); //Populating our Mangoes list
fastAdapter = new FastItemAdapter<>();
fastAdapter.setHasStableIds(true);
fastAdapter.withSelectable(true);
fastAdapter.withMultiSelect(true);
fastAdapter.withSelectOnLongClick(true);
fastAdapter.withOnClickListener(new FastAdapter.OnClickListener<Mango>() {
@Override
public boolean onClick(View v, IAdapter<Mango> adapter, Mango item, int position) {
//@// TODO: Handle normal clicks: Intent to DetailActivity
return false;
}
});
fastAdapter.withFilterPredicate(new IItemAdapter.Predicate<Mango>() {
@Override
public boolean filter(Mango item, CharSequence constraint) {
// Remove those which return true
return item.getName().startsWith(String.valueOf(constraint));
}
});
// Drag and drop setup
dragCallback = new SimpleDragCallback(this);
touchHelper = new ItemTouchHelper(dragCallback);
touchHelper.attachToRecyclerView(recyclerView);
// Init for multi-select CAB mode
actionModeHelper = new ActionModeHelper(fastAdapter, R.menu.cab, new ActionBarCallBack());
fastAdapter.withOnPreClickListener(new FastAdapter.OnClickListener<Mango>() {
@Override
public boolean onClick(View v, IAdapter<Mango> adapter, Mango item, int position) {
Boolean res = actionModeHelper.onClick(item);
return res != null ? res : false;
}
});
fastAdapter.withOnPreLongClickListener(new FastAdapter.OnLongClickListener<Mango>() {
@SuppressWarnings("ConstantConditions")
@Override
public boolean onLongClick(View v, IAdapter<Mango> adapter, Mango item, int position) {
ActionMode actionMode = actionModeHelper.onLongClick(MainActivity.this, position);
if (actionMode != null) {
// Set CAB background color
findViewById(R.id.action_mode_bar).setBackgroundColor(Color.GRAY);
}
return actionMode != null;
}
});
/*
For handling multiple selected items deletion via CAB mode.
Also for Undo delete action via SnackBar
*/
//noinspection unchecked
undoHelper = new UndoHelper(fastAdapter, new UndoHelper.UndoListener<Mango>() {
@Override
public void commitRemove(Set<Integer> positions, ArrayList<FastAdapter.RelativeInfo<Mango>> removed) {
Log.d("remove", "removed: " + removed.size());
}
});
recyclerView.setAdapter(fastAdapter); // Used for single adapter type
fastAdapter.add(mangoes); // Always add items after setting adapter
// Call only after adding items
fastAdapter.withSavedInstanceState(savedInstanceState);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState = fastAdapter.saveInstanceState(outState);
super.onSaveInstanceState(outState);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.main_menu_filter:
// Ideally call this from your SearchView's 'onQuerytextSubmit()' & 'onQueryTextChange()'
fastAdapter.filter("K");
return true;
case R.id.main_menu_next:
Intent i = new Intent(MainActivity.this, HeaderActivity.class);
startActivity(i);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// ItemAdapter.ItemFilterListener
@Override
public void itemsFiltered() {
// Items filtering completed
Toast.makeText(MainActivity.this, "Filtered", Toast.LENGTH_SHORT).show();
}
// ItemTouchCallback
@Override
public boolean itemTouchOnMove(int oldPosition, int newPosition) {
Collections.swap(fastAdapter.getAdapterItems(), oldPosition, newPosition); // change position
fastAdapter.notifyAdapterItemMoved(oldPosition, newPosition);
return true;
}
// inner class for handling CAB
private class ActionBarCallBack implements ActionMode.Callback {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
undoHelper.remove(findViewById(android.R.id.content), "Item removed", "Undo", Snackbar.LENGTH_LONG, fastAdapter.getSelections());
mode.finish();
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
}
}
public class Mango extends AbstractItem<Mango, Mango.ViewHolder> {
private String name, imageUrl, description;
public Mango() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
// Fast Adapter AbstractItem methods
@Override
public int getType() {
return R.id.item_card;
}
@Override
public int getLayoutRes() {
return R.layout.list_item;
}
@Override
public void bindView(ViewHolder holder) {
super.bindView(holder);
holder.text.setText(name);
// Doing a simple check, useful for Header view
if (imageUrl.equals("header")) {
holder.image.setVisibility(View.GONE);
} else {
Glide
.with(holder.itemView.getContext())
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(holder.image);
}
}
protected static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.item_image) ImageView image;
@BindView(R.id.item_title) TextView text;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
<resources>
<style name="AppTheme" parent="Base.AppTheme"></style>
<style name="Base.AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="windowActionBar">false</item>
<item name="windowActionBarOverlay">true</item>
<item name="windowNoTitle">true</item>
<item name="android:windowBackground">@color/bgLight</item>
<item name="windowActionModeOverlay">true</item>
</style>
</resources>
@antonio10
Copy link

can not resolve symbol AbstractItem in android studio

@afarber
Copy link

afarber commented Jul 23, 2018

antonio10, read the article https://blog.iamsuleiman.com/recyclerview-adapter-android-made-fast-easy/ on how to setup FastAdapter library to fix that problem

@vkotovv
Copy link

vkotovv commented Jun 19, 2019

Which version of FastAdapter is used in your sample?

@Suleiman19
Copy link
Author

At the time of writing the article, it was version 1.5.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment