Reputation: 11
I have faced a problem following: I want to implement View.DragOnListener for a LinearLayout. When i long Click on the screen, OnDrag method received DragEvent.ACTION_DRAG_STARTED, but when i release drag on the screen. This method cannot received DragEvent.ACTION_DROP. Hope to get some helps from everyone. Here my code:
package com.example.dragdroptestapp;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.widget.LinearLayout;
public class MyLinearLayout extends LinearLayout implements View.OnDragListener{
private final String TAG = "MyLinearLayout";
public MyLinearLayout(Context context) {
super(context);
initLongClick();
}
public MyLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initLongClick();
}
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initLongClick();
}
@Override
public boolean onDragEvent(DragEvent event) {
final int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
Log.e(TAG, "Started");
break;
case DragEvent.ACTION_DRAG_ENTERED:
Log.e(TAG, "Entered");
break;
case DragEvent.ACTION_DROP:
Log.e(TAG, "Droped");
break;
default:
Log.e(TAG, "action event" + String.valueOf(action));
break;
}
return true;
}
@Override
public boolean onDrag(View v, DragEvent event) {
Log.e(TAG, "onDrag");
final int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
Log.e(TAG, "Started");
break;
case DragEvent.ACTION_DRAG_ENTERED:
Log.e(TAG, "Entered");
break;
case DragEvent.ACTION_DROP:
Log.e(TAG, "Droped");
break;
default:
break;
}
return true;
}
private void initLongClick() {
setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Log.e(TAG, "LongClick");
View.DragShadowBuilder myShadow = new DragShadowBuilder(v);
v.startDrag(null, myShadow, null, 0);
return true;
}
});
}
}
Upvotes: 1
Views: 2846
Reputation: 473
It is because may be you are trying to drop the view in some other view which is not the parent of that dragging view or may be the parent of the dragging view is inside some other view so the listening of drop event is not coming to the actual parent but the root of that parent (and the root is not registered with the DragListner )
Upvotes: 0
Reputation: 62
Below code might help others who are struggling with similar issue.
package com.javapapers.android.drag_drop;
import android.os.Bundle; import android.app.Activity;
import android.view.*;
import android.view.View.OnDragListener;
import android.view.View.OnTouchListener;
import android.view.View.DragShadowBuilder;
import android.widget.LinearLayout;
import android.util.Log;
import com.javapapers.android.drag_drop.R;
public class MainActivity extends Activity implements OnTouchListener, OnDragListener {
private static final String LOGCAT = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.textView1).setOnTouchListener(this);
findViewById(R.id.pinkLayout).setOnDragListener(this);
findViewById(R.id.yellowLayout).setOnDragListener(this);
}
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(null, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
}
else {
return false;
}
}
public boolean onDrag(View layoutview, DragEvent dragevent) {
int action = dragevent.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
Log.d(LOGCAT, "Drag event started");
break;
case DragEvent.ACTION_DRAG_ENTERED:
Log.d(LOGCAT, "Drag event entered into " + layoutview.toString());
break;
case DragEvent.ACTION_DRAG_EXITED:
Log.d(LOGCAT, "Drag event exited from "+layoutview.toString());
break;
case DragEvent.ACTION_DROP:
Log.d(LOGCAT, "Dropped");
View view = (View) dragevent.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
owner.removeView(view);
LinearLayout container = (LinearLayout) layoutview;
container.addView(view);
view.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
Log.d(LOGCAT, "Drag ended");
break;
default:
break;
}
return true;
}
Upvotes: 0
Reputation: 896
I just got done wrestling with a similar issue. The View that was mysteriously receiving ACTION_DRAG_STARTED and ACTION_DRAG_ENDED but not ACTION_DROP was underneath another much larger view that was also listening for drag events (but would only do anything with them if they were dropped in specific areas).
I fixed this by moving the larger towards the top of the XML layout file, which put it "underneath" the smaller View.
Upvotes: 2
Reputation: 5442
I also had same issue, ACTION_DROP
is not received usually due to following reasons:
1. OnDragListner should be applied on the layout rather then on view
2. You should return true instead break; from ACTION_DRAG_STARTED
as if it would not be true it will continue to next ACTION. so return true
from each ACTION.
So it is bit tough to tell on what you are setting OnDrag either layout or view, if you are calling on view then change it for layout.
Next instead of breaking from each ACTION in OnDragEvent just return true. This should solve your problem.
I hope I helped
Upvotes: 1