1. 程式人生 > >Android自定義View——可拖拽的ListView

Android自定義View——可拖拽的ListView

有時時候需要對ListView的Item進行手動拖拽排序,如安桌系統中的對通知欄的開關排序,因此需要自定義一個可拖拽的ListView,效果如下:

可見,該ListView只有已新增欄可以拖動,同時可以拖動到未新增欄中,且拖動到頂部或底部時,會自動滾動列表。實現的基本原理為:

1.當點選列表時,獲取點選的itemView

int position = pointToPosition(x, y);
View itemView = getChildAt(position - getFirstVisiblePosition());


2.獲取itemView的DrawingCache

itemView.setDrawingCacheEnabled(true); // 開啟cache.
mBitmap = Bitmap.createBitmap(itemView.getDrawingCache()); // 根據cache建立一個新的bitmap物件.
itemView.setDrawingCacheEnabled(false);

3.根據拖拽的位置繪製DrawingCache

protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
// 繪製拖拽的itemView,mLastY為觸控點的y座標,mDragViewOffset為觸控點在itemView中的座標y
if (mBitmap != null && !mBitmap.isRecycled()) {
    canvas.drawBitmap(mBitmap, 0, mLastY - mDragViewOffset, null);
}
}

4.拖拽的過程中,判斷是否交換位置

 private void checkExchange(int y) {
        if (mCurrentPosition != mLastPosition) { // // 資料交換
            if (mDragItemListener != null) {
                if (mDragItemListener.canExchange(mLastPosition, mCurrentPosition)) { // 進行資料交換,true則表示交換成功
                    View lastView = mItemView;
                    mItemView = getChildAt(mCurrentPosition - getFirstVisiblePosition());
                    // 通知交換資料成功,可在此時設定交換的動畫效果
                    mDragItemListener.onExchange(mLastPosition, mCurrentPosition, lastView, mItemView);
                    mLastPosition = mCurrentPosition;
                }
            }
        }
    }


5.當移動到底部時,ListView向上滑動,當移動到頂部時,ListView要向下滑動

 public void checkScroller(final int y) {

        int offset = 0;
        if (y < mAutoScrollUpY) { // 拖動到頂部,ListView需要下滑
            if (y <= mDownY - mTouchSlop) {
                offset = dp2px(getContext(), 6); // 滑動的距離
            }
        } else if (y > mAutoScrollDownY) { // 拖動到底部,ListView需要上滑
            if (y >= mDownY + mTouchSlop) {
                offset = -dp2px(getContext(), 6); // 滑動的距離
            }
        }

        if (offset != 0) {
            View view = getChildAt(mCurrentPosition - getFirstVisiblePosition());
            if (view != null) {
                // 滾動列表
                setSelectionFromTop(mCurrentPosition, view.getTop() + offset);
                if (!mScrolling) {
                    mScrolling = true;
                    long passed = System.currentTimeMillis() - mLastScrollTime;
                    postDelayed(mScrollRunnable, passed > 15 ? 15 : 15 - passed);
                }
            }
        }
    }

為了相容不同的互動需求,定義了DragItemListener,把跟互動相關的程式碼交給外部。

public interface DragItemListener {

        /**
         * 是否進行資料交換
         *
         * @param srcPosition
         * @param position 當前拖拽的view的索引
         * @return 返回true,則確認資料交換;返回false則表示放棄
         */
        boolean canExchange(int srcPosition, int position);

        /**
         * 當完成資料交換時回撥
         *
         * @param srcPosition
         * @param position    當前拖拽的view的索引
         * @param srcItemView
         * @param itemView 當前拖拽的view
         */
        void onExchange(int srcPosition, int position, View srcItemView, View itemView);

        /**
         * 釋放手指
         *
         * @param position
         */
        void onRelease(int position, View itemView, int itemViewY, int releaseX, int releaseY);

        /**
         * 是否可以拖拽
         *
         * @param itemView
         * @param x        當前觸控的座標
         * @param y
         * @return
         */
        boolean canDrag(View itemView, int x, int y);

        /**
         * 開始拖拽
         *
         * @param position
         */
        void startDrag(int position, View itemView);

        /**
         * 在生成拖影(itemView.getDrawingCache())之前
         *
         * @param itemView
         */
        void beforeDrawingCache(View itemView);

        /**
         * 在生成拖影(itemView.getDrawingCache())之後
         *
         * @param itemView
         * @param bitmap   由itemView.getDrawingCache()生成
         * @return 最終顯示的拖影,如果返回為空則使用itemView.getDrawingCache()
         */
        Bitmap afterDrawingCache(View itemView, Bitmap bitmap);
    }

相關推薦

Android定義View——ListView

有時時候需要對ListView的Item進行手動拖拽排序,如安桌系統中的對通知欄的開關排序,因此需要自定義一個可拖拽的ListView,效果如下: 可見,該ListView只有已新增欄可以拖動,同時可以拖動到未新增欄中,且拖動到頂部或底部時,會自動滾動列表。實現的基

Android 定義View實現效果

騰訊QQ有那種紅點拖動效果,今天就來實現一個簡單的自定義View拖動效果,再回到原處,並非完全仿QQ紅點拖動 先來看一下效果圖 簡單說一下實現步驟 1.建立一個類繼承View 2.繪製出一個

Android 定義View動移動位置及邊緣拉伸放大縮

