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;
}
}
}