Android Swipe Layout đây là một thư viện mã ngồn mở trên github là một thành phần giao diện người dùng đẹp và bắt mắt. Ở bài viết này mình sẽ làm một demo cho các bạn cùng sử dụng.
Author for Creating this Library:
https://github.com/daimajia/
Library Link :
https://github.com/daimajia/AndroidSwipeLayout/
Wiki Page:
https://github.com/daimajia/AndroidSwipeLayout/wiki
1.Thêm các phụ thuộc vào build.gradle
compile 'com.android.support:recyclerview-v7:25.1.1' compile 'com.android.support:support-v4:25.1.1' compile "com.daimajia.swipelayout:library:1.2.0@aar"
2. Tạo swipe_row_item.xml như sau:
<?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"> <!--Phần layout lướt từ phải qua trái--> <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> <!-- Phần layout Left --> <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> <!-- Row itemView gồm 2 trường --> <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>
2. Trong activity_main.xml code như sau:
<?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.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>
3. Tạo đối tượng Student.java như sau:
package com.lynkdev.androidswipelayout.model; import java.io.Serializable; /** * Created by LynkMieu on 2/13/2017. */ public class Student implements Serializable { 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; } }
4. Tạo một file DividerItemDecoration.java như sau:
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."); } } }
5. Trong drawable tạo một file divider.xml như sau
<?xml version="1.0"?> <shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#666666"/> <size android:height="1dp" android:width="1dp"/> </shape>
6. Tạo file SwipeRecyclerViewAdapter.java như sau
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); } } }
7. Quay lại MainActivity.java thiết lập dữ liệu
public class MainActivity 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 TextView tvEmptyView; private RecyclerView mRecyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); 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>(); 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")); } } }
Done tiến hành Run App.
Download code Link GitHub