首先說一下定義這樣一個View有什麼用?在一些app中,需要設定頭像,而使用者選擇的圖片可能是使用攝像頭拍攝,也可能是選擇的相簿裡面的圖片,總之,這樣的圖片大小不一,就比如在使用某個聊天軟體的時候,設定頭像,需要對圖片進行擷取. 要實現這樣一個功能,首先,需

Android 定義View--小球

下面就是大致的功能程式碼 不是特別全面 import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint

Android 定義View隨意動的View

因為趕專案本人停更兩個月 從今天開始又可以更新了 今天說一下這個可隨意拖動的view 簡單說一下這個view效果 和 發展 一開始這種效果是使用在網頁端的特別是購物類 例如某寶 某東 購物車和客服視窗 都有使用這個懸浮可拖動的設計效果 後來才發展到的移動端 還有

Android定義View實現圖片顯示,並實現縮放、、切換功能

這裡貼三個檔案的原始碼,第一個是main.java package com.example.test; import java.util.ArrayList; import java.util.List; import com.example.test.MyXZ; i

Android 定義View(繼承原生元件)實現動移位效果

自定義View實現拖拽移位效果 通過繼承GridLayout實現的拖拽移位效果 首先建立Class類繼承GridLayout並重寫前三個構造方法 public class MyGridlayout extends GridLayout implement

Android 定義View(繼承原生元件)實現動移位效果

自定義View實現拖拽移位效果 通過繼承GridLayout實現的拖拽移位效果 首先建立Class類繼承GridLayout並重寫前三個構造方法 public class MyGridlayout extends GridLayout implements

Android定義View繪圖實現影動畫

前幾天在“Android繪圖之漸隱動畫”一文中通過畫線實現了漸隱動畫,但裡面有個問題,畫筆較粗(大於1)時線段之間會有裂隙,我又改進了一下。這次效果好多了。 先看效果吧: 然後我們來說說基本的做法: 根據畫筆寬度,計算每一條線段兩個頂點對應的四個點,

我的Android進階之旅------>Android定義View來實現解析lrc歌詞並同步滾動、上下動、縮放歌詞的功能

前言 最近有個專案有關於播放音樂時候,關於歌詞有以下幾個功能: 1、實現歌詞同步滾動的功能,即歌曲播放到哪句歌詞,就高亮地顯示出正在播放的這個歌詞; 2、實現上下拖動歌詞時候,可以拖動播放器的進度。即可以不停地上下拖動歌詞,

Android定義ViewListView實現時間軸效果:我只是個送快遞的。

先上效果圖: 實現時間軸的原理 listview的基本使用,相信大家都很熟悉。先在layout下新建一個xml佈局檔案,對應一個子項的listView的顯示內容。在上面的圖我們可以看到,每一項都是 有3個 textview控制元件

android 定義view 圓形移動

Mycircle2 extends View { private Paint paint; private int rawX; private int rawY; private int wid; private int he; int statusBarHe

Android定義View來實現解析lrc歌詞同步滾動、上下動、縮放歌詞等功能

http://blog.csdn.net/ouyang_peng/article/details/50813419 前言 最近有個專案有關於播放音樂時候,關於歌詞有以下幾個功能:  1、實現歌詞同步滾動的功能,即歌曲播放到哪句

Android 定義view:實現ListView下拉的視差特效

一、概述: 現在流型的APP如微信朋友圈,QQ空間,微博個人展示都有視差特效的影子。 如圖:下拉圖片會產生圖片拉昇的效果,放手後圖片有彈回到原處: 那我們如何實現呢? 1)重寫ListView控制元件: 2)重寫裡面的overScrollBy方法

Android定義View-----TitleHead隨列表動漸變---TitleHeadRecyclerView

    仿照網易的有道詞典的專欄詳情的上拉下來效果。特點繼承RecyclerView,重寫onTouchEvent()事件,根據不同情況執行不同的操作。使用LayoutParams改變View引數,實現View的大小改變。使用setX()方法,改變View的座標,實現View

Android定義imageview對圖片進行多點縮放和

package com.msstudent.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import andro

Android 定義View基礎(四)--ListView

這篇文章主要是總結ListView的使用: 首先來說說ListView,幾乎所有的app都在使用listview,所以熟練使用ListView是作為Android移動開發必不可少的。 Adapter ViewHolder setEnpty() 自動隱藏,顯

Android 定義View

wid declare created odi lex getwidth 實現 tdi led   最近在看鴻洋大神的博客,在看到自定義部分View部分時,想到之前案子中經常會要用到"圖片 + 文字"這類控件,如下圖所示: 之前的做法是在布局文件中,將一個Imag

Android定義view詳解

this boolean mar 處理 都是 並且 jdk text 命名 從繼承開始 懂點面向對象語言知識的都知道:封裝,繼承和多態,這是面向對象的三個基本特征,所以在自定義View的時候,最簡單的方法就是繼承現有的View 通過上面這段代碼,我定義了一個Ske

Android -- 定義view實現keep歡迎頁倒計時效果

super onfinish -m use new getc awt ttr alt 1,最近打開keep的app的時候,發現它的歡迎頁面的倒計時效果還不錯,所以打算自己來寫寫,然後就有了這篇文章。 2,還是老規矩,先看一下我們今天實現的效果   相較於我們常見的倒計時