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!
Related
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 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.
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 have a circle and triangle images inside a view pager.
I am trying to move the triangle image along the circle image using on-touch listener.
But when i move the triangle, the screen/fragment also moves to the next as i am using a view pager.
What do i do so that when the on-touch listener of the triangle or circle is called then view pager on touch listener is not called.
UPDATE: ADDING CODE
mCurrTempIndicator.setOnTouchListener(new MyOnTouchListener());
private class MyOnTouchListener implements OnTouchListener {
private double startAngle;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mThermostatCentreXOnScreen == 0 || mThermostatCentreYOnScreen == 0){
int centerXOnImage=mThermostatBgrd.getWidth()/2;
int centerYOnImage=mThermostatBgrd.getHeight()/2;
mThermostatCentreXOnScreen=mThermostatBgrd.getLeft()+centerXOnImage;
mThermostatCentreYOnScreen=mThermostatBgrd.getTop()+centerYOnImage;
mStartPosX = event.getRawX();
mStartPosY = event.getRawY();
float dx = event.getX() - mThermostatCentreXOnScreen;
float dy = event.getY() - mThermostatCentreYOnScreen;
float r = FloatMath.sqrt((dx * dx) + (dy * dy));
////
break;
case MotionEvent.ACTION_MOVE:
dx = event.getX() - mThermostatCentreXOnScreen;
dy = event.getY() - mThermostatCentreYOnScreen;
r = FloatMath.sqrt((dx * dx) + (dy * dy));
mEndPosX = event.getX();
mEndPosY = event.getY();
case MotionEvent.ACTION_UP:
allowRotating = true;
break;
}
return true;
}
Thanks and regards,
Sunny
If you return true in your onTouchListener for the triangle and circle it will consume the event and the parent won't receive it.
Any suggestions for how to make an activity slider with "slide left" and "slide right" like a typical image slider??
I tried with: (implements OnTouchListener)
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
// code
break;
}
case MotionEvent.ACTION_UP:
{
// code
break;
}
case MotionEvent.ACTION_MOVE:
{
// code
break;
}
}
return true;
}
but don't have LEFT, RIGHT choice.
I don't need use buttons, just I need do somethings like the image slider for ipad2 but with activities for a customer app.
Thanks
You need to calculate by your own for slide left and right movement
MotionEvent.ACTION_UP
A pressed gesture has finished, the motion contains the final release location as well as any intermediate points since the last down or move event.
MotionEvent.ACTION_DOWN
A pressed gesture has started, the motion contains the initial starting location.
Use onTouchEvent(), and calculate difference in X and difference in Y by where the user presses down and lifts up. Use these values to figure out the direction of the move.
float x1, x2, y1, y2;
String direction;
switch(event.getAction()) {
case(MotionEvent.ACTION_DOWN):
x1 = event.getX();
y1 = event.getY();
break;
case(MotionEvent.ACTION_UP) {
x2 = event.getX();
y2 = event.getY();
float differenceInX = x2-x1;
float differenceInY = y2-y1;
// Use dx and dy to determine the direction
if(Math.abs(differenceInX) > Math.abs(differenceInY)) {
if(differenceInX > 0) direction = "right";
else direction = "left";
} else {
if(differenceInY > 0) direction = "down";
else direction = "up";
}
}
}