I use the onTouchEvent method to be able to have a drag&drop event and a click event. I test the result on my Nexus 7 (2012), it's working really great but on my smarphone a Asus Zenfone, it's not and I can't see why, here is my code :
button.setOnTouchListener(new View.OnTouchListener() {
private float startX, startY;
private long startClickTime;
#Override
public boolean onTouch(final View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
startClickTime = Calendar.getInstance().getTimeInMillis();
break;
case MotionEvent.ACTION_MOVE:
if (v instanceof Button) {
Button button = ((Button) v);
if (button.getText().length() == 0) return true;
ClipData clipData = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new DragShadowBuilder(v, false, scale);
v.startDrag(clipData, shadowBuilder, v, 0);
DataHolder.getInstance().setCurrentText(button.getText().toString());
button.setText("");
}
return true;
case MotionEvent.ACTION_UP:
float endX = event.getX();
float endY = event.getY();
long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
if (isAClick(startX, endX, startY, endY) && clickDuration < CLICK_DURATION) {
v.performClick();
}
return true;
}
return false;
}
});
Did someone see why my click is not triggered ?
Edit : the screenshot
This is my suggestion - Go to your phone settings there is an option to show layout boundaries you can set it on and off - you can see where you are clicking when this options is on .
I take no responsibility on what might happen to your phone yet this is how i always solve those problems
I finally succeed to make my code working. I just added in the Action Move if the detection of a click, if it's not and only if it's not I begin a drag. That's it.
Related
I used this link to create a view to swipe up and down views! but there is one problem! after I slide up the view and I want to slide down to close it, I have to slide the parent view!! and the view itself can't detect the sliding!
I've tried adding this code to my mainActivity :
sliderView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
float touchedArea = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mViewHeight = sliderView.getHeight();
x1 = event.getX();
y1 = event.getY();
mViewStartPositionY = sliderView.getTranslationY();
mCanSlide |= sliderView.getBottom() - sliderView.getHeight() <= touchedArea;
t1 = System.currentTimeMillis();
break;
case MotionEvent.ACTION_MOVE:
float difference = event.getRawY() - y1;
y2 = event.getRawY();
float moveTo = mViewStartPositionY + difference;
if(moveTo > 0 && mCanSlide) {
sliderView.setTranslationY(moveTo);
}
}
return true;
}
});
but when I slide down, it has some bugs and the sliderView freeze sometimes!
how can I fixed this issue?!
or if there are any tutorials or other useful libraries, please let me know!
also, I used this library, but It has some issues too!
So I've been in this for a while now and have been unable to figure out how to implement 4-way swipe recognition in android. I've found different links pointing to different solutions but none of them fulfill my requirements.
What I wish to accomplish is to attain a "Badoo" like swipe gesture. Badoo is a Tinder like application. On swiping up/down the user's pictures are scrolled, and on left/right, the card is liked/disliked.
The animation I wish to achieve is that on left/right the card follows the set left/right path and moves to like/dislike. On up/down the pictures snap to their next/previous ones.
I've tried countless libraries over github that for swipeable cards and am now trying to implement a custom view for my requirements.
Currently I'm trying to insert a VerticalViewPager inside a CardView. The problem here is that the VerticalViewPager is intercepting all touch events therefore I am unable to swipe my card right/left.
This is my OnTouch event for the CardView item:
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
pager.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
pager.requestDisallowInterceptTouchEvent(false);
break;
}
return true;
}
This is what I'm trying to achieve. This is what Badoo looks like:
Badoo Screenshot 1: https://drive.google.com/open?id=0BzGcu10X5GRrTDZHRm4xT0tnQ1k
Badoo Screenshot 2: https://drive.google.com/open?id=0BzGcu10X5GRrc2pvRTZKS2p2UEU
If anyone knows of any similar libraries with a similar 4-way swipe gesture please let me know.
EDIT:
I've made a parent view for the card and the ViewPager, the CardView (cardViewParent) has a child cardView and cardView's child is a VerticalViewPager (mViewPager):
cardViewParent.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
Toast.makeText(context, "incardviewPARENT", Toast.LENGTH_SHORT).show ();
float rawX = 0, rawY = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//gesture has begun
float x;
float y;
//cancel any current animations
mActivePointerId[0] = event.getPointerId(0);
x = event.getX();
y = event.getY();
rawX = event.getRawX();
rawY = event.getRawY();
initialXPress[0] = x;
initialYPress[0] = y;
initialRawXPress[0] = rawX;
initialRawYPress[0] = rawY;
break;
case MotionEvent.ACTION_MOVE:
//gesture is in progress
final int pointerIndex = event.findPointerIndex(mActivePointerId[0]);
//Log.i("pointer index: " , Integer.toString(pointerIndex));
if (pointerIndex < 0 || pointerIndex > 0) {
break;
}
final float xMove = event.getX(pointerIndex);
final float yMove = event.getY(pointerIndex);
float rawDY = Math.abs(event.getRawY() -
initialRawYPress[0]);
float rawDX = Math.abs(event.getRawX() - initialRawXPress[0]);
//calculate distance moved
final float dx = xMove - initialXPress[0];
final float dy = yMove - initialYPress[0];
Log.d("RAW DY:", "" + rawDY);
if(rawDY > 100 && !animationStart[0])
{
// vertical swipe detected
mViewPager.setSwipeable(true);
cardStack.setSWIPE_ENABLED(false);
// mViewPager.dispatchTouchEvent(event);
return false;
}
if((rawDY <100 && rawDX > 100) ||
animationStart[0]) {
//horizontal swipe
animationStart[0] = true;
cardStack.setSWIPE_ENABLED(true);
mViewPager.setSwipeable(false);
// cardStack.dispatchTouchEvent(event);
return false;
}
}
return true;
}
});
If an Upwards Swipe Motion is detected then I'm enabling the ViewPager's swipe motion, else the CardStack's (swipe deck) swipe is enabled. The problem is that the swipe motion doesn't start in any direction.
I am working on an Android app where I would like the user to be able to drag their finger on the screen and have an object I have set up as an Image View (a plane) follow it. I have a somewhat working model of this right now where the image will go to a point that is touched on the screen, but this is not exactly what I am looking to do. Also each time the user touches a new point, my image goes back to its starting spot then go to the users touch point. This is the relevant code:
public boolean onTouch(View v, MotionEvent e){
switch (e.getAction()){
case MotionEvent.ACTION_DOWN:
{
}
case MotionEvent.ACTION_UP:
{
float x = e.getX();
float y = e.getY();
movePlane(x, y);
}
case MotionEvent.ACTION_MOVE:
{
}
}
return true;
}
private boolean movePlane(float endX, float endY){
ImageView plane = (ImageView) findViewById(planeID);
float startX = plane.getX();
float startY = plane.getY();
TranslateAnimation animation = new TranslateAnimation(startX, endX, startY, endY);
animation.setDuration(3000);
animation.setFillAfter(true);
animation.setFillEnabled(true);
plane.startAnimation(animation);
return true;
}
So I know I am probably going to be working inside of the ACTION_DOWN case but I am not sure exactly how I should be handling the event and ImageView accordingly. Any help is really appreciated.
Hi try this link here you can use the params.x and params.y as the x,y co-ordinates you are passing to the method movePlane. Hope it helps.
There is a lot to read on that link, so thought its better i post the important code here. Below is the code you can use
plane.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
#Override public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
movePlane(params.x, params.y);
return true;
}
return false;
}
});
Plane is ofcourse the ImageView which you want to be dragged. You can refer the link if you want i took reference from it.
you have to set the x and y values after your animation with an AnimationListener -> onAnimationFinished, to avoid the "Also each time the user touches a new point, my image goes back to its starting spot then go to the users touch point" thing.
i am trying to do finger swipe but it is not detected .i am trying to draw a path which describes the area through which finger swipe but only when i swipe with force then only swipe get detected and else not detected
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 500) {
lastClick = System.currentTimeMillis();
synchronized (getHolder()) {
int eventaction = event.getAction();
if(event.getPressure()>0.00001||event.getSize()>0.00001)
{
float a,b,c;
switch(eventaction)
{
case MotionEvent.ACTION_DOWN:
xdown = event.getX();
ydown =event.getY();
pres=true;
break;
case MotionEvent.ACTION_MOVE:
if(pres)
{
xmove = event.getX();
ymove =event.getY();
a = (float) Math.sqrt(Math.pow(xdown - xmove,2) +Math.pow( ydown - ymove,2));
b=(float) (xdown-(((xdown - xmove) / a) * 150));
c=(float) (ydown-((( ydown - ymove)/a)*150));
move.moveTo(xdown, ydown);
move.lineTo(b, c);
pres=false;
lmove=true;
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_POINTER_UP:
move.reset();
xmove = 0;
ymove =0;
xdown=0;
ydown=0;
lmove=false;
pres=false;
break;
default:
return true;
}
}
}}
return true;
}
Android has a class for that. Check http://developer.android.com/reference/android/view/GestureDetector.html
I believe it is one of in touch events
See the code here: Simple swipe gesture to activity tutorial?
Using a SimpleOnGestureListener is easiest, and if you override the onFling method, it's easy/
Greets,
Does anyone how I go about detecting when a user presses on a bitmap which is inside a canvas?
Thanks
You should work with something like so:
public boolean onTouchEvent(MotionEvent event){
int action = event.getAction();
int x = event.getX() // or getRawX();
int y = event.getY();
switch(action){
case MotionEvent.ACTION_DOWN:
if (x >= xOfYourBitmap && x < (xOfYourBitmap + yourBitmap.getWidth())
&& y >= yOfYourBitmap && y < (yOfYourBitmap + yourBitmap.getHeight())) {
//tada, if this is true, you've started your click inside your bitmap
}
break;
}
}
That's a start, but you need to handle case MotionEvent.ACTION_MOVE and case MotionEvent.ACTION_UP to make sure you properly deal with the user input. The onTouchEvent method gets called every time the user: puts a finger down, moves a finger already on the screen or lifts a finger. Each time the event carries the X and Y coordinates of where the finger is. For example if you want to check for someone tapping inside your bitmap, you should do something like set a boolean that the touch started inside the bitmap on ACTION_DOWN, and then check on ACTION_UP that you're still inside the bitmap.
Steve,
Google has a great article and tutorial for handling UI Events # http://developer.android.com/guide/topics/ui/ui-events.html. This is what got me started and it was great for me :-)
This will detect a touch and check if it is not transparent. You need this if your bitmaps are not rectangles. myBitmap is just a simple container class I use.
private boolean clickOnBitmap(MyBitmap myBitmap, MotionEvent event) {
float xEnd = myBitmap.originX() + myBitmap.width();
float yEnd = myBitmap.originY() + myBitmap.height();;
if ((event.getX() >= myBitmap.originX() && event.getX() <= xEnd)
&& (event.getY() >= myBitmap.originY() && event.getY() <= yEnd) ) {
int pixX = (int) (event.getX() - myBitmap.originX());
int pixY = (int) (event.getY() - myBitmap.originY());
if (!(myBitmap.getBitmap().getPixel(pixX, pixY) == 0)) {
return true;
} else {
return false;
}
}
return false;
}
This is the on touch code for completeness
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (clickOnBitmap(dog, event)) {
Toast.makeText(getContext(), "dog", Toast.LENGTH_SHORT).show();
} else if (clickOnBitmap(mouse,event)) {
Toast.makeText(getContext(), "mouse", Toast.LENGTH_SHORT).show();
}
return true;
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
return true;
}
return false;
}