im trying to implement swipe for my list view item, i have hidden element (like a button )
i want swipe left/right item for showing this button. Everything work perfect. Except i cant click normally on item or button. Because event MotionEvent.ACTION_UP always triggered.
Log when i just make simple click/touch on item
Action DOWN
OLD X = -329.0
DX = -329.0
MOVE RIGHT
OLD X = -329.0
DX = -330.5
MOVE RIGHT
OLD X = -329.0
DX = -330.95996
MOVE RIGHT
Action UP
Can any help me ?
For click on items im trying to use this code
float cx = event.getX();
if(cx<width && cx>(width-150)) {
and my code
swipeLayout.setOnTouchListener(new View.OnTouchListener() {
private boolean canClick = false;
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
Logger.e("Action DOWN");
oldX = dX;
return true;
case MotionEvent.ACTION_MOVE:
Logger.e("OLD X = " + oldX);
Logger.e("DX = " + dX);
dX = view.getX() - event.getRawX();
if (oldX < dX) {
Logger.e("MOVE LEFT");
view.animate().x(-100).setDuration(50).start();
break;
}
if (oldX > dX) {
Logger.e("MOVE RIGHT");
view.animate().x(0).setDuration(50).start();
break;
}
case MotionEvent.ACTION_UP:
Logger.e("Action UP");
}
return false;
}
});
Consider using GestureDetector to handle swiping.
Here is the possible example:
new GestureDetector(context, new GestureDetector.SimpleOnGestureListener(){
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// Here you handle short quick swipe gesture
return super.onFling(e1, e2, velocityX, velocityY);
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// Here you handle slow finger movement across the screen
return super.onScroll(e1, e2, distanceX, distanceY);
}
});
Related
I'm currently creating my own game and I'm finding a way to recreate some sort of Clash of Clans kind of functionality where you can zoom in and out and drag the view of the screen these is what so far, I've done and it's kind of close to it I guess any other recommendations.
Functionality for it to zoom
image = (ImageView) findViewById(R.id.imageView);
sgd = new ScaleGestureDetector(this, new ScaleListener());
#Override
public boolean onTouchEvent(MotionEvent event) {
sgd.onTouchEvent(event);
return super.onTouchEvent(event);
}
class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener{
#Override
public boolean onScale(ScaleGestureDetector detector) {
FACTOR *= detector.getScaleFactor();
FACTOR = Math.max(.01f,Math.min(FACTOR, 10.f));
image.setScaleX(FACTOR);
image.setScaleY(FACTOR);
return true;
}
}
For it to drag
image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getActionMasked()) {
//checks if the user place finger in the screen
case MotionEvent.ACTION_DOWN:
xDown = motionEvent.getX();
yDown = motionEvent.getY();
break;
//checks if the user moves thier finger
case MotionEvent.ACTION_MOVE:
float movedX, movedY;
movedX = motionEvent.getX();
movedY = motionEvent.getY();
//calculate how much the user move their fingers
float distanceX = movedX - xDown;
float distanceY = movedY - yDown;
//will move the view to that position
image.setX(image.getX() + distanceX);
image.setY(image.getY() + distanceY);
break;
}
return true;
}
});
}
I have drag and drop imageView(multiple imageView with same object) in layout and after that ImageView onTouch it move around layout. but after move imageView it overlapping with each other, how do prevent overalapping image?
also every image object is same. here is my code :
public boolean onDrag(View view, DragEvent event) {
recyclerViewFloorTiles = findViewById(R.id.rvfloortiles);
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_ENDED:
break;
case DragEvent.ACTION_DROP:
dropX = event.getX();
dropY = event.getY();
final ObjectAdapter.DragData state = (ObjectAdapter.DragData) event.getLocalState();
final ImageView shape = (ImageView) LayoutInflater.from(this).inflate(
R.layout.layout_drag_image, dropContainer, false);
shape.setImageResource(state.item.getDrawableRes());
shape.setX(dropX - (float) state.width / 2);
shape.setY(dropY - (float) state.height / 2);
shape.getLayoutParams().width = state.width;
shape.getLayoutParams().height = state.height;
dropContainer.addView(shape);
shape.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
ImageView objectDropImage = new ImageView(DashboardActivity.this);
objectDropImage.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
dropContainer.addView(objectDropImage);
float newX, newY;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
newX = event.getRawX() + dX;
newY = event.getRawY() + dY;
if ((newX <= 0 || newX >= screenWidth-view.getWidth()) || (newY <= 0 || newY >= screenHight-view.getHeight()))
{
break;
}
view.setX(newX);
view.setY(newY);
break;
}
return false;
}
});
}
break;
default:
break;
}
return true;
}
I simply want to touch and drag/move an object around on the screen.
I know there are plenty of given codes out there, using surface holder and imageview matrix. But these codes are not well notated, and I don't know what is going on. I want to just copy and paste them into my own code.
I know there is this documentation on Android Dev website that teaches you how to drag and scale. But for dragging, it only gives an example for the onTouchEvent(), but I don't how I can integrate this method into my MainActivity.java and activity_main.xml files. Specically, in the code snippet, there are mPosX and mPosY, and I don't know how to use these global variables.
I tried creating a new class extending View class and put onTouchEvent().
I know you can use onDraw() and override it to utilize mPosX and mPosY to redraw the object every time your finger moves, but how exactly i don't know. I need some example codes implementing onDraw().
This is the code snippet I am talking about:
// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = MotionEventCompat.getActionMasked(ev);
switch (action) {
case MotionEvent.ACTION_DOWN: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
// Remember where we started (for dragging)
mLastTouchX = x;
mLastTouchY = y;
// Save the ID of this pointer (for dragging)
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
break;
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex =
MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
// Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
// Remember this touch position for the next move event
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
}
break;
}
}
return true;
}
Create a class MoveViewTouchListener
public class MoveViewTouchListener
implements View.OnTouchListener
{
private GestureDetector mGestureDetector;
private View mView;
public MoveViewTouchListener(View view)
{
mGestureDetector = new GestureDetector(view.getContext(), mGestureListener);
mView = view;
}
#Override
public boolean onTouch(View v, MotionEvent event)
{
return mGestureDetector.onTouchEvent(event);
}
private GestureDetector.OnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener()
{
private float mMotionDownX, mMotionDownY;
#Override
public boolean onDown(MotionEvent e)
{
mMotionDownX = e.getRawX() - mView.getTranslationX();
mMotionDownY = e.getRawY() - mView.getTranslationY();
Log.d("imageview"," down");
return true;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
{
mView.setTranslationX(e2.getRawX() - mMotionDownX);
mView.setTranslationY(e2.getRawY() - mMotionDownY);
if((distanceX==0)&&(distanceY==0))
{
Log.d("imageview"," zoomed");
}
return true;
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
Log.d("imageview"," tapped");
return true;
}
};
}
In activity call:
ImageView imageView= findViewById(R.id.imageView);
imageView.setOnTouchListener(new MoveViewTouchListener(imageView));
I have a library which handles onTouchListener Events for a ImageView.
view.setOnTouchListener(new View.OnTouchListener() {
int lastAction;
float dX = 0;
float dY = 0;
int DELTA = 50;
private static final int MAX_CLICK_DURATION = 200;
private long pressStartTime;
#Override
public boolean onTouch(View view, final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
pressStartTime = System.currentTimeMillis();
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
lastAction = MotionEvent.ACTION_DOWN;
break;
case MotionEvent.ACTION_UP:
if (lastAction == MotionEvent.ACTION_DOWN) {
break;
}
break;
case MotionEvent.ACTION_MOVE:
lastAction = MotionEvent.ACTION_MOVE;
break;
}
return false;
}
});
And then once installing the library into my app i also wanted to set my own onTouchEvent for that ImageView.
view.setOnTouchListener(new new View.OnTouchListener(){});
The problem is that only the library touchListener event gets called and the app one is lost/neglected. If I remove the library then the app touch event gets called. How can I make it so that both the library and the app touchListeners are called?
i have a problem with an OnSwipeImageListener (implements OnTouchListener). I use the OnSwipeImageListener in two activities.
On the one activitiy on the ImageView is the OnTouchListener and an OnClickListener and on the other activity on the ImageView is only the OnTouchListener.
If i change return v.onTouchEvent(event) to true under the MotionEvent.ACTION_DOWN then the OnClickListener on the first activity doesn't work and in this way the Swipe of ImageView on the second activity doesn't work. I debugged some times and see that MotionEvent.ACTION_UP is never called.
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
dX = event.getX();
dY = event.getY();
return v.onTouchEvent(event);
case MotionEvent.ACTION_UP:
uX = event.getX();
uY = event.getY();
float deltaX = dX - uX;
float deltaY = dY - uY;
// horizontal
if(Math.abs(deltaX) > MIN_DISTANCE) {
//Left to right
if(deltaX < 0) {
this.onLeftToRight();
return v.onTouchEvent(event);
} else if (deltaX > 0) {
this.onRightToLeft();
return v.onTouchEvent(event);
}
else {
//Swipe too short
return v.onTouchEvent(event);
}
}
// vertical
if (Math.abs(deltaY) > MIN_DISTANCE) {
if(deltaY < 0) {
this.onTopToBottom();
return v.onTouchEvent(event);
} else if (deltaY > 0) {
this.onBottomToTop();
return v.onTouchEvent(event);
}
else {
//Swipe too short
return v.onTouchEvent(event);
}
}
}
return v.onTouchEvent(event);
}
If you want to get the ACTION_UP, you should hijack the ACTION_DOWN.
Instead of returning "v.onTouchEvent(event)", return "true" when you are just handling the ACTION_DOWN.