Build More Flexible And Efficient Apps With Android RecyclerView Example

0
Shares
Build More Flexible And Efficient Apps With Android RecyclerView Example
5 (100%) 1 vote

Recycling has been one of those good things for planet and a couple of developers also thought about bringing recycling idea into digital world. They realized that OS can be also recycled to run more efficiently. And the outcome of this inspiration was rejoicing the eco-warriors when the Android RecyclerView Example was introduced in the world.

in this Android app tutorial, you’ll experience the power of Android recyclerview with example.

Let’s Get Started

First of all, add dependency in .gradle file

compile 'com.android.support:recyclerview-v7:22.2.0'

with the help of ItemTouchHelper and ItemTouchHelper.callback, we’ll implement the interface to allow you for listening ‘Move’ and ‘Swipe’ events.

before we do this, we need to override following methods to enable basic drag & drop and swipe-to-dismiss.

getMovementFlags(RecyclerView, ViewHolder)
onMove(RecyclerView, ViewHolder, ViewHolder)
onSwiped(ViewHolder, int)

Next, implement your CustomItemTouchHelperCallBack to override onMove and onSwipe.

  • Add Constructor
private final ItemTouchHelperAdapter mAdapter;
public SimpleItemTouchHelperCallback(
ItemTouchHelperAdapter adapter) {
mAdapter = adapter;
}
  • Override Two Methods
@Override
public boolean onMove(RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
mAdapter.onItemMove(viewHolder.getAdapterPosition(),
target.getAdapterPosition());
return true;
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder,
int direction) {
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}

Further, we’ll do breakdown of overridden method of CustomItemTouchHelperCallback

  • By following method we can decide the direction of swipe
@Override
public int getMovementFlags(RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
  • By overriding following method enable swipe
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
  • By following method we can unable long press drag functionality
@Override
public boolean isLongPressDragEnabled() {
return true;
}
  • Listner to handle call back event of drag and swipe-dismiss event
public interface ItemTouchHelperAdapter {
void onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);
}

Implement CallBack in Adapter 

public class RecyclerListAdapter extends
RecyclerView.Adapter<ItemViewHolder>
implements ItemTouchHelperAdapter {

//Item Swip and dismissed
@Override
public void onItemDismiss(int position) {
mItems.remove(position);
notifyItemRemoved(position);
}

//Item Dragged from one position to another
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(mItems, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(mItems, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
return true;
}

Static values in string.xml

<array name="main_items">
<item>List - Basic Drag and Swipe</item>
<item>Grid - Basic Swipe</item>
</array>
<array name="dummy_items">
<item>One</item>
<item>Two</item>
<item>Three</item>
<item>Four</item>
<item>Five</item>
<item>Six</item>
<item>Seven</item>
<item>Eight</item>
<item>Nine</item>
<item>Ten</item>
</array>

set up integer values in integer.xml

<resources>
<integer name="grid_columns">2</integer>
</resources>

Start Code Integration

  • ItemTouchHelperAdapter.java
public interface ItemTouchHelperAdapter {
boolean onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);
}
  • ItemTouchHelperViewHolder.java
public interface ItemTouchHelperViewHolder {
void onItemSelected();
void onItemClear();
}
  • OnStartDragListner.java
public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}
  • CustomItemTouchHelperCallback.java
public class CustomItemTouchHelperCallback extends ItemTouchHelper.Callback {
public static final float ALPHA_FULL = 1.0f;
private final ItemTouchHelperAdapter mAdapter;
public CustomItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
mAdapter = adapter;
}
@Override
public boolean isLongPressDragEnabled() {
return true;
}
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// Set movement flags based on the layout manager
if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
} else {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
if (source.getItemViewType() != target.getItemViewType()) {
return false;
}
// Notify the adapter of the move
mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) {
// Notify the adapter of the dismissal
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
// Fade out the view as it is swiped out of the parent's bounds
final float alpha = ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
viewHolder.itemView.setAlpha(alpha);
viewHolder.itemView.setTranslationX(dX);
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
// We only want the active item to change
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Let the view holder know that this item is being moved or dragged
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(ALPHA_FULL);
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Tell the view holder it's time toundo.swipe.drag.recyclerview.Fragment; restore the idle state
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemClear();
}
}
}
  • MainFragment.java
