Android中Drag and Drop拖拽功能的使用1-----基本實現
阿新 • • 發佈:2019-01-02
Android中的拖拽功能是有自帶的api的;(很多時候會誤以為要自定義控制元件,所以我放到了,自定義目錄下)
參考文件:
http://www.android-doc.com/guide/topics/ui/drag-drop.html
我寫了一個例子分析:
效果圖:
思路:
1主要用到了View的startDrag(startDragAndDrop API24+) 方法
2拖拽的監聽OnDragListener方法
具體實現:
第一步:通過一個長按事件啟動拖拽:
imageView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { Intent intent = new Intent(); ClipData clipData = ClipData.newIntent("label", intent); View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v); v.startDrag(null, shadowBuilder, imageView, 0); //震動反饋 v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); return true; } });
第二步:OnDragListener監聽拖拽
linearLayout.setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View v, DragEvent event) { //v 永遠是設定該監聽的view,這裡即fl_blue String simpleName = v.getClass().getSimpleName(); // Log.w(BLUE, "view name:" + simpleName); //獲取事件 int action = event.getAction(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: Log.i("111", "開始拖拽"); imageView.setVisibility(View.INVISIBLE); break; case DragEvent.ACTION_DRAG_ENDED: Log.i("111", "結束拖拽"); imageView.setVisibility(View.VISIBLE); break; case DragEvent.ACTION_DRAG_ENTERED: Log.i("111", "拖拽的view進入監聽的view時"); break; case DragEvent.ACTION_DRAG_EXITED: Log.i("111", "拖拽的view離開監聽的view時"); break; case DragEvent.ACTION_DRAG_LOCATION: float x = event.getX(); float y = event.getY(); long l = SystemClock.currentThreadTimeMillis(); Log.i("111", "拖拽的view在BLUE中的位置:x =" + x + ",y=" + y); break; case DragEvent.ACTION_DROP: Log.i("111", "釋放拖拽的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); linearLayout.addView(localState, layoutParams); imageView.setX(event.getX() - imageView.getWidth() / 2); imageView.setY(event.getY() - imageView.getHeight() / 2); break; } //是否響應拖拽事件,true響應,返回false只能接受到ACTION_DRAG_STARTED事件,後續事件不會收到 return true; } });
ok講完了,就可以實現上面的效果了;
下面貼出完整程式碼:
MainActivity中:
package com.zhh.android; import android.app.Activity; import android.content.ClipData; import android.content.Intent; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import android.view.DragEvent; import android.view.HapticFeedbackConstants; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; public class MainActivity extends Activity { private ImageView imageView; private LinearLayout linearLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ImageView)findViewById(R.id.imageView); linearLayout = (LinearLayout)findViewById(R.id.linearLayout); imageView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { Intent intent = new Intent(); ClipData clipData = ClipData.newIntent("label", intent); View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v); v.startDrag(null, shadowBuilder, imageView, 0); //震動反饋 v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); return true; } }); linearLayout.setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View v, DragEvent event) { //v 永遠是設定該監聽的view,這裡即fl_blue String simpleName = v.getClass().getSimpleName(); // Log.w(BLUE, "view name:" + simpleName); //獲取事件 int action = event.getAction(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: Log.i("111", "開始拖拽"); imageView.setVisibility(View.INVISIBLE); break; case DragEvent.ACTION_DRAG_ENDED: Log.i("111", "結束拖拽"); imageView.setVisibility(View.VISIBLE); break; case DragEvent.ACTION_DRAG_ENTERED: Log.i("111", "拖拽的view進入監聽的view時"); break; case DragEvent.ACTION_DRAG_EXITED: Log.i("111", "拖拽的view離開監聽的view時"); break; case DragEvent.ACTION_DRAG_LOCATION: float x = event.getX(); float y = event.getY(); long l = SystemClock.currentThreadTimeMillis(); Log.i("111", "拖拽的view在BLUE中的位置:x =" + x + ",y=" + y); break; case DragEvent.ACTION_DROP: Log.i("111", "釋放拖拽的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); linearLayout.addView(localState, layoutParams); imageView.setX(event.getX() - imageView.getWidth() / 2); imageView.setY(event.getY() - imageView.getHeight() / 2); break; } //是否響應拖拽事件,true響應,返回false只能接受到ACTION_DRAG_STARTED事件,後續事件不會收到 return true; } }); } }
佈局檔案:activity_main中
<LinearLayout 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"
tools:context=".MainActivity"
android:orientation="vertical"
android:background="#4043f1"
>
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
</LinearLayout>
</LinearLayout>
參考文章:
https://blog.csdn.net/Hubert_bing/article/details/79499654
原始碼下載:
https://download.csdn.net/download/zhaihaohao1/10890390