Hello! Thank you for reading.
Based upon this answer, I integrated View dragging like so:
float dX, dY;
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
setX(event.getRawX() + dX);
setY(event.getRawY() + dY);
break;
default:
return false;
} return true;
}
However, the View's position relative to my finger is proportionally offset with the scale of the parent layout. In other words, when I start zooming in the layout, View dragging breaks.
I've been debugging for quite a bit and it seems that even knowing the parent layout scale (as, say, dScale), I can't use that value in a way that fixes the offset completely.
I cannot even reach a point where the distance between my finger and the View is constant.
To note that the issue is only observable when the parent's scale is not equal to 1.
.
Thank you very much for your help!
For further reference, this situation can be solved by applying the parent's scale to the getRawX() methods in both occurrences. I somehow hadn't tried that...
float dX, dY;
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX() / dScale;
dY = view.getY() - event.getRawY() / dScale;
break;
case MotionEvent.ACTION_MOVE:
setX(event.getRawX() / dScale + dX);
setY(event.getRawY() / dScale + dY);
break;
default:
return false;
} return true;
}
I'd also recommend putting the MOVE case first in the switch.
I suppose the reasoning behind this solution can be vaguely explained by "view positioning methods know how to handle scaling, touch callback methods don't".
Hope this will help some!
Related
I have an image and it moves to my finger position when I touch it, Everything is working but I want to know what these variables do.
Part of code
//I'm trying since the morning to understand what these variables do but I failed so can someone tell me why we put these variables?
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
Full code
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View view, MotionEvent event) {
if (view.getId() == R.id.img_view) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
view.setX(event.getRawX() + dX);
view.setY(event.getRawY() + dY);
}
}
return true;
}
dX and dY is a difference between top left corner of this view and touch point on this view - you are touching view somewhere in the middle of it, almost never on its edge (pixel on 0,0 coordinates). when ACTION_MOVE occurs then you are using setX/setY methods for changing position, which are setting position of this top left corner - for preserving feeling of dragging (no view jump, smooth drag) you have to add these initial difference. use Log.i(..) and observe Logcat tab in Android Studio, you will notice which value is responsible for which param of touch/view
So in my layout I have this ball which I want to drag around the screen. I tried using the onTouch() method, and these are my results:
1)((Button)findViewById(R.id.ball)).setY(event.getY());
((Button)findViewById(R.id.ball)).setX(event.getX());
This one is very glitchy for some reason. I try to move the ball and it just quickly goes back and forth between two different places.
2) ((Button)findViewById(R.id.ball)).setY(event.getRawY());
((Button)findViewById(R.id.ball)).setX(event.getRawX());
This one works a bit smoother, but when I start the movement the ball just teleports to some other place. It works fine except for that part where it "teleports"
What I want to achieve:
A normal drag movement of the ball where the ball is right beneath the finger (x and y coordinates of the ball match the x and y coordinates of the touch)
I can add screen recordings explaining the two cases above if needed
First make your activity implement View.OnTouchListener and import the requested method:
public class MyActivity extends AppCompatActivity implements View.OnTouchListener {}
Then change newly created onTouch method like below:
float dX, dY;
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
view.animate()
.x(event.getRawX() + dX)
.y(event.getRawY() + dY)
.setDuration(0)
.start();
break;
default:
return false;
}
return true;
}
and finally set this onTouch method to your view:
ball.setOnTouchListener(this);
I've created an OnTouchListener that will allow me to drag views around the screen. This works well, except for one problem:
My views resize instead of leaving the parent. They are in a RelativeLayout, which I suspect is contributing to the problem. They only resize when touching the right or bottom boundaries of my RelativeLayout.
I'm hoping there is a simple solution to this problem, (ideally not involving resizing the RelativeLayout), but I haven't found a solution yet.
Ideally, this solution would be applicable for all views, as I use this OnTouchListener for TextViews as well as ImageViews. I was hoping to find an XML solution. I'm assuming others have dealt with this issue??
PS: Before I post this..I've just remembered I believe there is a flag for hitting a RelativeLayout's border, so maybe I can apply negative margin to the TextView when that happens. Thoughts?
EDIT
Here is my OnTouchListener:
// Dragging functionality for all views and double tap to remove
// functionality for ImageViews
final OnTouchListener onTouchListener = new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
v.bringToFront();
//if(v instanceof android.widget.ImageView)
//mScaleDetector.onTouchEvent(event);
layoutParams = (LayoutParams) v.getLayoutParams();
switch (event.getActionMasked())
{
case MotionEvent.ACTION_DOWN:
// Where the user started the drag
pressed_x = (int) event.getRawX();
pressed_y = (int) event.getRawY();
if (v instanceof android.widget.ImageView)
{
curTime = System.currentTimeMillis();
if(curTime - prevTime <= DOUBLE_TAP_INTERVAL)
{
v.setVisibility(View.GONE);
}
prevTime = curTime;
}
case MotionEvent.ACTION_MOVE:
// Where the user's finger is during the drag
final int x = (int) event.getRawX();
final int y = (int) event.getRawY();
// Calculate change in x and change in y
dx = x - pressed_x;
dy = y - pressed_y;
// Update the margins
layoutParams.leftMargin += dx;
layoutParams.topMargin += dy;
v.setLayoutParams(layoutParams);
// Save where the user's finger was for the next ACTION_MOVE
pressed_x = x;
pressed_y = y;
break;
default:
break;
}
return true;
}
}
I am guessing this means making the whole screen touchable. How exactly is that done?
and secondly calculating if an X,Y is within the EditText.
override the onTouchEvent in the activity you want to implement this....and get the X, Y co-ordinates using event.getX() and event.getY()
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
}
return false;
}
but i suggest you must search thoroughly before posting a question.
can any one help me how to drag and drop the text view on entire image view. i found from this drag n drop textview in android here the text view is static, in my app textview and image view's are dynamically change. `#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Remember our initial down event location.
startX = event.getRawX();
startY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
float x = event.getRawX();
float y = event.getRawY();
// Calculate move update. This will happen many times
// during the course of a single movement gesture.
scrollByX = x - startX; //move update x increment
scrollByY = y - startY; //move update y increment
startX = x; //reset initial values to latest
startY = y;
invalidate(); //force a redraw
break;
}
return true; //done with this event so consume it
}
i wright this code, but it's not working properly.
You can always change the image and text of existing view programatically using setText sort of methods.
There are many drag and drop tutrials if you google it. strongly suggest you try them out.
Basically what you do is implement a OnTouchListener on the TextView like
textview.setOntouchListener(listen);
OnTouchListener onThumbTouch = new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
switch(v.getId())
{
case R.id.slider_thumb_id:
{
switch(event.getAction())
{
case MotionEvent.ACTION_MOVE:
{
}
case MotionEvent.ACTION_UP:
{
}
}
break;
}
}
return true;
}
};
Here from the event attribute you get the value of x and y and the touch event and
use that to alter the position of the textview. I did it by add add/subtracting the margin values.
EDIT:
This is what I did to update the position of my view
Look event.getRawY(); is going to give you the distance from the parent view. So if I get event.getRawY() = 50. I know I need the text view to be 50 pixels from the top.
LinearLayout.LayoutParams iconParams = (LinearLayout.LayoutParams)
v.getLayoutParams();
iconParams.topMargin = 50;
v.setLayoutParams(iconParams);
So now the view that i selected is 50 px from the top of the parent view.