ItemTouchHelper.Callback實(shí)現(xiàn)仿朋友圈發(fā)布圖片拖拽排序

項(xiàng)目需求需要類似發(fā)布朋友圈拖拽排序的功能,故此記錄一下锣枝,感謝Android SDK的強(qiáng)大。

API鏈接:https://developer.android.com/reference/android/support/v7/widget/helper/ItemTouchHelper.Callback

效果視頻連接:https://blog.csdn.net/CCstar1/article/details/89284445

網(wǎng)上有很多使用GirdView實(shí)現(xiàn)拖拽排序效果相對來說比較復(fù)雜撇叁,在保證效率和質(zhì)量的情況下我這里選擇使用RecycleView,官方提供了TiemTouchHelper來支持此效果的完成陨闹,它的出現(xiàn)本意是上下拖拽實(shí)現(xiàn)排序楞捂,左右拖拽實(shí)現(xiàn)刪除(此處非瀑布流)趋厉。但是實(shí)現(xiàn)拖拽效果已經(jīng)綽綽有余了寨闹。下面我們開始吧君账。

TiemTouchHelper:(官方解釋)

此類是ItemTouchHelper與您的應(yīng)用程序之間的契約。它允許您控制每個ViewHolder啟用觸摸行為乡数,并在用戶執(zhí)行這些操作時(shí)接收回調(diào)椭蹄。

要控制用戶可以對每個視圖執(zhí)行哪些操作净赴,您應(yīng)該覆蓋?getMovementFlags(RecyclerView, ViewHolder)并返回適當(dāng)?shù)姆较驑?biāo)志集绳矩。(LEFT劫侧,RIGHT埋酬,START烧栋,END写妥,?UP审姓,DOWN)珍特。您可以使用?makeMovementFlags(int, int)它輕松構(gòu)建它魔吐。或者酬姆,您可以使用?ItemTouchHelper.SimpleCallback嗜桌。

如果用戶拖動item辞色,ItemTouchHelper將調(diào)用?onMove(recyclerView, dragged, target)。收到此回調(diào)后相满,您應(yīng)該將項(xiàng)目從舊位置(dragged.getAdapterPosition())移動到target.getAdapterPosition()適配器中的新位置()并調(diào)用notifyItemMoved(int, int)层亿。要控制可以刪除視圖的位置立美,您可以覆蓋?canDropOver(RecyclerView, ViewHolder, ViewHolder)。當(dāng)拖動視圖與多個其他視圖重疊時(shí)建蹄,Callback會選擇最近的視圖碌更,拖動的視圖可能會更改位置。雖然此方法適用于許多用例痛单,但如果您有自定義LayoutManager,則可以覆蓋?chooseDropTarget(ViewHolder, java.util.List, int, int)以選擇自定義放置目標(biāo)桦他。

滑動視圖時(shí),ItemTouchHelper會對其進(jìn)行動畫處理快压,直到它超出范圍,然后調(diào)用?onSwiped(ViewHolder, int)蔫劣。此時(shí)坪郭,您應(yīng)該更新適配器(例如刪除item)并調(diào)用相關(guān)的Adapter#notify事件脉幢。

自定義了Recycleview實(shí)現(xiàn)拖拽,更換位置有數(shù)據(jù)換位置然后刷新實(shí)現(xiàn)并非Recycleview自己實(shí)現(xiàn)嫌松,代碼如下:

