




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、可拖拽gridview根據(jù)手指按下的X,Y坐標(biāo)來獲取我們在GridView上面點擊的item手指按下的時候使用Handler和Runnable來實現(xiàn)一個定時器,假如定時時間為1000毫秒,在1000毫秒內(nèi),如果手指抬起了移除定時器,沒有抬起并且手指點擊在GridView的item所在的區(qū)域,則表示我們長按了GridView的item如果我們長按了item則隱藏item,然后使用WindowManager來添加一個item的鏡像在屏幕用來代替剛剛隱藏的item當(dāng)我們手指在屏幕移動的時候,更新item鏡像的位置,然后在根據(jù)我們移動的X,Y的坐標(biāo)來獲取移動到GridView的哪一個位置到GridVi
2、ew的item過多的時候,可能一屏幕顯示不完,我們手指拖動item鏡像到屏幕下方,要觸發(fā)GridView想上滾動,同理,當(dāng)我們手指拖動item鏡像到屏幕上面,觸發(fā)GridView向下滾動GridView交換數(shù)據(jù),刷新界面,移除item的鏡像看完上面的這些思路你是不是找到了些感覺了呢,心里癢癢的想動手試試吧,好吧,接下來就帶大家根據(jù)思路來實現(xiàn)可拖拽的GridView,新建一個項目就叫DragGridView新建一個類DragGridView繼承GridView,先來看看DragGridView的代碼,然后在根據(jù)代碼進(jìn)行相關(guān)的講解java view plaincopy在CODE上查看代碼片派生到我
3、的代碼片package com.example.draggridview; 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.util.AttributeSet; import androi
4、d.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 * * author xiaanming * */ public class DragGridView extends GridView /* * DragGr
5、idView的item長按響應(yīng)的時間, 默認(rèn)是1000毫秒,也可以自行設(shè)置 */ private long dragResponseMS = 1000; /* * 是否可以拖拽,默認(rèn)不可以 */ private boolean isDrag = false; private int mDownX; private int mDownY; private int moveX; private int moveY; /* * 正在拖拽的position */ private int mDragPosition; /* * 剛開始拖拽的item對應(yīng)的View */ private View mSta
6、rtDragItemView = null; /* * 用于拖拽的鏡像,這里直接用一個ImageView */ private ImageView mDragImageView; /* * 震動器 */ private Vibrator mVibrator; private WindowManager mWindowManager; /* * item鏡像的布局參數(shù) */ private WindowManager.LayoutParams mWindowLayoutParams; /* * 我們拖拽的item對應(yīng)的Bitmap */ private Bitmap mDragBitmap; /
7、* * 按下的點到所在item的上邊緣的距離 */ private int mPoint2ItemTop ; /* * 按下的點到所在item的左邊緣的距離 */ private int mPoint2ItemLeft; /* * DragGridView距離屏幕頂部的偏移量 */ private int mOffset2Top; /* * DragGridView距離屏幕左邊的偏移量 */ private int mOffset2Left; /* * 狀態(tài)欄的高度 */ private int mStatusHeight; /* * DragGridView自動向下滾動的邊界值 */ pri
8、vate int mDownScrollBorder; /* * DragGridView自動向上滾動的邊界值 */ private int mUpScrollBorder; /* * DragGridView自動滾動的速度 */ private static final int speed = 20; /* * item發(fā)生變化回調(diào)的接口 */ private OnChanageListener onChanageListener; public DragGridView(Context context) this(context, null); public DragGridView(Co
9、ntext 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(Con
10、text.WINDOW_SERVICE); mStatusHeight = getStatusHeight(context); /獲取狀態(tài)欄的高度 private Handler mHandler = new Handler(); /用來處理是否為長按的Runnable private Runnable mLongClickRunnable = new Runnable() Override public void run() isDrag = true; /設(shè)置可以拖拽 mVibrator.vibrate(50); /震動一下 mStartDragItemView.setVisibility
11、(View.INVISIBLE);/隱藏該item /根據(jù)我們按下的點顯示item鏡像 createDragImage(mDragBitmap, mDownX, mDownY); ; /* * 設(shè)置回調(diào)接口 * param onChanageListener */ public void setOnChangeListener(OnChanageListener onChanageListener) this.onChanageListener = onChanageListener; /* * 設(shè)置響應(yīng)拖拽的毫秒數(shù),默認(rèn)是1000毫秒 * param dragResponseMS */ pu
12、blic void setDragResponseMS(long dragResponseMS) this.dragResponseMS = dragResponseMS; Override public boolean dispatchTouchEvent(MotionEvent ev) switch(ev.getAction() case MotionEvent.ACTION_DOWN: mDownX = (int) ev.getX(); mDownY = (int) ev.getY(); /根據(jù)按下的X,Y坐標(biāo)獲取所點擊item的position mDragPosition = poin
13、tToPosition(mDownX, mDownY); if(mDragPosition = AdapterView.INVALID_POSITION) return super.dispatchTouchEvent(ev); /使用Handler延遲dragResponseMS執(zhí)行mLongClickRunnable mHandler.postDelayed(mLongClickRunnable, dragResponseMS); /根據(jù)position獲取該item所對應(yīng)的View mStartDragItemView = getChildAt(mDragPosition - getFi
14、rstVisiblePosition(); /下面這幾個距離大家可以參考我的博客上面的圖來理解下 mPoint2ItemTop = mDownY - mStartDragItemView.getTop(); mPoint2ItemLeft = mDownX - mStartDragItemView.getLeft(); mOffset2Top = (int) (ev.getRawY() - mDownY); mOffset2Left = (int) (ev.getRawX() - mDownX); /獲取DragGridView自動向上滾動的偏移量,小于這個值,DragGridView向下滾動
15、 mDownScrollBorder = getHeight() /4; /獲取DragGridView自動向下滾動的偏移量,大于這個值,DragGridView向上滾動 mUpScrollBorder = getHeight() * 3/4; /開啟mDragItemView繪圖緩存 mStartDragItemView.setDrawingCacheEnabled(true); /獲取mDragItemView在緩存中的Bitmap對象 mDragBitmap = Bitmap.createBitmap(mStartDragItemView.getDrawingCache(); /這一步很
16、關(guān)鍵,釋放繪圖緩存,避免出現(xiàn)重復(fù)的鏡像 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);
17、break; case MotionEvent.ACTION_UP: mHandler.removeCallbacks(mLongClickRunnable); mHandler.removeCallbacks(mScrollRunnable); break; return super.dispatchTouchEvent(ev); /* * 是否點擊在GridView的item上面 * param itemView * param x * param y * return */ private boolean isTouchInItem(View dragView, int x, int y
18、) if(dragView = null) return false; int leftOffset = dragView.getLeft(); int topOffset = dragView.getTop(); if(x leftOffset + dragView.getWidth() return false; if(y topOffset + dragView.getHeight() return false; return true; Override public boolean onTouchEvent(MotionEvent ev) if(isDrag & mDragImage
19、View != 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; break; return true; return super.onTouchEvent(ev); /* * 創(chuàng)建拖動的鏡像 * param bitmap * para
20、m downX * 按下的點相對父控件的X坐標(biāo) * param downY * 按下的點相對父控件的X坐標(biāo) */ private void createDragImage(Bitmap bitmap, int downX , int downY) mWindowLayoutParams = new WindowManager.LayoutParams(); mWindowLayoutParams.format = PixelFormat.TRANSLUCENT; /圖片之外的其他地方透明 mWindowLayoutParams.gravity = Gravity.TOP | Gravity.L
21、EFT; mWindowLayoutParams.x = downX - mPoint2ItemLeft + mOffset2Left; mWindowLayoutParams.y = downY - mPoint2ItemTop + mOffset2Top - mStatusHeight; mWindowLayoutParams.alpha = 0.55f; /透明度 mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mWindowLayoutParams.height = WindowManager.L
22、ayoutParams.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); /* *
23、從界面上面移動拖動鏡像 */ private void removeDragImage() if(mDragImageView != null) mWindowManager.removeView(mDragImageView); mDragImageView = null; /* * 拖動item,在里面實現(xiàn)了item鏡像的位置更新,item的相互交換以及GridView的自行滾動 * param x * param y */ private void onDragItem(int moveX, int moveY) mWindowLayoutParams.x = moveX - mPoin
24、t2ItemLeft + mOffset2Left; mWindowLayoutParams.y = moveY - mPoint2ItemTop + mOffset2Top - mStatusHeight; mWindowManager.updateViewLayout(mDragImageView, mWindowLayoutParams); /更新鏡像的位置 onSwapItem(moveX, moveY); /GridView自動滾動 mHandler.post(mScrollRunnable); /* * 當(dāng)moveY的值大于向上滾動的邊界值,觸發(fā)GridView自動向上滾動 * 當(dāng)
25、moveY的值小于向下滾動的邊界值,觸犯GridView自動向下滾動 * 否則不進(jìn)行滾動 */ private Runnable mScrollRunnable = new Runnable() Override public void run() int scrollY; if(moveY mUpScrollBorder) scrollY = speed; mHandler.postDelayed(mScrollRunnable, 25); else if(moveY mDownScrollBorder) scrollY = -speed; mHandler.postDelayed(mScr
26、ollRunnable, 25); else scrollY = 0; mHandler.removeCallbacks(mScrollRunnable); /當(dāng)我們的手指到達(dá)GridView向上或者向下滾動的偏移量的時候,可能我們手指沒有移動,但是DragGridView在自動的滾動 /所以我們在這里調(diào)用下onSwapItem()方法來交換item onSwapItem(moveX, moveY); smoothScrollBy(scrollY, 10); ; /* * 交換item,并且控制item之間的顯示與隱藏效果 * param moveX * param moveY */ priv
27、ate void onSwapItem(int moveX, int moveY) /獲取我們手指移動到的那個item的position int tempPosition = pointToPosition(moveX, moveY); /假如tempPosition 改變了并且tempPosition不等于-1,則進(jìn)行交換 if(tempPosition != mDragPosition & tempPosition != AdapterView.INVALID_POSITION) if(onChanageListener != null) onChanageListener.onChang
28、e(mDragPosition, tempPosition); getChildAt(tempPosition - getFirstVisiblePosition().setVisibility(View.INVISIBLE);/拖動到了新的item,新的item隱藏掉 getChildAt(mDragPosition - getFirstVisiblePosition().setVisibility(View.VISIBLE);/之前的item顯示出來 mDragPosition = tempPosition; /* * 停止拖拽我們將之前隱藏的item顯示出來,并將鏡像移除 */ priv
29、ate id onStopDrag() View view = getChildAt(mDragPosition - getFirstVisiblePosition(); if(view != null) view.setVisibility(View.VISIBLE); (DragAdapter)this.getAdapter().setItemHide(-1); removeDragImage(); /* * 獲取狀態(tài)欄的高度 * param context * return */ private static int getStatusHeight(Context context) in
30、t statusHeight = 0; Rect localRect = new Rect(); (Activity) context).getWindow().getDecorView().getWindowVisibleDisplayFrame(localRect); statusHeight = localRect.top; if (0 = statusHeight) Class localClass; try localClass = Class.forName(ernal.R$dimen); Object localObject = localClass
31、.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
32、 /* * 當(dāng)item交換位置的時候回調(diào)的方法,我們只需要在該方法中實現(xiàn)數(shù)據(jù)的交換即可 * param form * 開始的position * param to * 拖拽到的position */ public void onChange(int form, int to); 首先看DragGridView的事件分發(fā)方法,不了解Android事件分發(fā)的可以先去了解下,Android事件分發(fā)對于自定義控件很重要,簡單說下,當(dāng)我們點擊DragGridView的Item,先會去執(zhí)行dispatchTouchEvent()方法將事件分發(fā)下去,所以我們要重寫dispatchTouchEvent()方法
33、在手指按下的時候根據(jù)pointToPosition()方法來獲取我們按下的item的position,根據(jù)getChildAt()方法來獲取該position上面所對應(yīng)的View, 并且開啟長按的定時器,默認(rèn)時間為1000毫秒,如果在1000毫秒內(nèi)手指抬起或者手指在屏幕上滑動出了該item,則取消長按定時器,否則就表示可以進(jìn)行拖拽,手機(jī)友好的震動一下,隱藏我們長按的Item,屏幕調(diào)用createDragImage()方法來創(chuàng)建我們長按的item的鏡像,創(chuàng)建Item的鏡像使用的是WindowManager類,該類可以創(chuàng)建一個窗體顯示在Activity之上,再此之前大家先要理解這幾個距離,理解這幾
34、個距離之前要首先知道getRawX(),getRawY()和getX(),getY()的區(qū)別,getRawX(),getRawY()是相對于屏幕的原點的距離,而getX(),getY()是相對于控件左上方的點的距離,為了方便大家理解我用Word簡單的畫了下圖,畫得不好,大家將就的看下,紅色框框為我們的GridViewmPoint2ItemTop 手指按下的點到該Item的上邊緣的距離,如上圖的1號線mPoint2ItemLeft 手指按下的點到該Item的左邊緣的距離,如上圖的2號線mOffset2Top DragGridView的上邊緣到屏幕上邊緣的距離,如上圖的3號線,這個距離包裹狀態(tài)欄,
35、標(biāo)題欄,或者一些在DragGridView上面的布局的高度,這個很重要我們現(xiàn)實Item鏡像需要用到mOffset2Left DragGridView的左邊緣到屏幕左邊緣的距離,如上圖的4號線,我這個Demo的這個距離為0,因為我設(shè)置DragGridView的寬度為充滿屏幕,但是我們要考慮假如DragGridView與屏幕左邊緣設(shè)置了間隙或者左邊有其他的布局的情形mDownScrollBorder 這個距離表示當(dāng)DragGridView的item過多的時候,手機(jī)一屏顯示不完全,我們拖動Item鏡像到這個高度的時候,DragGridView自動向下滾動,如上圖的5號線.mUpScrollBorde
36、r 這個和mDownScrollBorder相反,當(dāng)我們大于這個高度的時候,DragGridView自動向上滾動,如上圖的6號線理解了這六個距離,我們就來看看創(chuàng)建Item鏡像的方法里面,其他的我不多說,首先設(shè)置format為PixelFormat.TRANSLUCENT,表示除了我們顯示圖片和文字的其他地方為透明,之后就是x,y這兩個距離的計算,計算的是item的左上角的坐標(biāo),理解了上面這六個距離我們很容易得出x,y的坐標(biāo),可是你會發(fā)現(xiàn)y的坐標(biāo)減去了狀態(tài)欄的高度,這點大家需要注意下,另外我們需要獲取item的繪制緩存的Bitmap對象,然后將Bitmap設(shè)置到一個ImageView上面,為什么
37、要這么做呢?如果調(diào)用addView()方法將item 直接添加到WindowManager里面,會有異常產(chǎn)生,因為item已經(jīng)有了自己歸屬的父容器DragGridView,所有我們這里使用一個ImageView來代替item添加到WindowManager里面上面已經(jīng)完成了開始拖拽的準(zhǔn)備工作,要想拖動鏡像我們還需要重寫onTouchEvent()方法,獲取移動的X,Y的坐標(biāo),利用WindowManager的updateViewLayout方法就能對鏡像進(jìn)行拖動,拖動的鏡像的時候為了有更好的用戶體驗,我們還要做item的實時交換效果,我們利用手指移動的X,Y坐標(biāo),利用pointToPositio
38、n()來獲取拖拽到的position,然后將之前的item顯示出來,將拖拽到的item進(jìn)行隱藏,這樣子就完成了item在界面上面的交換,但是數(shù)據(jù)交換我這里沒有做,所以我提供了回調(diào)接口OnChanageListener,我們只需要自己實現(xiàn)數(shù)據(jù)的交換邏輯然后刷新DragGridView即可,我們還需要實現(xiàn)DragGridView的自動向上滾動或者向下滾動,使用Handler和mScrollRunnable利用smoothScrollToPositionFromTop()來實現(xiàn)DragGridView滾動,具體的實現(xiàn)大家可以看代碼手指離開界面,將item的鏡像移除,并將拖拽到的item顯示出來,這樣
39、子就實現(xiàn)了GirdView的拖拽效果啦,接下來我們來使用下我們自定義可拖拽的GridView吧,先看主界面布局,只有我們自定義的一個DragGridViewhtml view plaincopy在CODE上查看代碼片派生到我的代碼片android:layout_width=match_parent android:layout_height=match_parent 接下來我們看看DragGridView的item的布局,上面一個ImageView下面一個TextViewhtml view plaincopy在CODE上查看代碼片派生到我的代碼片 android:layout_width=fill_parent android:layout_height=wrap_content android:background=android:color/transparent 布局搞定了我們就來看看主頁面MainActivity的代碼吧java view plaincopy在CODE上查看代碼片派生到我的代碼片package com.example.draggridview; import java.util.ArrayList; impor
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 重癥醫(yī)學(xué)科護(hù)理發(fā)展現(xiàn)狀
- 腫瘤專科進(jìn)修護(hù)理實踐匯報
- ERAS神外護(hù)理講課
- 沙眼衣原體肺炎診療與防治策略
- 脊髓型頸椎病中醫(yī)護(hù)理
- 動物牙科知識培訓(xùn)課件
- 計量管理考試題及答案
- 《趣味小品》課件
- 積極應(yīng)對急診情況:急救技巧與流程
- 宿舍舍長培訓(xùn)
- 辦公軟件實操試題及詳細(xì)答案
- 米粉項目可行性分析報告
- 腰痛中醫(yī)護(hù)理查房
- 八五普法自查自評情況報告
- 競彩資格考試試題及答案
- esg考試試題及答案
- 重慶市大足區(qū)2023-2024學(xué)年四年級下學(xué)期語文期末考試試卷(含答案)
- 2025三季度四川經(jīng)準(zhǔn)檢驗檢測集團(tuán)股份限公司招聘48人易考易錯模擬試題(共500題)試卷后附參考答案
- 百貨店轉(zhuǎn)讓合同協(xié)議
- 軸承加工合同協(xié)議
- 高爾夫俱樂部績效考核手冊
評論
0/150
提交評論