Sau một thời gian sử dụng sử dụng Gmail và Outlook mình bắt đầu tìm hiểu và tìm kiếm một thư viện hỗ trợ để có được những hiệu ứng tương tự.
Sau khi Google mình tìm thấy thư viện AndroidSwipeLayout có hỗ trợ các hiệu ứng khá đẹp. Thư viện khi kết hợp với RecycleView sẽ tạo ra nhiều option cho người dùng chọn khi swipe trái/phải màn hình.
Bài viết này mình sẽ hướng dẫn các bạn thêm thư viện AndroidSwipeLayout kết hợp với RecyclerView vào project.
Các bước thực hiện như sau:
Bước 1: Add thư viện
Mở file gradle và thêm dòng sau.
Trong phần res/layout, thêm file swipe_row_item.xml dùng để định nghĩa một thành phần của Listview.
Sau khi Google mình tìm thấy thư viện AndroidSwipeLayout có hỗ trợ các hiệu ứng khá đẹp. Thư viện khi kết hợp với RecycleView sẽ tạo ra nhiều option cho người dùng chọn khi swipe trái/phải màn hình.
Bài viết này mình sẽ hướng dẫn các bạn thêm thư viện AndroidSwipeLayout kết hợp với RecyclerView vào project.
Các bước thực hiện như sau:
Bước 1: Add thư viện
Mở file gradle và thêm dòng sau.
compile 'com.daimajia.swipelayout:library:1.2.0@aar'Bước 2: Định nghĩa item của listview
Trong phần res/layout, thêm file swipe_row_item.xml dùng để định nghĩa một thành phần của Listview.
<?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="73dp" 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/location_icon" /> </LinearLayout> <!-- Top View, Row itemView of RecyclerView --> <LinearLayout android:layout_width="match_parent" android:layout_height="73dp" android:background="?android:selectableItemBackground" android:orientation="horizontal"> <RelativeLayout android:layout_width="85dp" android:layout_height="match_parent" android:paddingLeft="18dp" android:paddingRight="18dp" android:paddingTop="8dp" android:paddingBottom="8dp"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/contact_default"/> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingRight="18dp" android:paddingTop="15dp" android:paddingBottom="15dp"> > <!--contact name layout--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tvName" android:layout_width="200dp" android:layout_height="20dp" android:text="Name" android:textColor="@android:color/black" android:textSize="16sp" /> <TextView android:id="@+id/tvDeliveryStatus" android:layout_width="match_parent" android:layout_height="20dp" android:gravity="right" android:textAlignment="gravity" android:text="Sent"/> </LinearLayout> <!--message content--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tvEmailId" android:layout_width="200dp" android:layout_height="20dp" android:layout_below="@+id/tvName" android:text="Email Id" android:textColor="@android:color/black" android:textSize="12sp" /> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" android:scaleType="fitEnd" android:src="@drawable/facebook_icon"/> </LinearLayout> </LinearLayout> </LinearLayout> </com.daimajia.swipe.SwipeLayout>Bước 3: Tạo lớp Student.
package com.blogspot.simplecodecjava.swiperecycleview; 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; } }Bước 4: Tạo lớp SwipeRecyclerViewAdapter kế thừa từ RecyclerSwipeAdapter.
package com.blogspot.simplecodecjava.swiperecycleview; 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 com.slab.schedulerchat.R; 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); } } }Bước 5: Khai báo MainAtivity.
package com.blogspot.simplecodecjava.swiperecycleview; import android.content.Context; 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 java.util.ArrayList; public class MainActivity extends AppCompatActivity { private ArrayList<Student> mDataSet; private String TAG = MainActivity.class.getName(); private Toolbar toolbar; private TextView tvEmptyView; private RecyclerView mRecyclerView; private volatile static MainActivity mInstance; public static MainActivity getInstance(Context context){ if(mInstance == null){ synchronized (MainActivity.class){ if(mInstance == null){ mInstance = new MainActivity(); } } } return mInstance; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar = (Toolbar) findViewById(R.id.toolbar); tvEmptyView = (TextView) findViewById(R.id.empty_view); mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 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); } SwipeRecyclerViewAdapter mAdapter = new SwipeRecyclerViewAdapter(this, mDataSet); mRecyclerView.setAdapter(mAdapter); 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); } }); } public void loadData() { for (int i = 0; i <= 20; i++) { mDataSet.add(new Student("Student " + i, "androidstudent" + i + "@gmail.com")); } } }Bước 6: Khai báo activity_main layout.
<?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" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FF4081" 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>Bạn có thể tải project mẫu tại đây.
Nguồn: blogger.com