日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android拖拽详解

發布時間:2025/7/25 Android 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android拖拽详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android中實現拖拽其實很簡單,系統早已經提供了api讓我使用,主要用到了View的startDrag(startDragAndDrop API24+) 方法以及OnDragListener。

startDrag

先來看下方法介紹:

/*** Starts a drag and drop operation. When your application calls this method, it passes a* {@link android.view.View.DragShadowBuilder} object to the system. The* system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}* to get metrics for the drag shadow, and then calls the object's* {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.* <p>* Once the system has the drag shadow, it begins the drag and drop operation by sending* drag events to all the View objects in your application that are currently visible. It does* this either by calling the View object's drag listener (an implementation of* {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the* View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.* Both are passed a {@link android.view.DragEvent} object that has a* {@link android.view.DragEvent#getAction()} value of* {@link android.view.DragEvent#ACTION_DRAG_STARTED}.* </p>* <p>* Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,* int) startDragAndDrop()} on any attached View object. The View object does not need to be* the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related* to the View the user selected for dragging.* </p>* @param data A {@link android.content.ClipData} object pointing to the data to be* transferred by the drag and drop operation.* @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the* drag shadow.* @param myLocalState An {@link java.lang.Object} containing local data about the drag and* drop operation. When dispatching drag events to views in the same activity this object* will be available through {@link android.view.DragEvent#getLocalState()}. Views in other* activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}* will return null).* <p>* myLocalState is a lightweight mechanism for the sending information from the dragged View* to the target Views. For example, it can contain flags that differentiate between a* a copy operation and a move operation.* </p>* @param flags Flags that control the drag and drop operation. This can be set to 0 for no* flags, or any combination of the following:* <ul>* <li>{@link #DRAG_FLAG_GLOBAL}</li>* <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>* <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>* <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>* <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>* <li>{@link #DRAG_FLAG_OPAQUE}</li>* </ul>* @return {@code true} if the method completes successfully, or* {@code false} if it fails anywhere. Returning {@code false} means the system was unable to* do a drag, and so no drag operation is in progress.*/public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,Object myLocalState, int flags) 復制代碼

看到英文就頭大?沒事,我來翻譯解釋一下。

啟動拖放操作。當應用程序調用此方法時,它將傳遞一個DragShadowBuilder對象到系統。系統調用此對象的onProvideShadowMetrics(Point, Point)方法獲取拖動陰影的參數指標,然后調用onDrawShadow(Canvas)來繪制陰影。一旦系統有了拖動陰影,它就開始拖拽操作,通過將拖拽事件發送到當前可見的應用程序中的所有視圖對象。這些視圖可以通過設置OnDragListener在或者實現onDragEvent方法接受DragEvent(事件)來響應和拖拽事件。

可以看到有四個參數:

ClipData data

其實就是一個封裝數據的對象,通過拖放操作傳遞給接受者。該對象可以存放一個Item的集合,Item可以存放如下數據:

public static class Item {final CharSequence mText;final String mHtmlText;final Intent mIntent;Uri mUri; } 復制代碼

注意到可以存放Intent,因此,通常可以將參數存入intent,然后通過靜態方法直接創建ClipData對象:

ClipData clipData = ClipData.newIntent("label", intent); 復制代碼

該數據可以在監聽的中的DragEvent獲取

ClipData clipData = event.getClipData(); 復制代碼

簡單點說就是可以將一些數據傳遞給拖拽的接受者,該拖拽其實可以跨Activity的,如果只是同一個Activity可以使用第三個參數傳遞數據。

DragShadowBuilder shadowBuilder

用于創建拖拽view是的陰影,也就是跟隨手指移動的視圖,通常直接使用默認即可生成與一個原始view相同,帶有透明度的陰影:

View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v); 復制代碼

Object myLocalState