public class DragItemRecyclerView extends RecyclerView {

? ? private ItemTouchHelper itemTouchHelper;

? ? private DragAdapter dragAdapter;

? ? private float ALPHA_FULL = 1.0f;

? ? public DragItemRecyclerView(Context context) {

? ? ? ? super(context);

? ? }

? ? public DragItemRecyclerView(Context context, @Nullable AttributeSet attrs) {

? ? ? ? super(context, attrs);

? ? }

? ? public DragItemRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {

? ? ? ? super(context, attrs, defStyle);

? ? }

? ? @Override

? ? public void setAdapter(Adapter adapter) {

? ? ? ? super.setAdapter(adapter);

? ? ? ? dragAdapter = (DragAdapter) adapter;

? ? ? ? init();

? ? }

? ? private void init() {

? ? ? ? this.getItemAnimator().setChangeDuration(0);

? ? ? ? if (itemTouchHelper == null) {

? ? ? ? ? ? itemTouchHelper = new ItemTouchHelper(new ItemTouchHelperCallback());

? ? ? ? ? ? itemTouchHelper.attachToRecyclerView(this);

? ? ? ? }

? ? }

? ? public class ItemTouchHelperCallback extends ItemTouchHelper.Callback {

? ? ? ? int endPosition, startPosition;

? ? ? ? @Override

? ? ? ? public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {

? ? ? ? ? ? if (dragAdapter.list != null && !TextUtils.isEmpty(dragAdapter.list.get(viewHolder.getAdapterPosition())) && dragAdapter.list.get(viewHolder.getAdapterPosition()).equals(CreateTopicActivity.ADD_IMAGE)) {

? ? ? ? ? ? ? ? return makeMovementFlags(0, 0);

? ? ? ? ? ? }

? ? ? ? ? ? if (dragAdapter.list != null && !TextUtils.isEmpty(dragAdapter.list.get(viewHolder.getAdapterPosition())) && !PhotoTools.isImageFile(dragAdapter.list.get(viewHolder.getAdapterPosition()))) {

? ? ? ? ? ? ? ? return makeMovementFlags(0, 0);

? ? ? ? ? ? }

? ? ? ? ? ? if (recyclerView.getLayoutManager() instanceof GridLayoutManager || recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager) {

? ? ? ? ? ? ? ? final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;

? ? ? ? ? ? ? ? //不需要滑動

? ? ? ? ? ? ? ? final int swipeFlags = 0;

? ? ? ? ? ? ? ? return makeMovementFlags(dragFlags, swipeFlags);

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;

? ? ? ? ? ? ? ? final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;

? ? ? ? ? ? ? ? return makeMovementFlags(dragFlags, swipeFlags);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target) {

? ? ? ? ? ? if (viewHolder.getItemViewType() != target.getItemViewType()) {

? ? ? ? ? ? ? ? return false;

? ? ? ? ? ? }

? ? ? ? ? ? startPosition = viewHolder.getAdapterPosition();

? ? ? ? ? ? endPosition = target.getAdapterPosition();

? ? ? ? ? ? return dragAdapter.onItemMove(startPosition, endPosition);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void clearView(@NonNull RecyclerView recyclerView, @NonNull ViewHolder viewHolder) {

? ? ? ? ? ? super.clearView(recyclerView, viewHolder);

? ? ? ? ? ? if (dragAdapter != null) {

? ? ? ? ? ? ? ? dragAdapter.notifyItemRangeChanged(Math.min(startPosition, endPosition), Math.abs(startPosition - endPosition) + 1);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean canDropOver(RecyclerView recyclerView, ViewHolder current, ViewHolder target) {

? ? ? ? ? ? return true;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onSwiped(ViewHolder viewHolder, int direction) {

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean isLongPressDragEnabled() {

? ? ? ? ? ? return true;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {

? ? ? ? ? ? if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {

? ? ? ? ? ? ? ? //自定義滑動動畫

? ? ? ? ? ? ? ? final float alpha = ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth();

? ? ? ? ? ? ? ? viewHolder.itemView.setAlpha(alpha);

? ? ? ? ? ? ? ? viewHolder.itemView.setTranslationX(dX);

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? public interface ItemTouchHelperAdapter {

? ? ? ? //數(shù)據(jù)交換

? ? ? ? boolean onItemMove(int fromPosition, int toPosition);

? ? }

}

adapter相關(guān)代碼萎羔,主要是onMore調(diào)起在adapter內(nèi)方法,根據(jù)返回更換位置item的position更換數(shù)據(jù)位置然后notify贾陷,代碼如下:

? ? @Override

? ? public boolean onItemMove(int fromPosition, int toPosition) {

? ? ? ? if (list.get(toPosition).equals(CreateTopicActivity.ADD_IMAGE))

? ? ? ? ? ? return false;

? ? ? ? if (!PhotoTools.isImageFile(list.get(toPosition)))

? ? ? ? ? ? return false;

? ? ? ? //交換位置

? ? ? ? Collections.swap(list, fromPosition, toPosition);

? ? ? ? notifyItemMoved(fromPosition, toPosition);

? ? ? ? return true;

? ? }

上述第一個if是判斷是不是添加按鈕,如果是不更換髓废,需求默認(rèn)添加按鈕在最后巷懈。第二個if判斷是否是視頻慌洪,視頻需求默認(rèn)第一位也不可更換位置顶燕。

大家沒有看錯就這點(diǎn)代碼實(shí)現(xiàn)了所有功能,如果大家還有什么問題歡迎留言蒋譬。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愉适,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子维咸,更是在濱河造成了極大的恐慌惠爽,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婚肆,死亡現(xiàn)場離奇詭異,居然都是意外死亡坐慰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門结胀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人糟港,你說我怎么就攤上這事〗崭В” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵剥汤,是天一觀的道長。 經(jīng)常有香客問我吭敢,道長慈迈,這世上最難降的妖魔是什么省有? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任痒留,我火速辦了婚禮蠢沿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘舷蟀。我一直安慰自己恤磷,他們只是感情好野宜,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著匈子,像睡著了一般河胎。 火紅的嫁衣襯著肌膚如雪虎敦。 梳的紋絲不亂的頭發(fā)上游岳,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天政敢,我揣著相機(jī)與錄音,去河邊找鬼胚迫。 笑死喷户,一個胖子當(dāng)著我的面吹牛访锻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播期犬,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哭懈!你這毒婦竟也來了灾馒?” 一聲冷哼從身側(cè)響起遣总,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎旭斥,沒想到半個月后容达,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡垂券,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了菇爪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡凳宙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氏涩,到底是詐尸還是另有隱情届囚,我是刑警寧澤是尖,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站饺汹,受9級特大地震影響蛔添,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜作郭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一弦疮、第九天 我趴在偏房一處隱蔽的房頂上張望夹攒。 院中可真熱鬧胁塞,春花似錦咏尝、人聲如沸啸罢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽允懂。三九已至衩匣,卻和暖如春蕾总,著一層夾襖步出監(jiān)牢的瞬間琅捏,已是汗流浹背生百。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工柄延, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚀浆,地道東北人搜吧。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像滤奈,于是被迫代替她去往敵國和親秕衙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 家里兄弟姐妹比較多据忘,父親早逝搞糕,留下母親一個人處理大家庭矛盾勇吊,處理方向是和平窍仰,事實(shí)上卻有很多無法平息的涌動汉规。父親與母...
    寂滅Ganesha泳卉閱讀 485評論 0 0
  • Dubbo入門-協(xié)議&注冊中心 一、配置dubbo多協(xié)議模式 1针史、默認(rèn)協(xié)議 Dubbo缺省協(xié)議采用單一長連接和NI...
    Java幫幫閱讀 1,171評論 1 4
  • 江山如畫婚陪,憑誰記频祝,眸底深處伊人笑泌参。 繁花似錦常空,煙波碎沽一,桃花落盡人已非漓糙。 而今铣缠,一縷輕愁,任憑江山無限攘残,與誰共。 斷...
    雨晴煙晚斷閱讀 634評論 0 0
  • 嵊縣板川訪贈賢弟明亮 黃磊/文 越秀靈毓鼎奇殊歼郭,板川鶴立賽名廚。 青山送吾至剡溪辐棒,圣水為鳴鼓與呼。 潔身守立去百污...
    黃磊的簡書閱讀 275評論 0 5