我正在尝试在android studio中创建一个简单的拖放图像。我可以让图像在屏幕上拖动,一旦我释放它就会消失。在控制台中,我收到“报告丢弃结果:false”
这是我的代码:
ImageView mImageView;
String mString;
private android.widget.RelativeLayout.LayoutParams mLayoutParams;
mImageView.setOnLongClickListener(new View.OnLongClickListener(){
@Override
public boolean onLongClick(View v){
ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());
String[] mimeTypes = {
ClipDescription.MIMETYPE_TEXT_PLAIN
};
ClipData dragData = new ClipData(v.getTag().toString(), mimeTypes, item);
View.DragShadowBuilder myShadow = new View.DragShadowBuilder(mImageView);
v.startDrag(dragData, myShadow, null, 0);
return true;
}
});
mImageView.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
switch(event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
mLayoutParams = (RelativeLayout.LayoutParams)v.getLayoutParams();
Log.d(mString, "Action is DragEvent.ACTION_DRAG_STARTED");
// Do nothing
break;
case DragEvent.ACTION_DRAG_ENTERED:
Log.d(mString, "Action is DragEvent.ACTION_DRAG_ENTERED");
int x_cord = (int) event.getX();
int y_cord = (int) event.getY();
break;
case DragEvent.ACTION_DRAG_EXITED :
Log.d(mString, "Action is DragEvent.ACTION_DRAG_EXITED");
x_cord = (int) event.getX();
y_cord = (int) event.getY();
mLayoutParams.leftMargin = x_cord;
mLayoutParams.topMargin = y_cord;
v.setLayoutParams(mLayoutParams);
break;
case DragEvent.ACTION_DRAG_LOCATION :
Log.d(mString, "Action is DragEvent.ACTION_DRAG_LOCATION");
x_cord = (int) event.getX();
y_cord = (int) event.getY();
break;
case DragEvent.ACTION_DRAG_ENDED :
Log.d(mString, "Action is DragEvent.ACTION_DRAG_ENDED");
// Do nothing
break;
case DragEvent.ACTION_DROP:
Log.d(mString, "ACTION_DROP event");
// Do nothing
break;
default: break;
}
return true;
}
});
mImageView.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(mImageView);
mImageView.startDrag(data, shadowBuilder, mImageView, 0);
mImageView.setVisibility(View.INVISIBLE);
return true;
} else {
return false;
}
}
});
}
}
答案 0 :(得分:8)
已编辑:更改了如何使用onTouch移动RelativeLayout中包含的所有视图的工作示例。我认为onDrag事件更适用于拖放数据项,而不是移动视图。
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
private RelativeLayout mRelLay;
private float mInitialX, mInitialY;
private int mInitialLeft, mInitialTop;
private View mMovingView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRelLay = (RelativeLayout) findViewById(R.id.relativeLayout);
for (int i = 0; i < mRelLay.getChildCount(); i++)
mRelLay.getChildAt(i).setOnTouchListener(this);
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
RelativeLayout.LayoutParams mLayoutParams;
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
mMovingView = view;
mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams();
mInitialX = motionEvent.getRawX();
mInitialY = motionEvent.getRawY();
mInitialLeft = mLayoutParams.leftMargin;
mInitialTop = mLayoutParams.topMargin;
break;
case MotionEvent.ACTION_MOVE:
if (mMovingView != null) {
mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams();
mLayoutParams.leftMargin = (int) (mInitialLeft + motionEvent.getRawX() - mInitialX);
mLayoutParams.topMargin = (int) (mInitialTop + motionEvent.getRawY() - mInitialY);
mMovingView.setLayoutParams(mLayoutParams);
}
break;
case MotionEvent.ACTION_UP:
mMovingView = null;
break;
}
return true;
}
}
答案 1 :(得分:5)
给出的代码有一个问题很容易修复。应为目标(或任何可能的目标)视图设置OnDragListener()
。因此,OnLongClickListener()
和OnTouchListener()
在源视图imageView
上设置,imageView2
应该OnDragListener()
。这是一个很长的解释,但应该很容易解决。
请参阅drag-drop以获得一个好例子。
如果正确完成,解决方案的其余部分将更加复杂(但是,有一个解决方法)。
开始拖动时,基本上您需要将图像复制到剪贴板,然后将其粘贴到拖放视图中。这需要创建ContentProvider
然后使用ContentResolver
(link)。
剪贴板文档:ClipData
我有未来计划为应用程序执行此操作,但这不会很快发生,所以不幸的是,我将无法提供任何代码。
但是,有一种解决方法更少涉及。
在可能会移动的任何图像上设置标记。
imageView.setTag("ImageTag1");
在onLongClick()
中,按照问题进行设置item
和dragData
。
然后在OnDragListener()
中,读取标签,确定要删除的图像,然后将该图像设置为视图。像这样:
case DragEvent.ACTION_DROP:
ClipData.Item item = event.getClipData().getItemAt(0);
CharSequence dragData = item.getText();
if(dragData.equals("ImageTag1")) {
// this gets jpg image from "drawable" folder,
// set ImageView appropriately for your usage
((ImageView)v).setImageResource(R.drawable.image1);
} else if(dragData.equals("ImageTag2")) {
((ImageView)v).setImageResource(R.drawable.image2);
}
break;
您还需要在“ACTION_DRAG_EXITED”的情况下执行类似的操作。如果图像被放入无效区域,则会将图像放回原始视图。
答案 2 :(得分:0)
这就是我在我的应用中的表现:
对于&#34;视图&#34;要拖动,请在onTouchListener中设置:
public final class ChoiceTouchListener implements OnTouchListener {
Context context;
//int index;
public static float offsetX = 0,offsetY = 0;
DragShadowBuilder shadowBuilder;
public ChoiceTouchListener(Context context) {
super();
this.context = context;
//this.index = index;
}
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
//view.setTag("option"+index);
ClipData data = ClipData.newPlainText("tag", view.getTag().toString());
shadowBuilder = new View.DragShadowBuilder(view);
//start dragging the item touched
view.startDrag(data, shadowBuilder, view, 0);
offsetX = view.getLeft();//(int)view.getX();//(int)motionEvent.getX();
offsetY = view.getTop();//(int)view.getY();//motionEvent.getY();
view.setVisibility(View.INVISIBLE);
Log.v("here","it is ::" + (int)motionEvent.getX() + " , "+(int)motionEvent.getY());
return false;
}
return true;
}
}
这是一个具有目的地&#34; view&#34;的RelativeLayout。设置在中间并监听拖放事件:
public class DragLayout extends RelativeLayout {
boolean DEBUG = true;
AnimationDrawable blenderAnim;
Handler handlerAnim2;
Context context;
private int dimensionInPixel = 200;
int screenWidth,screenHeight;
public DragLayout(Context context) {
super(context);
this.context = context;
//not to include in main program
getDimensionsofScreen();
setLayout();
setViews();
}
private void setLayout() {
// set according to parent layout (not according to current layout)
RelativeLayout.LayoutParams rLp = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
rLp.topMargin = 2 * (screenHeight / 25); // calculating 1/10 of 4/5
// screen
this.setLayoutParams(rLp);
}
void setViews() {
ImageView img2 = new ImageView(context);
int dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics());
RelativeLayout.LayoutParams rLp = new RelativeLayout.LayoutParams(
(screenWidth / 5), (screenHeight / 5));
rLp.topMargin = (screenHeight / 10);
rLp.leftMargin = (4*screenWidth / 10);
rLp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
img2.setLayoutParams(rLp);
img2.getLayoutParams().height = dimensionInDp;
img2.getLayoutParams().width = dimensionInDp;
img2.setImageDrawable(getResources().getDrawable(R.drawable.blender_anim));
img2.setOnDragListener(new ChoiceDragListener(context));
this.addView(img2);
blenderAnim = (AnimationDrawable)img2.getDrawable();
blenderAnim.setOneShot(true);
blenderAnim.stop();
}
public ArrayList<Integer> getDimensionsofScreen() {
//metrics that holds the value of height and width
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();;
ArrayList<Integer> vals = new ArrayList<Integer>();
vals.add(displayMetrics.widthPixels);
vals.add(displayMetrics.heightPixels);
screenHeight = displayMetrics.heightPixels;
screenWidth = displayMetrics.widthPixels;
return vals;
}
@SuppressLint("NewApi")
@Override
public boolean onDragEvent(DragEvent event) {
int mCurX = (int) event.getX();
int mCurY = (int) event.getY();
if(event.getAction() == DragEvent.ACTION_DRAG_STARTED || event.getAction() == DragEvent.ACTION_DRAG_ENTERED) {
if (blenderAnim.isRunning()) {
blenderAnim.stop();
} else {
blenderAnim.run();
handlerAnim2 = new Handler();
handlerAnim2.postDelayed(
new Runnable(){
@Override
public void run() {
blenderAnim.stop();
}},
getAnimationDuration(blenderAnim));
}
}
if(event.getAction() == DragEvent.ACTION_DROP || event.getAction() == DragEvent.ACTION_DRAG_EXITED) {
if (blenderAnim.isRunning()) {
blenderAnim.stop();
} else {
blenderAnim.run();
handlerAnim2 = new Handler();
handlerAnim2.postDelayed(
new Runnable(){
@Override
public void run() {
blenderAnim.stop();
}},
getAnimationDuration(blenderAnim));
}
Log.v("here", "it is :: " + mCurX + ", " + mCurY);
View view1 = (View) event.getLocalState();
view1.setVisibility(View.VISIBLE);
ObjectAnimator animationx = ObjectAnimator.ofFloat(view1,"translationX", mCurX - ChoiceTouchListener.offsetX-(screenWidth / 10),0.0f);
ObjectAnimator animationy = ObjectAnimator.ofFloat(view1, "translationY", mCurY - ChoiceTouchListener.offsetY - (screenHeight / 10), 0.0f);
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(500);
animSet.playTogether(animationx,animationy);
animSet.start();
}
if(event.getAction() == DragEvent.ACTION_DROP || event.getAction() == DragEvent.ACTION_DRAG_ENDED){
if(blenderAnim.isRunning()){
blenderAnim.stop();
}
}
return true;
}
private int getAnimationDuration(AnimationDrawable src){
int dur = 0;
for(int i=0; i<src.getNumberOfFrames(); i++){
dur += src.getDuration(i);
}
return dur;
}
}
这是DragLayout中ImageView的拖动侦听器:
public class ChoiceDragListener implements View.OnDragListener {
boolean DEBUG = true;
Context context;
public String TAG = "Drag Layout:";
public ChoiceDragListener(Context context){
this.context = context;
}
@Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
if(DEBUG) Log.v("here","drag started");
break;
case DragEvent.ACTION_DRAG_ENTERED:
break;
case DragEvent.ACTION_DRAG_LOCATION:
int mCurX = (int) event.getX();
int mCurY = (int) event.getY();
if(DEBUG) Log.v("Cur(X, Y) : " ,"here ::" + mCurX + ", " + mCurY );
break;
case DragEvent.ACTION_DRAG_EXITED:
if(DEBUG)
Log.v("here","drag exits");
break;
case DragEvent.ACTION_DROP:
//handle the dragged view being dropped over a drop view
View view = (View) event.getLocalState();
ClipData cd = event.getClipData();
ClipData.Item item = cd.getItemAt(0);
String resp = item.coerceToText(context).toString();
//view dragged item is being dropped on
ImageView dropTarget = (ImageView) v;
//view being dragged and dropped
final ImageView dropped = (ImageView) view;
dropped.setEnabled(false);
//if an item has already been dropped here, there will be a tag
final Object tag = dropTarget.getTag();
LayoutInflater li = LayoutInflater.from(context);
View promptsView = li.inflate(R.layout.ns_scoop_dialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set prompts.xml to alertdialog builder
alertDialogBuilder.setView(promptsView);
final EditText userInput = (EditText) promptsView
.findViewById(R.id.edit1);
// set dialog message
alertDialogBuilder
.setIcon(R.mipmap.ic_launcher)
.setTitle(dropped.getTag().toString())
.setCancelable(false)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// get user input and set it to result
// edit text
String inAmt = userInput.getText().toString();
CreateSmoothie.nsList.add(inAmt + " Green Scoops " + dropped.getTag().toString());
Log.d(TAG, inAmt + " Green Scoops " + dropped.getTag().toString() + " added to list");
dialog.dismiss();
//dropped.setEnabled(true);
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
int existingID = dropped.getId();
//set the original view visible again
((Activity) context).findViewById(existingID).setVisibility(View.VISIBLE);
dropped.setEnabled(true);
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
//Button nButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
//nButton.setBackgroundColor(Color.GREEN);
//Button pButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
//pButton.setBackgroundColor(Color.GREEN);
if(tag!=null)
{
//the tag is the view id already dropped here
int existingID = (Integer)tag;
//set the original view visible again
((Activity) context).findViewById(existingID).setVisibility(View.VISIBLE);
}
break;
case DragEvent.ACTION_DRAG_ENDED:
if(DEBUG) Log.i("drag event", "ended::" + ChoiceTouchListener.offsetX + "," + ChoiceTouchListener.offsetY);
/**
* returning false so that goes to parentView onDrag function
*/
return false;
//break;
default:
break;
}
return true;
}
}
希望有所帮助。