public class MainFragment extends ListFragment {
public interface OnListItemClickListener {
void onListItemClick(int position);
}
private OnListItemClickListener mItemClickListener;
public MainFragment() {
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mItemClickListener = (OnListItemClickListener) activity;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final String[] items = getResources().getStringArray(R.array.main_items);
final ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_list_item_1, items);
setListAdapter(adapter);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
mItemClickListener.onListItemClick(position);
}
}
  • RecyclerGridFragment.java
public class RecyclerGridFragment extends Fragment implements OnStartDragListener {
private ItemTouchHelper mItemTouchHelper;
public RecyclerGridFragment() {
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return new RecyclerView(container.getContext());
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final RecyclerListAdapter adapter = new RecyclerListAdapter(getActivity(), this);
RecyclerView recyclerView = (RecyclerView) view;
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
final int spanCount = getResources().getInteger(R.integer.grid_columns);
final GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), spanCount);
recyclerView.setLayoutManager(layoutManager);
ItemTouchHelper.Callback callback = new CustomItemTouchHelperCallback(adapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
}
@Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);
}
}
  • RecyclerListFragment.java
public class RecyclerListFragment extends Fragment implements OnStartDragListener {
private ItemTouchHelper mItemTouchHelper;
public RecyclerListFragment() {
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return new RecyclerView(container.getContext());
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerListAdapter adapter = new RecyclerListAdapter(getActivity(), this);
RecyclerView recyclerView = (RecyclerView) view;
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
ItemTouchHelper.Callback callback = new CustomItemTouchHelperCallback(adapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
}
@Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);
}
}
  • RecyclerListAdapter.java
public class RecyclerListAdapter extends RecyclerView.Adapter<RecyclerListAdapter.ItemViewHolder>
implements ItemTouchHelperAdapter {
private final List<String> mItems = new ArrayList<>();
private final OnStartDragListener mDragStartListener;
public RecyclerListAdapter(Context context, OnStartDragListener dragStartListener) {
mDragStartListener = dragStartListener;
mItems.addAll(Arrays.asList(context.getResources().getStringArray(R.array.dummy_items)));
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main, parent, false);
ItemViewHolder itemViewHolder = new ItemViewHolder(view);
return itemViewHolder;
}
@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
holder.textView.setText(mItems.get(position));
// Start a drag whenever the handle view it touched
holder.handleView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
mDragStartListener.onStartDrag(holder);
}
return false;
}
});
}
@Override
public void onItemDismiss(int position) {
mItems.remove(position);
notifyItemRemoved(position);
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
Collections.swap(mItems, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public int getItemCount() {
return mItems.size();
}
/**
* Simple example of a view holder that implements {@link ItemTouchHelperViewHolder} and has a
* "handle" view that initiates a drag event when touched.
*/
public static class ItemViewHolder extends RecyclerView.ViewHolder implements
ItemTouchHelperViewHolder {
public final TextView textView;
public final ImageView handleView;
public ItemViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.text);
handleView = (ImageView) itemView.findViewById(R.id.handle);
}
@Override
public void onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY);
}
@Override
public void onItemClear() {
itemView.setBackgroundColor(0);
}
}
}
  • activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
  • item_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item"
android:layout_width="match_parent"
android:layout_height="?listPreferredItemHeight"
android:clickable="true"
android:focusable="true"
android:foreground="?selectableItemBackground">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:textAppearance="?android:attr/textAppearanceMedium" />
<ImageView
android:id="@+id/handle"
android:layout_width="?listPreferredItemHeight"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|right"
android:scaleType="center"
android:src="@drawable/ic_reorder_grey_500_24dp" />
</FrameLayout>

once you run the demo, it will work like below output video.

Simple, right?

However if you face any issue or any query on Android development with Kotlin, you can contact our developers for help.

if you followed from beginning, then it’s been clear that a third-party library is not needed for this basic actions with Android RecyclerView Example. and adding such features can make your app more flexible to use to your app users. So if you still haven’t implemented them, hire Android app developer from us to implement this feature in your Android app.

Grab a free copy of Android RecyclerView Example from Github.

 
0
Shares
 

Want to Develop Efficient Android App? Contact Us

Get your free consultation now