當你的拖拽行為是在同一個Activity中進行時可以傳遞一個任意對象,在監聽中可以通過{@link android.view.DragEvent#getLocalState()}獲得。如果是跨Activity拖拽中無法訪問此數據,getLocalState()將返回null。

int flags

控制拖放操作的標志。因為沒有標志可以設置為0,flag標志拖動是否可以跨越窗口以及一些訪問權限(需要API24+)。

了解了方法參數含義,接下來就是啟用拖拽了,通常會通過長按來觸發拖拽:

iv.setOnLongClickListener(new View.OnLongClickListener() {@Overridepublic boolean onLongClick(View v) {View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);v.startDrag(null, shadowBuilder, null, 0);//震動反饋v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);return true;}}); 復制代碼

開始拖拽后還要有來接受這些拖拽事件,這就需要OnDragListener了。

OnDragListener

OnDragListener是在View中定義的接口,用于響應拖拽事件,可以通過View的setOnDragListener 方法設置監聽,有點類似于點擊事件。

public interface OnDragListener { boolean onDrag(View v, DragEvent event); } 復制代碼

設置監聽,實現onDrag(View v, DragEvent event)方法,其中View是設置該監聽的view,DragEvent是拖拽事件,可以通過event.getAction() 獲取具體事件類型,這和TouchEvent非常類似,具體事件類型有如下幾種:

fl_blue.setOnDragListener(new View.OnDragListener() {@Overridepublic boolean onDrag(View v, DragEvent event) {//v 永遠是設置該監聽的view,這里即fl_blueString simpleName = v.getClass().getSimpleName();Log.w(BLUE, "view name:" + simpleName);//獲取事件int action = event.getAction();switch (action) {case DragEvent.ACTION_DRAG_STARTED:Log.i(BLUE, "開始拖拽");break;case DragEvent.ACTION_DRAG_ENDED:Log.i(BLUE, "結束拖拽");break;case DragEvent.ACTION_DRAG_ENTERED:Log.i(BLUE, "拖拽的view進入監聽的view時");break;case DragEvent.ACTION_DRAG_EXITED:Log.i(BLUE, "拖拽的view離開監聽的view時");break;case DragEvent.ACTION_DRAG_LOCATION:float x = event.getX();float y = event.getY();long l = SystemClock.currentThreadTimeMillis();Log.i(BLUE, "拖拽的view在監聽view中的位置:x =" + x + ",y=" + y);break;case DragEvent.ACTION_DROP:Log.i(BLUE, "釋放拖拽的view");break;}//是否響應拖拽事件,true響應,返回false只能接受到ACTION_DRAG_STARTED事件,后續事件不會收到return true;}}); 復制代碼

此處通過event.getX(); event.getY(); 獲取的x,y是手指(也即是被拖拽view的中心點)在監聽view的位置。

釋放手指會觸發ACTION_DRAG_ENDED 事件,如果此時被拖拽的view正好在監聽的view中,則會先觸發ACTION_DROP 事件。

可以同時有多個view設置拖拽監聽接受事件,我給紅色和藍色view都設置了OnDragListener,然后拖動Android圖片到藍色區域后釋放,可以看到日志如下:

03-09 14:53:54.518 12937-12937/com.huburt.app.androiddrag I/RED: 開始拖拽 03-09 14:53:54.518 12937-12937/com.huburt.app.androiddrag I/BLUE: 開始拖拽 03-09 14:53:55.689 12937-12937/com.huburt.app.androiddrag I/BLUE: 拖拽的view進入監聽的view時 03-09 14:53:55.689 12937-12937/com.huburt.app.androiddrag I/BLUE: 拖拽的view在BLUE中的位置:x =111.0,y=2.0 03-09 14:53:55.870 12937-12937/com.huburt.app.androiddrag I/BLUE: 拖拽的view在BLUE中的位置:x =112.0,y=23.0 03-09 14:53:56.014 12937-12937/com.huburt.app.androiddrag I/BLUE: 釋放拖拽的view 03-09 14:53:56.017 12937-12937/com.huburt.app.androiddrag I/RED: 結束拖拽 03-09 14:53:56.017 12937-12937/com.huburt.app.androiddrag I/BLUE: 結束拖拽 復制代碼

現在我們已經可以把Android圖片拖出來,但是還不能把它放入目標view,其實也挺簡單的,只需要在ACTION_DROP事件做一些處理即可:

case DragEvent.ACTION_DROP:Log.i(BLUE, "釋放拖拽的view");ImageView localState = (ImageView) event.getLocalState();FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);layoutParams.topMargin = (int) event.getY() - localState.getWidth() / 2;layoutParams.leftMargin = (int) event.getX() - localState.getHeight() / 2;((ViewGroup) localState.getParent()).removeView(localState);fl_blue.addView(localState, layoutParams);break; 復制代碼

這里因為是在同一個Activity中,我是將拖拽的view直接傳遞過來了,當然也可以只傳遞圖片,然后在接收的view中重新new一個imageview現實圖片。

運行一下就可以看到view可以拖拽到目標位置了。

可能文字描述不是特別清楚,請看demo

總結

以上是生活随笔為你收集整理的Android拖拽详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 四虎色 | 欧洲一区二区三区 | 蜜桃视频一区二区三区在线观看 | 国产露脸150部国语对白 | 黄网av | 日本不卡123| 午夜影院福利社 | 国产山村乱淫老妇女视频 | 超碰福利在线 | 成人在线播放av | 国产成人免费视频网站 | 日本在线免费观看 | 欧美日韩免费高清 | 国产成a人亚洲精v品在线观看 | 日韩精品在线一区 | 国产资源在线观看 | 极品国产一区 | 天天色天| 色婷婷av一区二区三区四区 | 在线成人日韩 | av色成人| 善良的女朋友在线观看 | 亚洲成肉网| 欧美视频日韩视频 | 精品国产大片大片大片 | 97久久精品人人澡人人爽 | 6080黄色| 丰满人妻一区二区三区精品高清 | 日韩精品欧美 | 成年人在线视频免费观看 | 久操视频在线免费观看 | 欧美体内谢she精2性欧美 | 麻豆精品在线 | av爱爱网站 | 久久精品黄色片 | 亚洲涩视频 | 东北毛片| 精品人妻aV中文字幕乱码色欲 | 毛片一区| 成年人在线视频观看 | 婷婷综合国产 | 成人免费视频网站在线看 | 国产无遮挡免费视频 | 国产理论片在线观看 | 久久久国产亚洲 | 欧美在线一| 美女黄色一级视频 | 婷婷伊人综合中文字幕 | 亚洲日本欧美在线 | 男人的亚洲天堂 | 中国极品少妇xxxx做受 | 一级片免费在线观看 | 最近中文字幕在线中文视频 | 国产在线观看不卡 | 欧美用舌头去添高潮 | 夜夜爽天天爽 | 夜夜嗨aⅴ一区二区三区 | 不卡精品视频 | 啪啪自拍视频 | 干老太太视频 | 97超在线 | 医生强烈淫药h调教小说视频 | 后进极品白嫩翘臀在线视频 | 亚洲精品偷拍 | 手机在线中文字幕 | 亚洲巨乳在线 | 青青草网址 | 激情五月婷婷小说 | 日韩不卡免费视频 | 性视频在线 | 国产av国片偷人妻麻豆 | 在线视频亚洲色图 | 亚洲一区中文字幕在线观看 | 日韩视频在线一区二区 | 亚洲图片综合网 | 91欧美国产 | 日韩影音| 青青青视频在线播放 | 91超碰在线免费观看 | 久久久久久久久久影院 | 亚洲生活片 | 日本www在线观看 | 久久久在线观看 | 中文字幕永久在线观看 | 久久久久久久久久久福利 | 18禁网站免费无遮挡无码中文 | 日日噜噜夜夜狠狠久久波多野 | 久久911 | 免费欧美 | av不卡免费在线 | 精品国产一区二区在线 | 国产精品无码专区 | 中文字幕一区三区 | 欧美在线影院 | 午夜插插| 天天躁日日躁狠狠躁 | 夜夜天堂 | 日韩性插| 成人国产精品一区二区 |