編輯:關於Android編程
前言:
上次呢為大家介紹了如何給RecycleView添加頭部、尾部達到裝飾的效果,那麼本章節將為大家介紹RecycleView實現不一樣的拖動排序以及側滑刪除。
首先呢我們來分析下使用ListView是如何實現拖動排序的,如果我們要使用ListView實現拖動排序,第一反應就是自定義控件了,因為android API提供的ListView是不具備有拖動排序的功能,那麼就會想到要在onTouchEvent去處理,那麼在RecycleView中是怎麼做的呢?需不需要自定義RecycleView呢?
答案是不需要。在RecycleView的jar包裡呢可以看到有ItemTouchHelper這麼一個類,那麼這個類是干嘛用的呢?根據官方的介紹,該類支持RecycleView的拖動排序以及側滑刪除的實用類。看到這裡,那麼是不是覺得RecycleView很牛逼啊,連側滑都可以用,我們平常實現側滑的時候也是需要自定義控件去實現的,但是在RecycleView裡不需要,是不是頓時覺得RecycleView的逼格就提升了,有木有這種感覺。。。
OK,分析完之後呢,我們就需要去使用了,那麼如何使用呢?看我細細寫來,首先先把准備工作做好
布局:
item布局:
Adapter、ViewHolder、分割線處理這裡就不一一列舉了,直接進入主題,RecycleView如何實現拖動排序。
上面為大家介紹了RecycleView的jar包裡有個叫的ItemTouchHelper的類,那麼接下來就是使用這個類來實現效果了。
那麼當我們去實例化的時候就會發現這個類需要回調監聽ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(callback);,接下來就是要去定義一個回調類了
package com.example.recyclerviewdemo4; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper.Callback; public class ItemTouchCallback extends Callback { // Callback回調監聽先調用的方法,用於判斷當前手勢動作 @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { return 0; } // 拖動的時候回調 @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; } // 側滑的時候回調 @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { } }當我們繼承Callback的時候,我們需要重寫這麼幾個方法,如果需要實現長按拖動或者是側滑,就需要在getMovementFlags返回給RecycleView一個方向了,著這裡呢我們需要調用makeMovementFlags這個方法,不能調錯了方法啊,不然的話可沒有效果,這個方法需要傳入兩個參數makeMovementFlags(int dragFlags, int swipeFlags),分別是拖動的Flags,滑動的Flags,在ItemTouchHelper裡,可以看到這麼幾個常量值,分別是:
UP = 1
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { return makeMovementFlags(ItemTouchHelper.DOWN | ItemTouchHelper.UP,ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT); }還有一個要注意的地方就是在onMove的方法裡要返回true,否則沒有拖動的效果。接下來就是在Activy裡使用了:
main_rv = (RecyclerView) findViewById(R.id.main_rv); RecycleViewAdapter mAdapter = new RecycleViewAdapter(MainActivity.this, datas); // 設置Adapter main_rv.setAdapter(mAdapter); // 設置顯示的布局水平顯示 main_rv.setLayoutManager(new LinearLayoutManager(MainActivity.this)); // 添加分割線(繪制水平方向的分割線) main_rv.addItemDecoration(new ItemDecorationDivider(MainActivity.this)); // 回調類 ItemTouchCallback callback = new ItemTouchCallback(); mItemTouchHelper = new ItemTouchHelper(callback); // 關聯RecycleView mItemTouchHelper.attachToRecyclerView(main_rv);接下來就是看效果了:
拖動效果實現了,是不是還沒有交換啊,那麼接下來就是處理交換了,上面介紹了Callback裡有這個一個方法onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,RecyclerView.ViewHolder target),這個麼也就是拖動時候的回調方法,這裡呢有三個參數,第一個就不多說了,第二個參數是指我的拖動的原始位置也就是長按的那個item,target是指拖動的時候需要交換的位置。交換的事情呢就在這裡做了,那麼是不是直接在這裡作交換呢?那當然不是了,如果要做交換的話,那麼是一定需要Adapter的,如果在實例化ItemCallback的時候需要傳入Adapter,這樣是不是耦合度很高啊,這樣做就違背了RecycleView的高度解耦了。在這裡呢我就定義個回調接口,接口如下(這裡就把側滑的也一並帶進去吧):
public interface ItemCallback { // 拖動的時候回調 void onMove(int from, int target); // 側滑的時候回調 void onSwiped(int position); }
接口裡要傳那些參數自定義,這裡就傳一個初始位置還有目標位置了:
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { if (mItemCallback != null) { mItemCallback.onMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); } return true; }
那麼這個接口是不是在Activity裡實現呢?當然也是可以的,我個人建議是不要在Activity裡實現這個接口,這裡呢就在Adapter裡實現這個接口。
public void onMove(int from, int target) { // 交換數據 Collections.swap(mDatas, from, target); // 移動Item notifyItemMoved(from, target); }還有就是在Activity裡要設置監聽了:
callback.setItemCallback(mAdapter);
public interface ItemHeaderIconTouchListener { void onTouchDrag(RecyclerView.ViewHolder holder); }
Adapter回調實現
private ItemHeaderIconTouchListener mItemHeaderIconTouchListener; public void setItemHeaderIconTouchListener(ItemHeaderIconTouchListener mItemHeaderIconTouchListener) { this.mItemHeaderIconTouchListener = mItemHeaderIconTouchListener; } /** * item綁定要顯示的數據 */ @Override public void onBindViewHolder(final RecyclerViewHolder viewHolder, final int position) { viewHolder.drag_sort_item_tv.setText(mDatas.get(position)); //回調 viewHolder.drag_sort_item_iv.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (mItemHeaderIconTouchListener != null) { mItemHeaderIconTouchListener.onTouchDrag(viewHolder); } } return true; } }); }
Activity實現接口:
// 綁定回調接口 mAdapter.setItemHeaderIconTouchListener(this);實現拖動:
@Override public void onTouchDrag(ViewHolder holder) { mItemTouchHelper.startDrag(holder); }
這樣做肯定可以滴,但是既然我們使用了RecycleView,那麼就可以使用RecycleView提供的方法來處理,這樣做是不是感覺更有逼格啊。那麼接下來呢就為大家介紹這兩個方法onSelectedChanged以及clearView,這兩個方法呢分別在DOWN和UP的時候回調。
@Override public void onSelectedChanged(ViewHolder viewHolder, int actionState) { // 處於拖動或者側滑狀態 if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { viewHolder.itemView.setBackgroundColor(Color.RED); } super.onSelectedChanged(viewHolder, actionState); } @SuppressWarnings("deprecation") @Override public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) { viewHolder.itemView .setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(R.color.colorPrimaryDark)); super.clearView(recyclerView, viewHolder); }
總算把拖動排序給搞定了,接下來就是側滑了,上面我們已經使用了getMovementFlags以及onMove,那麼是不是還有一個方法沒有編寫代碼邏輯啊,是的,側滑就在這裡實現。在上面講到定義了回調接口,同樣在onSwap的時候也是交給實現類(在這裡是Adapter)去處理,
Callback裡觸發回調
// 側滑的時候回調 @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { if (mItemCallback != null) { mItemCallback.onSwiped(viewHolder.getAdapterPosition()); } }Adapter裡實現回調:
@Override public void onSwiped(int position) { // 刪除數據 mDatas.remove(position); // 刪除item notifyItemRemoved(position); }
ACTION_STATE_IDLE = 0 閒置狀態
在這裡呢我們只需要側滑的狀態,OK,分析完了之後就上代碼了:
@Override public void onChildDraw(Canvas c, RecyclerView recyclerView, ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { // 側滑狀態 if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { View itemView = viewHolder.itemView; // 百分比 float ratio = 1 - Math.abs(dY) / itemView.getWidth(); itemView.setAlpha(ratio); itemView.setScaleX(ratio); itemView.setScaleY(ratio); } super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); }
有兩個方法:
第一就是在onClearView方法裡添加這麼一段代碼
viewHolder.itemView.setAlpha(1); viewHolder.itemView.setScaleX(1); viewHolder.itemView.setScaleY(1);第二就是在onChildDraw求百分比的時候判斷ration是否為0
if (ratio == 0) { ratio = 1; }這兩種方法都可以達到同樣的效果
好了,RecycleView實現拖動排序以及側滑刪除就到這裡了
本文實例講述了Android編程中的四大基本組件與生命周期。分享給大家供大家參考,具體如下:Android四大基本組件分別是Activity,Service服務,Cont
android客戶端生成本地驗證碼主要用來限制用戶隨意按請求按鈕,其實該示例也是來對自定義view的練練手而已,先給出效果圖吧其中可定制:*干擾線數目*干擾點數目*背景顏
項目地址:https://github.com/JeasonWong/SlackLoadingView老規矩,先上效果。圖好大。。說下第一眼看到這個動畫後的思路:+兩根平
最近將電腦的操作系統換成了ubuntu,對於不習慣win8/win10的人來說ubuntu確實是一個不錯的選擇,基本的軟件都ok了,至於QQ什麼的,大家可以去找wine版