天天看點

Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換

轉帖請注明本文出自xiaanming的部落格(http://blog.csdn.net/xiaanming/article/details/17718579),請尊重他人的辛勤勞動成果,謝謝!

在android開發中,我們常常用到listview和gridview,而有的時候系統的listview,gridview并不能滿足我們的需求,是以我們需要自己定義一個listview或者gridview,我的上一篇文章中就是自定義的一個左右滑動删除item的例子,大家有興趣的可以去看看 android

使用scroller實作絢麗的listview左右滑動删除item效果,今天這篇文章就給大家來自定義gridview的控件,gridview主要是來顯示網格的控件,在android的開發中使用很普通,相對于textview,button這些控件來說要來的複雜些,今天給大家帶來長按gridview的item,然後将其拖拽其他item上面,使得gridview的item發生交換,比較典型的就是我們的launcher,網上有很多關于gridview的拖動的demo,但是大部分都是相同的,而且存在一些bug,而且大部分都是點選gridview的item然後進行拖動,或者item之間不進行實時交換,今天給大家更加詳細的介紹gridview拖拽,并且将demo做的更完美,大家更容易接受,也許很多人聽到這個感覺實作起來很複雜,就關掉的這篇文章,其實告訴大家,隻要知道了思路就感覺一點都不複雜了,不信大家可以接着往下看看,首先還是跟大家說說實作的思路

根據手指按下的x,y坐标來擷取我們在gridview上面點選的item

手指按下的時候使用handler和runnable來實作一個定時器,假如定時時間為1000毫秒,在1000毫秒内,如果手指擡起了移除定時器,沒有擡起并且手指點選在gridview的item所在的區域,則表示我們長按了gridview的item

如果我們長按了item則隐藏item,然後使用windowmanager來添加一個item的鏡像在螢幕用來代替剛剛隐藏的item

當我們手指在螢幕移動的時候,更新item鏡像的位置,然後在根據我們移動的x,y的坐标來擷取移動到gridview的哪一個位置

到gridview的item過多的時候,可能一螢幕顯示不完,我們手指拖動item鏡像到螢幕下方,要觸發gridview想上滾動,同理,當我們手指拖動item鏡像到螢幕上面,觸發gridview向下滾動

gridview交換資料,重新整理界面,移除item的鏡像

看完上面的這些思路你是不是找到了些感覺了呢,心裡癢癢的想動手試試吧,好吧,接下來就帶大家根據思路來實作可拖拽的gridview,建立一個項目就叫draggridview

建立一個類draggridview繼承gridview,先來看看draggridview的代碼,然後在根據代碼進行相關的講解

[java] view

plaincopy

Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換
Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換

package com.example.draggridview;  

import android.annotation.suppresslint;  

import android.app.activity;  

import android.content.context;  

import android.graphics.bitmap;  

import android.graphics.pixelformat;  

import android.graphics.rect;  

import android.os.handler;  

import android.os.vibrator;  

import android.text.getchars;  

import android.util.attributeset;  

import android.view.gravity;  

import android.view.motionevent;  

import android.view.view;  

import android.view.windowmanager;  

import android.widget.adapterview;  

import android.widget.gridview;  

import android.widget.imageview;  

/** 

 * @blog http://blog.csdn.net/xiaanming  

 *  

 * @author xiaanming 

 * 

 */  

@suppresslint("newapi")  

public class draggridview extends gridview{  

    /** 

     * draggridview的item長按響應的時間, 預設是1000毫秒,也可以自行設定 

     */  

    private long dragresponsems = 1000;  

     * 是否可以拖拽,預設不可以 

    private boolean isdrag = false;  

    private int mdownx;  

    private int mdowny;  

    private int movex;  

    private int movey;  

     * 正在拖拽的position 

    private int mdragposition;  

     * 剛開始拖拽的item對應的view 

    private view mstartdragitemview = null;  

     * 用于拖拽的鏡像,這裡直接用一個imageview 

    private imageview mdragimageview;  

     * 震動器 

    private vibrator mvibrator;  

    private windowmanager mwindowmanager;  

     * item鏡像的布局參數 

    private windowmanager.layoutparams mwindowlayoutparams;  

     * 我們拖拽的item對應的bitmap 

    private bitmap mdragbitmap;  

     * 按下的點到所在item的上邊緣的距離 

    private int mpoint2itemtop ;   

     * 按下的點到所在item的左邊緣的距離 

    private int mpoint2itemleft;  

     * draggridview距離螢幕頂部的偏移量 

    private int moffset2top;  

     * draggridview距離螢幕左邊的偏移量 

    private int moffset2left;  

     * 狀态欄的高度 

    private int mstatusheight;   

     * draggridview自動向下滾動的邊界值 

    private int mdownscrollborder;  

     * draggridview自動向上滾動的邊界值 

    private int mupscrollborder;  

     * draggridview自動滾動的速度 

    private static final int speed = 80;  

     * item發生變化回調的接口 

    private onchanagelistener onchanagelistener;  

    public draggridview(context context) {  

        this(context, null);  

    }  

    public draggridview(context context, attributeset attrs) {  

        this(context, attrs, 0);  

    public draggridview(context context, attributeset attrs, int defstyle) {  

        super(context, attrs, defstyle);  

        mvibrator = (vibrator) context.getsystemservice(context.vibrator_service);  

        mwindowmanager = (windowmanager) context.getsystemservice(context.window_service);  

        mstatusheight = getstatusheight(context); //擷取狀态欄的高度  

    private handler mhandler = new handler();  

    //用來處理是否為長按的runnable  

    private runnable mlongclickrunnable = new runnable() {  

        @override  

        public void run() {  

            isdrag = true; //設定可以拖拽  

            mvibrator.vibrate(50); //震動一下  

            mstartdragitemview.setvisibility(view.invisible);//隐藏該item  

            //根據我們按下的點顯示item鏡像  

            createdragimage(mdragbitmap, mdownx, mdowny);  

        }  

    };  

     * 設定回調接口 

     * @param onchanagelistener 

    public void setonchangelistener(onchanagelistener onchanagelistener){  

        this.onchanagelistener = onchanagelistener;  

     * 設定響應拖拽的毫秒數,預設是1000毫秒 

     * @param dragresponsems 

    public void setdragresponsems(long dragresponsems) {  

        this.dragresponsems = dragresponsems;  

    @override  

    public boolean dispatchtouchevent(motionevent ev) {  

        switch(ev.getaction()){  

        case motionevent.action_down:  

            //使用handler延遲dragresponsems執行mlongclickrunnable  

            mhandler.postdelayed(mlongclickrunnable, dragresponsems);  

            mdownx = (int) ev.getx();  

            mdowny = (int) ev.gety();  

            //根據按下的x,y坐标擷取所點選item的position  

            mdragposition = pointtoposition(mdownx, mdowny);  

            if(mdragposition == adapterview.invalid_position){  

                return super.dispatchtouchevent(ev);  

            }  

            //根據position擷取該item所對應的view  

            mstartdragitemview = getchildat(mdragposition - getfirstvisibleposition());  

            //下面這幾個距離大家可以參考我的部落格上面的圖來了解下  

            mpoint2itemtop = mdowny - mstartdragitemview.gettop();  

            mpoint2itemleft = mdownx - mstartdragitemview.getleft();  

            moffset2top = (int) (ev.getrawy() - mdowny);  

            moffset2left = (int) (ev.getrawx() - mdownx);  

            //擷取draggridview自動向上滾動的偏移量,小于這個值,draggridview向下滾動  

            mdownscrollborder = getheight() /4;  

            //擷取draggridview自動向下滾動的偏移量,大于這個值,draggridview向上滾動  

            mupscrollborder = getheight() * 3/4;  

            //開啟mdragitemview繪圖緩存  

            mstartdragitemview.setdrawingcacheenabled(true);  

            //擷取mdragitemview在緩存中的bitmap對象  

            mdragbitmap = bitmap.createbitmap(mstartdragitemview.getdrawingcache());  

            //這一步很關鍵,釋放繪圖緩存,避免出現重複的鏡像  

            mstartdragitemview.destroydrawingcache();  

            break;  

        case motionevent.action_move:  

            int movex = (int)ev.getx();  

            int movey = (int) ev.gety();  

            //如果我們在按下的item上面移動,隻要不超過item的邊界我們就不移除mrunnable  

            if(!istouchinitem(mstartdragitemview, movex, movey)){  

                mhandler.removecallbacks(mlongclickrunnable);  

        case motionevent.action_up:  

            mhandler.removecallbacks(mlongclickrunnable);  

            mhandler.removecallbacks(mscrollrunnable);  

        return super.dispatchtouchevent(ev);  

     * 是否點選在gridview的item上面 

     * @param itemview 

     * @param x 

     * @param y 

     * @return 

    private boolean istouchinitem(view dragview, int x, int y){  

        int leftoffset = dragview.getleft();  

        int topoffset = dragview.gettop();  

        if(x < leftoffset || x > leftoffset + dragview.getwidth()){  

            return false;  

        if(y < topoffset || y > topoffset + dragview.getheight()){  

        return true;  

    public boolean ontouchevent(motionevent ev) {  

        if(isdrag && mdragimageview != null){  

            switch(ev.getaction()){  

            case motionevent.action_move:  

                movex = (int) ev.getx();  

                movey = (int) ev.gety();  

                //拖動item  

                ondragitem(movex, movey);  

                break;  

            case motionevent.action_up:  

                onstopdrag();  

                isdrag = false;  

            return true;  

        return super.ontouchevent(ev);  

     * 建立拖動的鏡像 

     * @param bitmap  

     * @param downx 

     *          按下的點相對父控件的x坐标 

     * @param downy 

    private void createdragimage(bitmap bitmap, int downx , int downy){  

        mwindowlayoutparams = new windowmanager.layoutparams();  

        mwindowlayoutparams.format = pixelformat.translucent; //圖檔之外的其他地方透明  

        mwindowlayoutparams.gravity = gravity.top | gravity.left;  

        mwindowlayoutparams.x = downx - mpoint2itemleft + moffset2left;  

        mwindowlayoutparams.y = downy - mpoint2itemtop + moffset2top - mstatusheight;  

        mwindowlayoutparams.alpha = 0.55f; //透明度  

        mwindowlayoutparams.width = windowmanager.layoutparams.wrap_content;    

        mwindowlayoutparams.height = windowmanager.layoutparams.wrap_content;    

        mwindowlayoutparams.flags = windowmanager.layoutparams.flag_not_focusable    

                    | windowmanager.layoutparams.flag_not_touchable ;  

        mdragimageview = new imageview(getcontext());    

        mdragimageview.setimagebitmap(bitmap);    

        mwindowmanager.addview(mdragimageview, mwindowlayoutparams);    

     * 從界面上面移動拖動鏡像 

    private void removedragimage(){  

        if(mdragimageview != null){  

            mwindowmanager.removeview(mdragimageview);  

            mdragimageview = null;  

     * 拖動item,在裡面實作了item鏡像的位置更新,item的互相交換以及gridview的自行滾動 

    private void ondragitem(int movex, int movey){  

        mwindowlayoutparams.x = movex - mpoint2itemleft + moffset2left;  

        mwindowlayoutparams.y = movey - mpoint2itemtop + moffset2top - mstatusheight;  

        mwindowmanager.updateviewlayout(mdragimageview, mwindowlayoutparams); //更新鏡像的位置  

        onswapitem(movex, movey);  

        //gridview自動滾動  

        mhandler.post(mscrollrunnable);  

     * 當movey的值大于向上滾動的邊界值,觸發gridview自動向上滾動 

     * 當movey的值小于向下滾動的邊界值,觸犯gridview自動向下滾動 

     * 否則不進行滾動 

    private runnable mscrollrunnable = new runnable() {  

            int scrolly;  

            if(movey > mupscrollborder){  

                 scrolly = -speed;  

                 mhandler.postdelayed(mscrollrunnable, 25);  

            }else if(movey < mdownscrollborder){  

                scrolly = speed;  

            }else{  

                scrolly = 0;  

                mhandler.removecallbacks(mscrollrunnable);  

            //當我們的手指到達gridview向上或者向下滾動的偏移量的時候,可能我們手指沒有移動,但是draggridview在自動的滾動  

            //是以我們在這裡調用下onswapitem()方法來交換item  

            onswapitem(movex, movey);  

            view view = getchildat(mdragposition - getfirstvisibleposition());  

            //實作gridview的自動滾動  

            smoothscrolltopositionfromtop(mdragposition, view.gettop() + scrolly);  

     * 交換item,并且控制item之間的顯示與隐藏效果 

     * @param movex 

     * @param movey 

    private void onswapitem(int movex, int movey){  

        //擷取我們手指移動到的那個item的position  

        int tempposition = pointtoposition(movex, movey);  

        //假如tempposition 改變了并且tempposition不等于-1,則進行交換  

        if(tempposition != mdragposition && tempposition != adapterview.invalid_position){  

            getchildat(tempposition - getfirstvisibleposition()).setvisibility(view.invisible);//拖動到了新的item,新的item隐藏掉  

            getchildat(mdragposition - getfirstvisibleposition()).setvisibility(view.visible);//之前的item顯示出來  

            if(onchanagelistener != null){  

                onchanagelistener.onchange(mdragposition, tempposition);  

            mdragposition = tempposition;  

     * 停止拖拽我們将之前隐藏的item顯示出來,并将鏡像移除 

    private void onstopdrag(){  

        getchildat(mdragposition - getfirstvisibleposition()).setvisibility(view.visible);  

        removedragimage();  

     * 擷取狀态欄的高度 

     * @param context 

    private static int getstatusheight(context context){  

        int statusheight = 0;  

        rect localrect = new rect();  

        ((activity) context).getwindow().getdecorview().getwindowvisibledisplayframe(localrect);  

        statusheight = localrect.top;  

        if (0 == statusheight){  

            class<?> localclass;  

            try {  

                localclass = class.forname("com.android.internal.r$dimen");  

                object localobject = localclass.newinstance();  

                int i5 = integer.parseint(localclass.getfield("status_bar_height").get(localobject).tostring());  

                statusheight = context.getresources().getdimensionpixelsize(i5);  

            } catch (exception e) {  

                e.printstacktrace();  

            }   

        return statusheight;  

     *  

     * @author xiaanming 

     * 

    public interface onchanagelistener{  

        /** 

         * 當item交換位置的時候回調的方法,我們隻需要在該方法中實作資料的交換即可 

         * @param form 

         *          開始的position 

         * @param to  

         *          拖拽到的position 

         */  

        public void onchange(int form, int to);  

}  

首先看draggridview的事件分發方法,不了解android事件分發的可以先去了解下,android事件分發對于自定義控件很重要,簡單說下,當我們點選draggridview的item,先會去執行dispatchtouchevent()方法将事件分發下去,是以我們要重寫dispatchtouchevent()方法在手指按下的時候根據pointtoposition()方法來擷取我們按下的item的position,根據getchildat()方法來擷取該position上面所對應的view,

并且開啟長按的定時器,預設時間為1000毫秒,如果在1000毫秒内手指擡起或者手指在螢幕上滑動出了該item,則取消長按定時器,否則就表示可以進行拖拽,手機友好的震動一下,隐藏我們長按的item,螢幕調用createdragimage()方法來建立我們長按的item的鏡像,建立item的鏡像使用的是windowmanager類,該類可以建立一個窗體顯示在activity之上,

再此之前大家先要了解這幾個距離,了解這幾個距離之前要首先知道getrawx(),getrawy()和getx(),gety()的差別,getrawx(),getrawy()是相對于螢幕的原點的距離,而getx(),gety()是相對于控件左上方的點的距離,為了友善大家了解我用word簡單的畫了下圖,畫得不好,大家将就的看下,紅色框框為我們的gridview

Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換

mpoint2itemtop 手指按下的點到該item的上邊緣的距離,如上圖的1号線

mpoint2itemleft 手指按下的點到該item的左邊緣的距離,如上圖的2号線

moffset2top  draggridview的上邊緣到螢幕上邊緣的距離,如上圖的3号線,這個距離包裹狀态欄,标題欄,或者一些在draggridview上面的布局的高度,這個很重要我們現實item鏡像需要用到

moffset2left draggridview的左邊緣到螢幕左邊緣的距離,如上圖的4号線,我這個demo的這個距離為0,因為我設定draggridview的寬度為充滿螢幕,但是我們要考慮假如draggridview與螢幕左邊緣設定了間隙或者左邊有其他的布局的情形

mdownscrollborder 這個距離表示當draggridview的item過多的時候,手機一屏顯示不完全,我們拖動item鏡像到這個高度的時候,draggridview自動向下滾動,如上圖的5号線

.mupscrollborder 這個和mdownscrollborder相反,當我們大于這個高度的時候,draggridview自動向上滾動,如上圖的6号線

了解了這六個距離,我們就來看看建立item鏡像的方法裡面,其他的我不多說,首先設定format為pixelformat.translucent,表示除了我們顯示圖檔和文字的其他地方為透明,之後就是x,y這兩個距離的計算,計算的是item的左上角的坐标,了解了上面這六個距離我們很容易得出x,y的坐标,可是你會發現y的坐标減去了狀态欄的高度,這點大家需要注意下,另外我們需要擷取item的繪制緩存的bitmap對象,然後将bitmap設定到一個imageview上面,為什麼要這麼做呢?如果調用addview()方法将item

直接添加到windowmanager裡面,會有異常産生,因為item已經有了自己歸屬的父容器draggridview,所有我們這裡使用一個imageview來代替item添加到windowmanager裡面

上面已經完成了開始拖拽的準備工作,要想拖動鏡像我們還需要重寫ontouchevent()方法,擷取移動的x,y的坐标,利用windowmanager的updateviewlayout方法就能對鏡像進行拖動,拖動的鏡像的時候為了有更好的使用者體驗,我們還要做item的實時交換效果,我們利用手指移動的x,y坐标,利用pointtoposition()來擷取拖拽到的position,然後将之前的item顯示出來,将拖拽到的item進行隐藏,這樣子就完成了item在界面上面的交換,但是資料交換我這裡沒有做,是以我提供了回調接口onchanagelistener,我們隻需要自己實作資料的交換邏輯然後重新整理draggridview即可,我們還需要實作draggridview的自動向上滾動或者向下滾動,使用handler和mscrollrunnable利用smoothscrolltopositionfromtop()來實作draggridview滾動,具體的實作大家可以看代碼

手指離開界面,将item的鏡像移除,并将拖拽到的item顯示出來,這樣子就實作了girdview的拖拽效果啦,接下來我們來使用下我們自定義可拖拽的gridview吧,先看主界面布局,隻有我們自定義的一個draggridview

[html] view

Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換
Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"  

    xmlns:tools="http://schemas.android.com/tools"  

    android:layout_width="match_parent"  

    android:layout_height="match_parent" >  

    <com.example.draggridview.draggridview  

        android:id="@+id/draggridview"  

        android:listselector="@android:color/transparent"  

        android:layout_width="match_parent"  

        android:layout_height="match_parent"  

        android:cachecolorhint="@android:color/transparent"  

        android:verticalspacing="10dip"  

        android:horizontalspacing="10dip"  

        android:stretchmode="columnwidth"    

        android:gravity="center"   

        android:numcolumns="3" >  

    </com.example.draggridview.draggridview>  

</relativelayout>  

接下來我們看看draggridview的item的布局,上面一個imageview下面一個textview

Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換
Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換

<?xml version="1.0" encoding="utf-8"?>  

    android:layout_width="fill_parent"  

    android:layout_height="wrap_content"  

    android:background="@android:color/transparent" >  

    <imageview  

        android:id="@+id/item_image"  

        android:scaletype="centercrop"  

        android:layout_width="wrap_content"  

        android:layout_height="wrap_content"  

        android:layout_centerhorizontal="true" >  

    </imageview>  

    <textview  

        android:id="@+id/item_text"  

        android:layout_below="@+id/item_image"  

    </textview>  

布局搞定了我們就來看看首頁面mainactivity的代碼吧

Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換
Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換

import java.util.arraylist;  

import java.util.collections;  

import java.util.hashmap;  

import java.util.list;  

import android.os.bundle;  

import android.widget.simpleadapter;  

import com.example.draggridview.draggridview.onchanagelistener;  

public class mainactivity extends activity {  

    private list<hashmap<string, object>> datasourcelist = new arraylist<hashmap<string, object>>();  

    protected void oncreate(bundle savedinstancestate) {  

        super.oncreate(savedinstancestate);  

        setcontentview(r.layout.activity_main);  

        draggridview mdraggridview = (draggridview) findviewbyid(r.id.draggridview);  

        for (int i = 0; i < 30; i++) {  

            hashmap<string, object> itemhashmap = new hashmap<string, object>();  

            itemhashmap.put("item_image",r.drawable.com_tencent_open_notice_msg_icon_big);  

            itemhashmap.put("item_text", "拖拽 " + integer.tostring(i));  

            datasourcelist.add(itemhashmap);  

        final simpleadapter msimpleadapter = new simpleadapter(this, datasourcelist,  

                r.layout.grid_item, new string[] { "item_image", "item_text" },  

                new int[] { r.id.item_image, r.id.item_text });  

        mdraggridview.setadapter(msimpleadapter);  

        mdraggridview.setonchangelistener(new onchanagelistener() {  

            @override  

            public void onchange(int from, int to) {  

                hashmap<string, object> temp = datasourcelist.get(from);  

                //直接互動item  

//              datasourcelist.set(from, datasourcelist.get(to));  

//              datasourcelist.set(to, temp);  

                //這裡的處理需要注意下  

                if(from < to){  

                    for(int i=from; i<to; i++){  

                        collections.swap(datasourcelist, i, i+1);  

                    }  

                }else if(from > to){  

                    for(int i=from; i>to; i--){  

                        collections.swap(datasourcelist, i, i-1);  

                }  

                datasourcelist.set(to, temp);  

                msimpleadapter.notifydatasetchanged();  

        });  

這裡面的代碼還是比較簡單,主要講下onchange()方法,我們要為mdraggridview設定一個onchanagelistener的回調接口,在onchange()方法裡面實作資料的交換邏輯,第一個參數from為item開始的位置,第二個參數to為item拖拽到的位置,剛開始我使用的交換邏輯是

Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換
Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換

hashmap<string, object> temp = datasourcelist.get(from);  

直接交換的item的資料,然後看了下網易新聞的拖拽的gridview,他不是直接實作兩個item直接的資料交換,是以将資料交換邏輯改成了下面的方式

簡單說下,資料的交換邏輯,比如我們将position從5拖拽到7這個位置,我注釋掉的邏輯是直接将5和7的資料交換,而後面的那種邏輯是将6的位置資料移動到5,将7的位置移動到6,然後再7顯示5  6->5, 7->6, 5->7不知道大家了解了沒有。

接下來我們來運作下項目,在運作之前我們不要忘了在androidmanifest.xml裡面加入震動的權限<uses-permission android:name="android.permission.vibrate"/>

Android 可拖拽的GridView效果實作, 長按可拖拽和item實時交換

好了,今天的講解就到此結束,效果還不錯吧,看完這篇文章你是不是覺得gridview拖拽也不是那麼難實作呢?你心裡是不是也大概有自己的一個思路,建議大家自己敲敲看看,可以自己去實作下listview的拖拽實作,listview比gridview簡單些,好的學習方法不是看得懂人家的代碼,而是看完代碼自己根據腦海裡的思路自己敲出來,是以還是鼓勵大家多敲代碼,不明白的同學在下面留言,我會為大家解答的!

項目源碼,點選下載下傳

ps:上面的代碼在4.0以上的機器上面運作是ok的,但是在4.0以下的機器存在幾個問題,首先是相容性的問題,首先smoothscrolltopositionfromtop()方法在2.x的機器是不存在的,但是我們可以使用smoothscrollby()來代替上面的方法使得gridview滾動

注意:很多朋友說運作在2.3的機器上面拖動的時候出現某些item無緣無故的隐藏了,筆者在寫demo的時候一直用的是4.0的真機運作的,後面部落客使用模拟器運作在2.3的機器上面,确實存在很多朋友反應的問題,原因就是因為部落客使用的是simpleadapter,simpleadapter會複用item,是以才導緻本不該隐藏的item隐藏了,但是為什麼運作在部落客4.0的機器上面不出現問題,部落客也很納悶,現在我對其做出了修改,采用自定義adapter,對item不采用複用的原則,雖然效率上面有點點不足,但是如果對于item不多的gridview,效率不足可以忽略,新修改的代碼可以運作在2.x以上的機器不出現朋友們所說的問題了,非常感謝大家提出的問題!

修改版源碼,點選下載下傳

再次聲明, 在修改版的源碼中還存在一點小bug,不過已解決,正如28樓所說的一樣,是因為我在mainactivity的onchange()方法中調用了mdragadapter.setitemhide(to)方法,主要是為了實作拖動到新的位置隐藏該item, 使得mhideposition不為-1,忘記在停止拖動onstopdrag()方法中将mhideposition設定為-1了,是以為了解決28樓所說的問題,隻需要在onstopdrag()方法添加一句 ((dragadapter)this.getadapter()).setitemhide(-1)就行了

繼續閱讀