I created a custom view which overrides onTouchListener in order to have differents images drown depending on the action performed by the user. (To change the background of the view when the user click on it for example).
I want to use this custom view in a ListView, so I created a custom adapter which displays all my views but the onItemClickListener of my ListView is never triggered.
What can I do ?
Here's the code from my Custom View:
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setMode(MODE_SELECTED);
invalidate();
break;
case MotionEvent.ACTION_UP:
setMode(MODE_NONE);
invalidate();
break;
case MotionEvent.ACTION_CANCEL:
setMode(MODE_NONE);
invalidate();
break;
case MotionEvent.ACTION_OUTSIDE:
setMode(MODE_NONE);
invalidate();
break;
default:
break;
}
return true;
}
Ok, I found a solution : I use StateListDrawable and it avoids me to override the onTouch of my custom view !
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
I'm making Android application and I want this feature:
User can drag some view and when he dropt on some another view, I can register that he dropt on some view and do some work with that view.
For example:
There are two ImageView, one blue one red, and there is thrid ImageView, when user dropt third ImageView on blue one I have to call method1() and otherwise when user dropt on red one I have to call method2().
I have implemented standrad drag listener:
imageView.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
switch(event.getAction())
{
case DragEvent.ACTION_DRAG_STARTED:
Log.e(msg, "Action is DragEvent.ACTION_DRAG_STARTED");
return true;
case DragEvent.ACTION_DRAG_ENTERED:
Log.e(msg, "Action is DragEvent.ACTION_DRAG_ENTERED");
return true;
case DragEvent.ACTION_DRAG_EXITED :
Log.e(msg, "Action is DragEvent.ACTION_DRAG_EXITED");
break;
case DragEvent.ACTION_DRAG_LOCATION :
Log.e(msg, "Action is DragEvent.ACTION_DRAG_LOCATION");
break;
case DragEvent.ACTION_DRAG_ENDED :
Log.e(msg, "Action is DragEvent.ACTION_DRAG_ENDED");
break;
case DragEvent.ACTION_DROP:
Log.e(msg, "ACTION_DROP event");
break;
default: break;
}
return true;
}
});
You don't need to calculate rects. You should call setOnDragListener two times, once on the red image view to handle the drop events on it, and once on the blue image view to handle drop events on it. Also just in case, I don't see the code where you need to call startDrag on the view that user is dragging during the touch event to start the drag.
So, you need to call view.startDrag in order to listen to the callbacks.
You can move your view in ACTION_MOVE, and check the intersection in ACTION_DROP.
This can also be directly achieved by OnTouchListener.
You can get the full example here.
I have a project which i'm required to develop Android game that display a 5*5 table and and image for each player which each one of them can move the image in place inside the 5*5 table.
ex:
Note : I need to know the exact coordinates (or anything relative) so i can save the position in array and move the image to that new place (eg : re-draw it on the new position).
Any ideas ?
Thanks in advance.
Just use a RelativeLayout with 5x5 ImageViews (set to not visible).
And on the images that the user can move to the place, use Drag and Drop.
In onDrag you set the visibility of the image to Gone.
For all ImageView (5x5 Table), you set the onDragListener.
After that, in the overwritten method OnDrop, you can receive the view that is dropped and can determine which drawable to show.
edit:
Oh well, in this case I would use GridView as said in the comments. And make usage of drag and drop. You don't need to attach a DragListener to every image then. You can simply let the GridView listen to the drop events and determine by the x and y where to drop.
Little example (just as a hint)
gameStoneView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
DragShadowBuilder shadowBuilder = new DragShadowBuilder(gameStoneView);
gameStoneView.startDrag(null, shadowBuilder, gameStoneView, 0);
if (dragListener != null) {
dragListener.onDragStart();
}
break;
default:
LOG.v("Motion event reorderIcon: DEFAULT - not action down");
}
return true;
}
});
gridView.setOnDragListener(new OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_LOCATION:
currentY = event.getY();
currentX = event.getX();
break;
case DragEvent.ACTION_DROP:
final Point position = getPositionOfItem(currentX, currentY);
dropItemAt(position);
break;
case DragEvent.ACTION_DRAG_EXITED:
//BORDER DRAGEVENT: ACTION_DRAG_EXITED
viewDraggedOutSide = true;
break;
case DragEvent.ACTION_DRAG_ENDED:
//BORDER DRAGEVENT: ACTION_DRAG_ENDED
if (viewDraggedOutSideList) {
reinsertDraggedItem();
update();
}
viewDraggedOutSideList = false;
return true;
default:
return true;
}
}
});
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.
I'm trying to create a custom GridView but i'm having troubles with the touch listeners.
What i want to do:
Create a GridView with custom Views.
Longpress on an item so it becomes 'editable'.
Drag the view horizontal or vertical to move it's position in the GridView.
Here's where i'm having trouble:
I'm implementing GestureDetector.OnGestureListener for the longpress functions, because for some reason using the gridview.setOnItemLongClickListener() isn't working when overriding the onTouchEvent() of the GridView itself (Which i need for the dragging part). So everything is fine at this point. Now i only need to know when the longpress is finished. So i though: "Well this shouldn't be hard." I couldn't have be more wrong. I've fiddled around for quite some time with this and it looks like using different touch events isn't helping me :/
When stepping through the onTouchEvent() i noticed that only 1 action is given: MotionEvent.ACTION_DOWN. So what am i doing wrong? i need the MotionEvent.ACTION_UP...
Found the culprit:
i was doing something like this
#Override
public boolean onTouchEvent(MotionEvent event) {
// Give everything to the gesture detector
boolean retValue = gestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE :
onMove();
break;
case MotionEvent.ACTION_UP :
onUp();
break;
case MotionEvent.ACTION_CANCEL:
onCancel();
break;
}
return retValue;
}
i think retValue was always returning false so no other events were triggered.
this fixed the issue:
#Override
public boolean onTouchEvent(MotionEvent event) {
// Give everything to the gesture detector
gestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE :
onMove();
break;
case MotionEvent.ACTION_UP :
onUp();
break;
case MotionEvent.ACTION_CANCEL:
onCancel();
break;
}
return true;
}