View 可以實現拖拽效果(Drag),根據參考API 文檔,實現也簡單。
(Api 文檔: https://tool.oschina.net/uploads/apidocs/android/guide/topics/ui/drag-drop.html)
以下簡單實現了拖拽效果,在拖拽的過程中,根據拖拽事件 更新ImageView 的背景顏色,方便理解拖拽事件的處理。
但是 ACTION_DROP 沒有執行,需要檢查一下原因。
此外,下一步進行研究 拖拽到指定目標View區域, 考慮能拖拽的範圍等等
package com.example.dragtest;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
// Create a string for the ImageView label
private static final String IMAGEVIEW_TAG = "icon bitmap";
private Context mContext;
// Creates a new ImageView
ImageView mImageView;
Bitmap mIconBitmap;
private View.OnDragListener mDragListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
ConstraintLayout layout = findViewById(R.id.main_layout);
// 動態添加 ImageView, 設置Tag, 拖拽時可以判斷時哪個view
mImageView = new ImageView(this);
mIconBitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
mImageView.setImageBitmap(mIconBitmap);
mImageView.setTag(IMAGEVIEW_TAG);
mImageView.setBackgroundColor(getResources().getColor(R.color.colorAccent));
// 使用ConstraintLayout 方式動態添加ImageView 到佈局中,與Drag 無關,可以直接使用圖片資源代替
int imageViewId = mImageView.generateViewId();
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.connect(imageViewId, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
constraintSet.connect(imageViewId, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP);
constraintSet.applyTo(layout);
layout.addView(mImageView);
//1. 簡單實現拖拽效果
mImageView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
//API 文檔使用 ClipData.MIMETYPE_TEXT_PLAIN, 但是無法使用。(MIMETYPES_TEXT_PLAIN)
String[] textPlain = new String[]{"text/plain"};
//1.1 ClipData 跟剪貼板有關??
ClipData.Item item = new ClipData.Item((CharSequence) v.getTag());
ClipData dragData = new ClipData((CharSequence) v.getTag(), textPlain, item);
//1.2 拖拽動畫效果有默認實現 DragShadowBuilder
//開始執行拖拽
v.startDrag(dragData, new View.DragShadowBuilder(v), null, 0);
return true;
}
});
//2. 自定義拖拽監聽器,響應各種拖拽事件 (start/enter/location/drop/end)
mDragListener = new MyDragEventListener();
mImageView.setOnDragListener(mDragListener);
}
protected class MyDragEventListener implements View.OnDragListener {
@Override
public boolean onDrag(View v, DragEvent event) {
final int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
v.setBackgroundColor(Color.BLUE); // 設置圖片背景顏色
v.invalidate();
// 返回true才能收到後面的時間,否則只能收到end
return (true);
} else {
return (false);
}
//break;
case DragEvent.ACTION_DRAG_ENTERED:
v.setBackgroundColor(Color.RED); // 設置圖片背景顏色
v.invalidate();
return true;
//break;
case DragEvent.ACTION_DRAG_LOCATION:
return true;
case DragEvent.ACTION_DRAG_EXITED:
v.setBackgroundColor(Color.BLACK); // 設置圖片背景顏色
v.invalidate();
return true;
//並沒有執行,需要檢查
case DragEvent.ACTION_DROP:
ClipData.Item item = event.getClipData().getItemAt(0);
CharSequence dragData = item.getText();
Toast.makeText(mContext, "Dragged data is " + dragData, Toast.LENGTH_LONG).show();
v.setBackgroundColor(mContext.getResources().getColor(R.color.colorAccent));
v.invalidate();
return true;
case DragEvent.ACTION_DRAG_ENDED:
v.setBackgroundColor(Color.YELLOW); // 設置圖片背景顏色
v.invalidate();
if (event.getResult()) {
Toast.makeText(mContext, "The drop was handled.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(mContext, "The drop didn't work.", Toast.LENGTH_LONG).show();
}
return true;
default:
Log.e("DragDrop Example", "Unknown action type received by OnDragListener.");
break;
}
return false;
}
}
}