【Android 事件分发】ItemTouchHelper 实现侧滑删除
Android 事件分發(fā) 系列文章目錄
【Android 事件分發(fā)】事件分發(fā)源碼分析 ( 驅(qū)動層通過中斷傳遞事件 | WindowManagerService 向 View 層傳遞事件 )
【Android 事件分發(fā)】事件分發(fā)源碼分析 ( Activity 中各層級的事件傳遞 | Activity -> PhoneWindow -> DecorView -> ViewGroup )
【Android 事件分發(fā)】事件分發(fā)源碼分析 ( ViewGroup 事件傳遞機制 一 )
【Android 事件分發(fā)】事件分發(fā)源碼分析 ( ViewGroup 事件傳遞機制 二 )
【Android 事件分發(fā)】事件分發(fā)源碼分析 ( ViewGroup 事件傳遞機制 三 )
【Android 事件分發(fā)】事件分發(fā)源碼分析 ( ViewGroup 事件傳遞機制 四 | View 事件傳遞機制 )
【Android 事件分發(fā)】事件分發(fā)源碼分析 ( ViewGroup 事件傳遞機制 五 )
【Android 事件分發(fā)】事件分發(fā)源碼分析 ( ViewGroup 事件傳遞機制 六 )
【Android 事件分發(fā)】事件分發(fā)源碼分析 ( ViewGroup 事件傳遞機制 七 )
【Android 事件分發(fā)】ItemTouchHelper 簡介 ( 拖動/滑動事件 | ItemTouchHelper.Callback 回調(diào) )
【Android 事件分發(fā)】ItemTouchHelper 實現(xiàn)側(cè)滑刪除 ( 設(shè)置滑動方向 | 啟用滑動操作 | 滑動距離判定 | 滑動速度判定 | 設(shè)置動畫時間 | 設(shè)置側(cè)滑觸發(fā)操作 )
【Android 事件分發(fā)】ItemTouchHelper 實現(xiàn)拖動排序 ( 設(shè)置滑動方向 | 啟啟用長按拖動功能 | 拖動距離判定 | 設(shè)置拖動觸發(fā)操作 )
文章目錄
- Android 事件分發(fā) 系列文章目錄
- 一、ItemTouchHelper.Callback 配置側(cè)滑刪除
- 1、設(shè)置移動標(biāo)志 ( 拖動/滑動 )
- 2、啟用滑動動作
- 3、滑動距離判定設(shè)置
- 4、滑動速度判定設(shè)置
- 5、設(shè)置動畫時間
- 6、設(shè)置側(cè)滑刪除觸發(fā)操作
- 7、RecyclerView.Adapter 適配器中的刪除操作
- 三、完整代碼實現(xiàn)
- 1、主界面
- 2、ItemTouchHelper.Callback 回調(diào)類
- 3、執(zhí)行效果
- 三、博客資源
一、ItemTouchHelper.Callback 配置側(cè)滑刪除
1、設(shè)置移動標(biāo)志 ( 拖動/滑動 )
重寫 ItemTouchHelper.Callback 的 getMovementFlags 方法 , 在該方法中設(shè)置滑動/拖動標(biāo)志位 ;
滑動 / 拖動 標(biāo)志 , 可使用 ItemTouchHelper.UP , ItemTouchHelper.DOWN , ItemTouchHelper.LEFT , ItemTouchHelper.RIGHT , 進行或操作得到 ;
// 設(shè)置拖動方向, 此處設(shè)置上下拖動事件int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;// 設(shè)置滑動方向, 此處設(shè)置左右側(cè)滑事件int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;再將 拖動標(biāo)志 和 滑動標(biāo)志 傳入 makeMovementFlags 方法 , 得到一個移動標(biāo)志位 , 作為 getMovementFlags 方法的返回值 ;
makeMovementFlags(dragFlags, swipeFlags);public class Callback extends ItemTouchHelper.Callback {/*** 設(shè)置上下左右動作* 只有在此處打開了指定方向的設(shè)置 , 才可以應(yīng)用具體方向的拖動* @param recyclerView* @param viewHolder* @return*/@Overridepublic int getMovementFlags(@NonNull RecyclerView recyclerView,@NonNull RecyclerView.ViewHolder viewHolder) {// 設(shè)置拖動方向, 此處設(shè)置上下拖動事件int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;// 設(shè)置滑動方向, 此處設(shè)置左右側(cè)滑事件int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;// 應(yīng)用 拖動 和 滑動 設(shè)置return makeMovementFlags(dragFlags, swipeFlags);} }
2、啟用滑動動作
重寫 ItemTouchHelper.Callback 的 isItemViewSwipeEnabled 方法 , 將該方法返回值設(shè)置為 true , 啟用滑動操作 ;
public class Callback extends ItemTouchHelper.Callback {/*** 是否啟用滑動操作* @return 是否啟用 true 啟用, false 不啟用*/@Overridepublic boolean isItemViewSwipeEnabled() {return true;} }3、滑動距離判定設(shè)置
重寫 ItemTouchHelper.Callback 的 getSwipeThreshold 方法 , 設(shè)置用戶的滑動距離 , 設(shè)置的是比例值, 返回值為 0.5 , 就意味著滑動寬度/高度的一半, 才觸發(fā)側(cè)滑 onSwiped 方法 ;
public class Callback extends ItemTouchHelper.Callback {/*** 用戶滑動距離, 設(shè)置的是比例值, 返回值為 0.5 , 就意味著滑動寬度/高度的一半, 才觸發(fā)側(cè)滑 onSwiped 方法* @param viewHolder* @return*/@Overridepublic float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {return 0.5f;} }上面案例中設(shè)置的滑動幅度是 0.5f , 在 getMovementFlags 方法中設(shè)置的滑動方向是左右滑動 , 因此在該案例中 , 滑動幅度在水平方向上超過 0.5 倍的條目組件寬度 , 側(cè)滑刪除才能生效 ;
下面的操作中 , 滑動在水平方向上沒有超過組件寬度的 0.5 倍 , 滑動刪除不生效 ;
下面的操作中 , 水平方向的滑動幅度超過了 0.5 倍 , 側(cè)滑刪除生效 ;
側(cè)滑判定 : 這里有兩種側(cè)滑判定條件 , 滿足任意一個即可觸發(fā)側(cè)滑刪除 ;
① 條件一 : getSwipeThreshold 方法中設(shè)置的滑動距離 , 滑動超過 0.5 滑動幅度 , 觸發(fā)側(cè)滑刪除 ;
② 條件二 : getSwipeEscapeVelocity 方法中設(shè)置的滑動速度 , 水平方向上每秒超過 5 像素的速度 , 觸發(fā)側(cè)滑刪除 ;
4、滑動速度判定設(shè)置
重寫 ItemTouchHelper.Callback 的 getSwipeEscapeVelocity 方法 , 設(shè)置用戶的滑動判定速度 , 單位是每秒移動的像素個數(shù) , 達到該速度后 , 才可以被判定為滑動 ;
public class Callback extends ItemTouchHelper.Callback {/*** 滑動判定速度, 每秒移動的像素個數(shù), 達到該速度后, 才可以被判定為滑動* @param defaultValue* @return*/@Overridepublic float getSwipeEscapeVelocity(float defaultValue) {return 5f;} }側(cè)滑判定 : 這里有兩種側(cè)滑判定條件 , 滿足任意一個即可觸發(fā)側(cè)滑刪除 ;
① 條件一 : getSwipeThreshold 方法中設(shè)置的滑動距離 , 滑動超過 0.5 滑動幅度 , 觸發(fā)側(cè)滑刪除 ;
② 條件二 : getSwipeEscapeVelocity 方法中設(shè)置的滑動速度 , 水平方向上每秒超過 5 像素的速度 , 觸發(fā)側(cè)滑刪除 ;
5、設(shè)置動畫時間
重寫 ItemTouchHelper.Callback 的 getAnimationDuration 方法 , 設(shè)置用戶的手指離開后的動畫持續(xù)時間 , 單位 毫秒 ms ;
public class Callback extends ItemTouchHelper.Callback {/*** 手指離開后的動畫持續(xù)時間* @param recyclerView* @param animationType* @param animateDx* @param animateDy* @return*/@Overridepublic long getAnimationDuration(@NonNull RecyclerView recyclerView,int animationType,float animateDx, float animateDy) {return 200L;} }6、設(shè)置側(cè)滑刪除觸發(fā)操作
重寫 ItemTouchHelper.Callback 的 onSwiped 方法 , 用戶側(cè)滑判定成功后 , 會調(diào)用該方法 , 如果側(cè)滑判定不成功 , 則不會調(diào)用該方法 ;
側(cè)滑判定 : 這里有兩種側(cè)滑判定條件 , 滿足任意一個即可觸發(fā)側(cè)滑刪除 ;
① 條件一 : getSwipeThreshold 方法中設(shè)置的滑動距離 , 滑動超過 0.5 滑動幅度 , 觸發(fā)側(cè)滑刪除 ;
② 條件二 : getSwipeEscapeVelocity 方法中設(shè)置的滑動速度 , 水平方向上每秒超過 5 像素的速度 , 觸發(fā)側(cè)滑刪除 ;
可以只設(shè)置一個 , 也可以都設(shè)置 ;
public class Callback extends ItemTouchHelper.Callback {/*** 滑動時的回調(diào)操作* @param viewHolder* @param direction*/@Overridepublic void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {Log.i(TAG, "觸發(fā)側(cè)滑刪除條目");// 滑動指定的距離, 達到一定幅度后, 就會觸發(fā)該方法回調(diào)// 這里做的是滑動刪除功能, 直接刪除滑動項// 該方法中刪除指定條目, 并刷新界面mAdapter.deleteItem(viewHolder.getAdapterPosition());} }
7、RecyclerView.Adapter 適配器中的刪除操作
刪除數(shù)據(jù)列表中的元素 , 并調(diào)用 notifyItemRemoved 觸發(fā)刪除動畫 ;
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {/*** 刪除元素調(diào)用的方法* @param position*/public void deleteItem(int position) {names.remove(position);notifyItemRemoved(position);}}三、完整代碼實現(xiàn)
1、主界面
package kim.hsl.recyclerview;import android.graphics.Color; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView;import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager;import java.util.ArrayList;public class MainActivity extends AppCompatActivity {/*** 數(shù)據(jù)源*/private ArrayList<String> names = new ArrayList<String>();/*** 當(dāng)前的 RecyclerView 列表*/private RecyclerView recycler_view;/*** 布局管理器*/private LinearLayoutManager layoutManager;/*** 適配器*/private Adapter adapter;/*** 添加拖動處理*/private ItemTouchHelper mItemTouchHelper;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 初始化數(shù)據(jù)initData();//1 . 從布局中獲取 RecyclerViewrecycler_view = findViewById(R.id.recycler_view);//2 . 創(chuàng)建并設(shè)置布局管理器//創(chuàng)建布局管理器layoutManager = new LinearLayoutManager(this,RecyclerView.VERTICAL,false);//設(shè)置布局管理器recycler_view.setLayoutManager(layoutManager);// 設(shè)置邊距recycler_view.addItemDecoration(new ItemDecoration());//3 . 創(chuàng)建并設(shè)置列表適配器adapter = new Adapter();recycler_view.setAdapter(adapter);//4. 添加拖動事件Callback callback = new Callback(adapter);mItemTouchHelper = new ItemTouchHelper(callback);mItemTouchHelper.attachToRecyclerView(recycler_view);}/*** 初始化數(shù)據(jù)*/private void initData(){names.add("宋江");names.add("盧俊義");names.add("吳用");names.add("公孫勝");names.add("關(guān)勝");names.add("林沖");names.add("秦明");names.add("呼延灼");names.add("花榮");names.add("柴進");names.add("李應(yīng)");names.add("朱仝");names.add("魯智深");names.add("武松");names.add("董平");names.add("張清");names.add("楊志");names.add("徐寧");names.add("索超");}/*** RecyclerView 適配器*/public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {private RecyclerView mRecyclerView;@Overridepublic void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {super.onAttachedToRecyclerView(recyclerView);this.mRecyclerView = recyclerView;}@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View root_view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_recyclerview, parent, false);return new ViewHolder(root_view);}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, int position) {holder.text.setText("" + names.get(position));}@Overridepublic int getItemCount() {return names.size();}public class ViewHolder extends RecyclerView.ViewHolder {TextView text;public ViewHolder(@NonNull View itemView) {super(itemView);text = itemView.findViewById(R.id.text);}}/*** 刪除元素調(diào)用的方法* @param position*/public void deleteItem(int position) {names.remove(position);notifyItemRemoved(position);}}}
2、ItemTouchHelper.Callback 回調(diào)類
package kim.hsl.recyclerview;import android.util.Log;import androidx.annotation.NonNull; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView;public class Callback extends ItemTouchHelper.Callback {private static final String TAG = "Callback";private MainActivity.Adapter mAdapter;public Callback(MainActivity.Adapter mAdapter) {this.mAdapter = mAdapter;}/*** 設(shè)置上下左右動作* 只有在此處打開了指定方向的設(shè)置 , 才可以應(yīng)用具體方向的拖動* @param recyclerView* @param viewHolder* @return*/@Overridepublic int getMovementFlags(@NonNull RecyclerView recyclerView,@NonNull RecyclerView.ViewHolder viewHolder) {// 設(shè)置拖動方向, 此處設(shè)置上下拖動事件int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;// 設(shè)置滑動方向, 此處設(shè)置左右側(cè)滑事件int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;// 應(yīng)用 拖動 和 滑動 設(shè)置return makeMovementFlags(dragFlags, swipeFlags);}/*以下是拖動相關(guān)方法*//*** 是否啟用長按拖動功能* @return*/@Overridepublic boolean isLongPressDragEnabled() {return true;}/*** 拖動幅度設(shè)置* 組件在寬度 / 高度 上移動超過該比例 , 就認為拖動觸發(fā), 執(zhí)行拖動相關(guān)操作* @param viewHolder* @return*/@Overridepublic float getMoveThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {// 該案例中, 拖動操作只能上下進行// 拖動超過條目組件高度超過 0.9 倍, 即可觸發(fā)拖動操作return 0.9f;}/*** 監(jiān)聽滑動事件* 滑動分 水平 / 垂直 兩個方向* @param recyclerView* @param viewHolder* @param target* @return*/@Overridepublic boolean onMove(@NonNull RecyclerView recyclerView,@NonNull RecyclerView.ViewHolder viewHolder,@NonNull RecyclerView.ViewHolder target) {// 拖動后交換數(shù)據(jù), 該方法中交換 Adapter 中的數(shù)據(jù), 并刷新界面Log.i(TAG, "觸發(fā)拖動交換條目");return true;}/*以下是滑動相關(guān)方法*//*** 是否啟用滑動操作* @return 是否啟用 true 啟用, false 不啟用*/@Overridepublic boolean isItemViewSwipeEnabled() {return true;}/*** 用戶滑動距離, 設(shè)置的是比例值, 返回值為 0.5 , 就意味著滑動寬度/高度的一半, 才觸發(fā)側(cè)滑 onSwiped 方法* @param viewHolder* @return*/@Overridepublic float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {return 0.5f;}/*** 滑動判定速度, 每秒移動的像素個數(shù), 達到該速度后, 才可以被判定為滑動* @param defaultValue* @return*/@Overridepublic float getSwipeEscapeVelocity(float defaultValue) {return 5000f;}/*** 手指離開后的動畫持續(xù)時間* @param recyclerView* @param animationType* @param animateDx* @param animateDy* @return*/@Overridepublic long getAnimationDuration(@NonNull RecyclerView recyclerView,int animationType,float animateDx, float animateDy) {return 200L;}/*** 滑動時的回調(diào)操作* @param viewHolder* @param direction*/@Overridepublic void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {Log.i(TAG, "觸發(fā)側(cè)滑刪除條目");// 滑動指定的距離, 達到一定幅度后, 就會觸發(fā)該方法回調(diào)// 這里做的是滑動刪除功能, 直接刪除滑動項// 該方法中刪除指定條目, 并刷新界面mAdapter.deleteItem(viewHolder.getAdapterPosition());} }
3、執(zhí)行效果
三、博客資源
博客資源 :
- GitHub 地址 : https://github.com/han1202012/001_RecyclerView
總結(jié)
以上是生活随笔為你收集整理的【Android 事件分发】ItemTouchHelper 实现侧滑删除的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 事件分发】ItemTo
- 下一篇: 【Android 事件分发】ItemTo