I am using OnDragListener to drag and drop image. i have MOTIONEVENT.ACTION_MOVE to implement image moving functionality. At a certain point in the action move, I want to end the drag and remove its shadow. Is it possible to set the action in drag event? Before releasing finger i want to call drop event.
switch(event.getAction()) {
case MotionEvent.ACTION_MOVE:
//here i want to remove shadow and stop dragging
break;
case DragEvent.ACTION_DROP:break;
}
You can implement OnDragListener in your class/ fragments.
class MyDrag implements OnDragListener {
Drawable image = getResources().getDrawable(
R.drawable.shape_droptarget);
#Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
// Signals the start of a drag and drop operation
break;
case DragEvent.ACTION_DRAG_ENTERED:
//Signals to a View that the drag point has entered the bounding box of the View
v.setBackgroundDrawable(image);
break;
case DragEvent.ACTION_DRAG_EXITED:
//Signals that the user has moved the drag shadow out of the bounding box of the View or into a descendant view that can accept the data.
v.setBackgroundDrawable(image);
break;
case DragEvent.ACTION_DROP:
// Signals to a View that the user has released the drag shadow, and the drag point is within the bounding box of the View and not within a descendant view that can accept the data.
View view = (View) event.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
owner.removeView(view);
LinearLayout container = (LinearLayout) v;
container.addView(view);
view.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
//Signals to a View that the drag and drop operation has concluded.
v.setBackgroundDrawable(image);
default:
break;
}
return true;
}
}
for more details refer here Drag and Drop
Related
In my code I have a LinearLayout that has child views, along with creating every child view (via code not xml) I set setOnLongClickListener and setOnDragListener, and it works with a horrible down side effect, that when onDrag gets called on one of the child views, case DragEvent.ACTION_DRAG_STARTED: gets called on all of the child views. why is that?
childView.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(final View aChildView, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
Log.d("++++", "Drag Started");
aChildView.addView(Early Made up view);
break;
case DragEvent.ACTION_DRAG_ENTERED:
break;
case DragEvent.ACTION_DRAG_EXITED:
childView.setBackground(new ColorDrawable(Color.TRANSPARENT));
break;
case DragEvent.ACTION_DROP:
childView.setBackground(new ColorDrawable(Color.TRANSPARENT));// In case it got dropped on itself.
break;
case DragEvent.ACTION_DRAG_ENDED:
break;
default:
return false;
}
return true;
}
});
The thing is, that the early made up view appears inside all the child views not just the one that is being dragged.
I believe the answer to my question is that Action Drag Started fired for all views that supports drag and drop in the layout, while Action Drop is for the view that received the drop.
https://stackoverflow.com/a/13301939/5851265
class MyDragListener implements View.OnDragListener {
private float dX;
private float dY;
ImageView tmpView;
#Override
public boolean onDrag(View view, DragEvent event) {
// Handles each of the expected events
switch (event.getAction()) {
//signal for the start of a drag and drop operation.
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
//the drag point has entered the bounding box of the View
case DragEvent.ACTION_DRAG_ENTERED:
//v.setBackground(targetShape); //change the shape of the view
break;
//the user has moved the drag shadow outside the bounding box of the View
case DragEvent.ACTION_DRAG_EXITED:
//v.setBackground(normalShape); //change the shape of the view back to normal
break;
//drag shadow has been released,the drag point is within the bounding box of the View
case DragEvent.ACTION_DROP:
dX = view.getX() - event.getX();
dY = view.getY() - event.getY();
tmpView = new ImageView(getActivity());
tmpView.setImageDrawable(((ImageView) view).getDrawable());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(150, 150);
params.leftMargin = (int) event.getX();
params.topMargin = (int) event.getY();
mFrameLayout.addView(tmpView, params);
RelativeLayout.LayoutParams ivLayoutParams = (RelativeLayout.LayoutParams) tmpView.getLayoutParams();
ivLayoutParams.leftMargin = (int) (event.getX());
ivLayoutParams.topMargin = (int) (event.getY() - 250);
tmpView.setLayoutParams(ivLayoutParams);
break;
//the drag and drop operation has concluded.
case DragEvent.ACTION_DRAG_ENDED:
//v.setBackground(normalShape); //go back to normal shape
default:
break;
}
return true;
}
}
Here mFrameLayout is the frameLayout in my xml.
<FrameLayout
android:layout_width="350dp"
android:layout_height="250dp"
android:layout_marginTop="20dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="#+id/frameLayout"
android:clickable="true"
android:longClickable="true">
</FrameLayout>
The Drag works properly but when dropping into the frameLayout it throws .FrameLayout cannot be cast to ImageView at line this:
tmpView.setImageDrawable(((ImageView) view).getDrawable());
The Draglistener is registered to the frame layout as mFrameLayout.setOnDragListener(new MyDragListener());
I have read that for dropping an image FrameLayout is best, but I am not able to drop the image to the FrameLayout from my other Layout.
UPDATE:
Now my error does not appear, but the image does not appear at the drop location too:
class MyDragListener implements View.OnDragListener {
private float dX;
private float dY;
ImageView tmpView;
#Override
public boolean onDrag(View view, DragEvent event) {
// Handles each of the expected events
switch (event.getAction()) {
//signal for the start of a drag and drop operation.
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
//the drag point has entered the bounding box of the View
case DragEvent.ACTION_DRAG_ENTERED:
//v.setBackground(targetShape); //change the shape of the view
break;
//the user has moved the drag shadow outside the bounding box of the View
case DragEvent.ACTION_DRAG_EXITED:
//v.setBackground(normalShape); //change the shape of the view back to normal
break;
//drag shadow has been released,the drag point is within the bounding box of the View
case DragEvent.ACTION_DROP:
View draggedView = (View) event.getLocalState();
if(mLinearLayout.getParent() != null){
ViewGroup parent = (ViewGroup) draggedView.getParent();
parent.removeView(draggedView);
mLinearLayout.removeView(draggedView);
}
mLinearLayout.addView(draggedView);
internalImageView.setVisibility(View.VISIBLE);
view.invalidate();
break;
//the drag and drop operation has concluded.
case DragEvent.ACTION_DRAG_ENDED:
//v.setBackground(normalShape); //go back to normal shape
default:
break;
}
return true;
}
}
My xml.
<LinearLayout
android:orientation="horizontal"
android:layout_height="250dp"
android:id="#+id/linearLayoutPlaceHolder"
android:layout_below="#+id/textView"
android:layout_centerHorizontal="true"
android:layout_marginTop="13dp"
android:layout_width="375dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:srcCompat="#drawable/cast_album_art_placeholder"
android:id="#+id/imageView2"
android:layout_weight="1" />
</LinearLayout>
And the StartDrag method being
mImageViewHolder.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
// Instantiates the drag shadow builder.
View.DragShadowBuilder myShadow = new DragShadowBuilder(mImageViewHolder);
// Starts the drag
view.startDrag(null, // the data to be dragged
myShadow, // the drag shadow builder
view, // need to use local data
0 // flags (not currently used, set to 0)
);
return true;
}
});
I can now drag and drop from one layout to another but the only one image can be dragged and dropped. I cannot repeat for other images.
Found a solution.
The Drag Listener is now written like this.
private LinearLayout mLinearLayout;
private ImageView internalImageView;
class MyDragListener implements View.OnDragListener {
#Override
public boolean onDrag(View view, DragEvent event) {
// Handles each of the expected events
switch (event.getAction()) {
//signal for the start of a drag and drop operation.
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
//the drag point has entered the bounding box of the View
case DragEvent.ACTION_DRAG_ENTERED:
break;
//the user has moved the drag shadow outside the bounding box of the View
case DragEvent.ACTION_DRAG_EXITED:
break;
//drag shadow has been released,the drag point is within the bounding box of the View
case DragEvent.ACTION_DROP:
View draggedView = (View) event.getLocalState();
if(mLinearLayout.getParent() != null){
ViewGroup parent = (ViewGroup) draggedView.getParent();
parent.removeView(draggedView);
mLinearLayout.removeAllViews();
//mLinearLayout.removeAllViewsInLayout();
}
mLinearLayout.addView(draggedView);
mLinearLayout.invalidate();
internalImageView.setVisibility(View.VISIBLE);
view.invalidate();
break;
//the drag and drop operation has concluded.
case DragEvent.ACTION_DRAG_ENDED:
//## Heading ##view.getRootView().findViewById(R.id.carouselView).invalidate();
break;
default:
break;
}
return true;
}
}
I use Android Drag and Drop to drag my image around the screen. When I drop, the image returns to its original location. But I want the image to stay in the location it was dropped in.
My attempt: I saved the X and Y positions of the image at ACTION_DROP, then tried to set the new view position with those same X and Y coordinates.
Can someone please help?
And please let me know if I need to provide more code.
Code:
class MyDragListener implements View.OnDragListener {
#Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
break;
case DragEvent.ACTION_DRAG_ENTERED:
if(v==findViewById(R.id.linear_layout_button))
findViewById(R.id.removeText).setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_EXITED:
if(v==findViewById(R.id.linear_layout_button))
findViewById(R.id.removeText).setVisibility(View.GONE);
break;
case DragEvent.ACTION_DROP:
if(v==findViewById(R.id.linear_layout_image)) {
View view = (View) event.getLocalState();
float posx = view.getX();
float posy = view.getY();
ViewGroup owner = (ViewGroup) view.getParent();
owner.removeView(view);
LinearLayout container = (LinearLayout) v;
container.addView(view);
view.setX(posx);
view.setY(posy);
view.setVisibility(View.VISIBLE);
}
break;
case DragEvent.ACTION_DRAG_ENDED:
default:
break;
}
return true;
}
}
This is happening because you are using your x y positions again. Try by commenting this two lines
// view.setX(posx);
// view.setY(posy);
I'm trying to drag and drop multiple items.
Currently I have one set of Imagebuttons defined in a Linear layout, and another defined in a separate linear layout.
I'd like to make it so if you drag from a button that is not at the bottom of the layout, it will drag all items below it along with it.
With the stock drag and drop code (below) it only allows me to drag one.
private final class MyTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(data, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
}
else {
return false;
}
}
}
I think I might be able to move more than one view through here, but I honestly don't know that much about them.
The drag and drop area (minus my log code and whatnot) looks typical:
class MyDragListener implements View.OnDragListener {
//Drawable enterShape = getResources().getDrawable(R.drawable.shape_droptarget);
//Drawable normalShape = getResources().getDrawable(R.drawable.shape);
#Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
View view = (View) event.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
LinearLayout container = (LinearLayout) v;
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
case DragEvent.ACTION_DRAG_ENTERED:
//v.setBackgroundDrawable(enterShape);
break;
case DragEvent.ACTION_DRAG_EXITED:
//v.setBackgroundDrawable(normalShape);
break;
case DragEvent.ACTION_DROP:
// Dropped, reassign View to ViewGroup
owner.removeView(view);
container.addView(view);
view.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
//rebuildField(); works well but is clogging up the logs
//v.setBackgroundDrawable(normalShape);
default:
break;
}
return true;
}
}
I ended up solving this by finding out a lot about views, inflaters, and layouts.
I wrote a function that finds all the ImageButtons below where the user clicked, and set them all to invisible. I then created a new Linear Layout within the Linear Layout that the user clicked, and passed that into the Drag Shadow builder.
Once into the ACTION_DROP portion, I simply referenced global variables to figure out if the user dropped in one or multiple ImageButtons, and dealt with them accordingly.
I am having two Draglisteners
Listener A it is placeholder to drop a particular item into it.(LinearLayout)
Listener B the item which is being drop.(its a relative layout)
When i drag the relative layout it is drawing the shadow but when dropped resulting false.
I set the visiblity View.VISIBLE of LinearLayout only when the relative layout is being dragged.
The draglistener code for linearlayout
#Override
public boolean onDrag(View v, DragEvent dragevent) {
switch (dragevent.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
break;
case DragEvent.ACTION_DRAG_ENTERED:
// setting background
break;
case DragEvent.ACTION_DRAG_EXITED:
break;
case DragEvent.ACTION_DROP:
// updating my view
break;
case DragEvent.ACTION_DRAG_ENDED:
break;
default:
break;
}
return true;
}
But only for the first time the DROP result is false from the second time it is working correct. And I set the draglistener when the activity created. Can anyone help me in this.