Android Swipe LayoutThis will be the most powerful Android swipe UI component
In one of my Project, I have a requirement to create a Swiping Layout For RecyclerView.
I looked for different Libraries. I found this Great Library Android Swipe Layout.
I have tried this Library for RecyclerView. I have done sample Project using this great Library.
This Library Supports ListView and GridView also.
Thanks to the Author for Creating this useful Library:https://github.com/daimajia/
Library Link :https://github.com/daimajia/AndroidSwipeLayout/Wiki Page:https://github.com/daimajia/AndroidSwipeLayout/wiki
Step: 1======
Add dependency to your build.gradle file
1 2 3 4 | dependencies { compile 'com.daimajia.swipelayout:library:1.2.0@aar' }
|
Step: 2======
Create a row for RecyclerView using SwipeLayout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | <?xml version="1.0" encoding="utf-8" ?> <com.daimajia.swipe.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:swipe="http://schemas.android.com/apk/res-auto" android:id="@+id/swipe" android:layout_width="match_parent" android:layout_height="wrap_content" swipe:leftEdgeSwipeOffset="0dp" swipe:rightEdgeSwipeOffset="0dp">
<!--Bottom View For Right to Left-->
<LinearLayout android:id="@+id/bottom_wrapper" android:layout_width="240dp" android:layout_height="match_parent" android:weightSum="3">
<TextView android:id="@+id/tvEdit" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="#0076a5" android:gravity="center" android:text="Edit" android:textColor="#fff" />
<TextView android:id="@+id/tvShare" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="#003c54" android:gravity="center" android:text="Share" android:textColor="#fff" />
<TextView android:id="@+id/tvDelete" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="#0076a5" android:gravity="center" android:text="Delete" android:textColor="#fff" /> </LinearLayout>
<!-- Another Bottom View For Left to Right -->
<LinearLayout android:id="@+id/bottom_wrapper1" android:layout_width="80dp" android:layout_height="match_parent" android:weightSum="1">
<ImageButton android:id="@+id/btnLocation" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@null" android:gravity="center" android:src="@drawable/ic_map" /> </LinearLayout>
<!-- Top View, Row itemView of RecyclerView --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:selectableItemBackground" android:elevation="5dp" android:orientation="vertical" android:padding="10dp">
<TextView android:id="@+id/tvName" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:text="Name" android:textColor="@android:color/black" android:textSize="18sp" />
<TextView android:id="@+id/tvEmailId" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/tvName" android:layout_margin="5dp" android:text="Email Id" android:textColor="@android:color/black" android:textSize="12sp" /> </LinearLayout>
</com.daimajia.swipe.SwipeLayout>
|
Step: 3======
Now, Create Adapter Class by extending
RecyclerSwipeAdapter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | package com.pratap.swipe;
import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.TextView; import android.widget.Toast;
import com.daimajia.swipe.SwipeLayout; import com.daimajia.swipe.adapters.RecyclerSwipeAdapter;
import java.util.ArrayList;
public class SwipeRecyclerViewAdapter extends RecyclerSwipeAdapter<SwipeRecyclerViewAdapter.SimpleViewHolder> {
private Context mContext; private ArrayList<Student> studentList;
public SwipeRecyclerViewAdapter(Context context, ArrayList<Student> objects) { this.mContext = context; this.studentList = objects; }
@Override public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.swipe_row_item, parent, false); return new SimpleViewHolder(view); }
@Override public void onBindViewHolder(final SimpleViewHolder viewHolder, final int position) { final Student item = studentList.get(position);
viewHolder.tvName.setText((item.getName()) + " - Row Position " + position); viewHolder.tvEmailId.setText(item.getEmailId());
viewHolder.swipeLayout.setShowMode(SwipeLayout.ShowMode.PullOut);
// Drag From Left viewHolder.swipeLayout.addDrag(SwipeLayout.DragEdge.Left, viewHolder.swipeLayout.findViewById(R.id.bottom_wrapper1));
// Drag From Right viewHolder.swipeLayout.addDrag(SwipeLayout.DragEdge.Right, viewHolder.swipeLayout.findViewById(R.id.bottom_wrapper));
// Handling different events when swiping viewHolder.swipeLayout.addSwipeListener(new SwipeLayout.SwipeListener() { @Override public void onClose(SwipeLayout layout) { //when the SurfaceView totally cover the BottomView. }
@Override public void onUpdate(SwipeLayout layout, int leftOffset, int topOffset) { //you are swiping. }
@Override public void onStartOpen(SwipeLayout layout) {
}
@Override public void onOpen(SwipeLayout layout) { //when the BottomView totally show. }
@Override public void onStartClose(SwipeLayout layout) {
}
@Override public void onHandRelease(SwipeLayout layout, float xvel, float yvel) { //when user's hand released. } });
/*viewHolder.swipeLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {
if ((((SwipeLayout) v).getOpenStatus() == SwipeLayout.Status.Close)) { //Start your activity
Toast.makeText(mContext, " onClick : " + item.getName() + " \n" + item.getEmailId(), Toast.LENGTH_SHORT).show(); }
} });*/
viewHolder.swipeLayout.getSurfaceView().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext, " onClick : " + item.getName() + " \n" + item.getEmailId(), Toast.LENGTH_SHORT).show(); } });
viewHolder.btnLocation.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {
Toast.makeText(v.getContext(), "Clicked on Map " + viewHolder.tvName.getText().toString(), Toast.LENGTH_SHORT).show(); } });
viewHolder.tvShare.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) {
Toast.makeText(view.getContext(), "Clicked on Share " + viewHolder.tvName.getText().toString(), Toast.LENGTH_SHORT).show(); } });
viewHolder.tvEdit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) {
Toast.makeText(view.getContext(), "Clicked on Edit " + viewHolder.tvName.getText().toString(), Toast.LENGTH_SHORT).show(); } });
viewHolder.tvDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mItemManger.removeShownLayouts(viewHolder.swipeLayout); studentList.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, studentList.size()); mItemManger.closeAllItems(); Toast.makeText(view.getContext(), "Deleted " + viewHolder.tvName.getText().toString(), Toast.LENGTH_SHORT).show(); } });
// mItemManger is member in RecyclerSwipeAdapter Class mItemManger.bindView(viewHolder.itemView, position);
}
@Override public int getItemCount() { return studentList.size(); }
@Override public int getSwipeLayoutResourceId(int position) { return R.id.swipe; }
// ViewHolder Class
public static class SimpleViewHolder extends RecyclerView.ViewHolder { SwipeLayout swipeLayout; TextView tvName; TextView tvEmailId; TextView tvDelete; TextView tvEdit; TextView tvShare; ImageButton btnLocation;
public SimpleViewHolder(View itemView) { super(itemView); swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe); tvName = (TextView) itemView.findViewById(R.id.tvName); tvEmailId = (TextView) itemView.findViewById(R.id.tvEmailId); tvDelete = (TextView) itemView.findViewById(R.id.tvDelete); tvEdit = (TextView) itemView.findViewById(R.id.tvEdit); tvShare = (TextView) itemView.findViewById(R.id.tvShare); btnLocation = (ImageButton) itemView.findViewById(R.id.btnLocation);
} } }
|
Step: 4======
Create an xml Layout with RecyclerView for the Activity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" style="@style/ToolBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/md_deep_orange_500" android:elevation="8dp" android:minHeight="?attr/actionBarSize">
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView android:id="@+id/my_recycler_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_margin="5dp" android:layout_weight="1" android:scrollbars="vertical" /> <TextView android:id="@+id/empty_view" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="No Records" android:visibility="gone" />
</LinearLayout>
|
Step: 5======
Now , Create an Activity Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | package com.pratap.swipe;
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.widget.TextView;
import com.daimajia.swipe.util.Attributes;
import java.util.ArrayList;
public class RecyclerViewExample extends AppCompatActivity {
/** * RecyclerView: The new recycler view replaces the list view. Its more modular and therefore we * must implement some of the functionality ourselves and attach it to our recyclerview. * <p/> * 1) Position items on the screen: This is done with LayoutManagers * 2) Animate & Decorate views: This is done with ItemAnimators & ItemDecorators * 3) Handle any touch events apart from scrolling: This is now done in our adapter's ViewHolder */
private ArrayList<Student> mDataSet;
private Toolbar toolbar;
private TextView tvEmptyView; private RecyclerView mRecyclerView;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.swiprecyclerview); toolbar = (Toolbar) findViewById(R.id.toolbar); tvEmptyView = (TextView) findViewById(R.id.empty_view); mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// Layout Managers: mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
// Item Decorator: mRecyclerView.addItemDecoration(new DividerItemDecoration(getResources().getDrawable(R.drawable.divider))); // mRecyclerView.setItemAnimator(new FadeInLeftAnimator());
mDataSet = new ArrayList<Student>();
if (toolbar != null) { setSupportActionBar(toolbar); getSupportActionBar().setTitle("Android Students");
}
loadData();
if (mDataSet.isEmpty()) { mRecyclerView.setVisibility(View.GONE); tvEmptyView.setVisibility(View.VISIBLE);
} else { mRecyclerView.setVisibility(View.VISIBLE); tvEmptyView.setVisibility(View.GONE); }
// Creating Adapter object SwipeRecyclerViewAdapter mAdapter = new SwipeRecyclerViewAdapter(this, mDataSet);
// Setting Mode to Single to reveal bottom View for one item in List // Setting Mode to Mutliple to reveal bottom Views for multile items in List ((SwipeRecyclerViewAdapter) mAdapter).setMode(Attributes.Mode.Single);
mRecyclerView.setAdapter(mAdapter);
/* Scroll Listeners */ mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); Log.e("RecyclerView", "onScrollStateChanged"); }
@Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); } }); }
// load initial data public void loadData() {
for (int i = 0; i <= 20; i++) { mDataSet.add(new Student("Student " + i, "androidstudent" + i + "@gmail.com"));
}
}
}
|
Step: 5======
Student.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package com.pratap.swipe;
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String emailId;
public Student() {
} public Student(String name, String emailId) { this.name = name; this.emailId = emailId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmailId() { return emailId; }
public void setEmailId(String emailId) { this.emailId = emailId; }
}
|
DividerItemDecoration.javaTo give divider for each row in RecyclerView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | package com.pratap.swipe;
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.View;
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider; private boolean mShowFirstDivider = false; private boolean mShowLastDivider = false;
public DividerItemDecoration(Context context, AttributeSet attrs) { final TypedArray a = context .obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider}); mDivider = a.getDrawable(0); a.recycle(); }
public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider, boolean showLastDivider) { this(context, attrs); mShowFirstDivider = showFirstDivider; mShowLastDivider = showLastDivider; }
public DividerItemDecoration(Drawable divider) { mDivider = divider; }
public DividerItemDecoration(Drawable divider, boolean showFirstDivider, boolean showLastDivider) { this(divider); mShowFirstDivider = showFirstDivider; mShowLastDivider = showLastDivider; }
@Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (mDivider == null) { return; } if (parent.getChildPosition(view) < 1) { return; }
if (getOrientation(parent) == LinearLayoutManager.VERTICAL) { outRect.top = mDivider.getIntrinsicHeight(); } else { outRect.left = mDivider.getIntrinsicWidth(); } }
@Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { if (mDivider == null) { super.onDrawOver(c, parent, state); return; }
// Initialization needed to avoid compiler warning int left = 0, right = 0, top = 0, bottom = 0, size; int orientation = getOrientation(parent); int childCount = parent.getChildCount();
if (orientation == LinearLayoutManager.VERTICAL) { size = mDivider.getIntrinsicHeight(); left = parent.getPaddingLeft(); right = parent.getWidth() - parent.getPaddingRight(); } else { //horizontal size = mDivider.getIntrinsicWidth(); top = parent.getPaddingTop(); bottom = parent.getHeight() - parent.getPaddingBottom(); }
for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
if (orientation == LinearLayoutManager.VERTICAL) { top = child.getTop() - params.topMargin; bottom = top + size; } else { //horizontal left = child.getLeft() - params.leftMargin; right = left + size; } mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); }
// show last divider if (mShowLastDivider && childCount > 0) { View child = parent.getChildAt(childCount - 1); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (orientation == LinearLayoutManager.VERTICAL) { top = child.getBottom() + params.bottomMargin; bottom = top + size; } else { // horizontal left = child.getRight() + params.rightMargin; right = left + size; } mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } }
private int getOrientation(RecyclerView parent) { if (parent.getLayoutManager() instanceof LinearLayoutManager) { LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager(); return layoutManager.getOrientation(); } else { throw new IllegalStateException( "DividerItemDecoration can only be used with a LinearLayoutManager."); } } }
|
Step: 6======
ScreenShots
Step: 7======
Source Code
DownloadLinkSample Apk
Sample Apk File