drag and drop textview - android

I have to drag and i am not able to drag it perfectly:
The issues are:
1) I have to drag two to three times to bring that to desired position.Hence textview is not following the finger movement smoothly.
2)If i move textview in upward direction its only going downwards.
I am providing the code of textview on touch event.Please help.Thanks in advance.
final TextView t=(TextView)findViewById(R.id.textView4);
t.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View v, MotionEvent me) {
// TODO Auto-generated method stub
float x = me.getX();
float y = me.getY();
if (me.getAction() == MotionEvent.ACTION_DOWN) {
status = START_DRAGGING;
}
if (me.getAction() == MotionEvent.ACTION_UP) {
status = STOP_DRAGGING;
t.setPadding((int) me.getX(), (int) me.getY(), 10, 10);
Log.i("Drag", "Stopped Dragging");
} if (me.getAction() == MotionEvent.ACTION_MOVE) {
if (status == START_DRAGGING) {
System.out.println("Dragging");
t.setPadding((int) me.getX(), (int) me.getY(), 10, 10);
t.invalidate();
}
}return true;
}});

Perhaps you are not moving Views the way they are supposed to, in Android?
setPadding() is not the best way to go about it.
Here is an alternative way of Drag and Drop for Views

Related

The ViewGroup can still scroll when I set it can scroll when getScrollX()>=0

Here is my Code:
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x=(int)event.getX();
if (action == MotionEvent.ACTION_DOWN) {
mLastX = x;
mStart = getScrollX();
} else if (action == MotionEvent.ACTION_MOVE) {
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
Log.d(TAG, "onTouchEvent: getScrollX-->"+getScrollX());
int dx=mLastX-x;
if(getScrollX()>=0&&getScrollX()<mSlideViewWidth){
scrollBy(dx,0);
}
mLastX=x;
} else if (action == MotionEvent.ACTION_UP) {
mEnd = getScrollX();
if(getScrollX()<0){
mScroller.startScroll(getScrollX(),0,-mEnd,0);
}
}
postInvalidate();
return true;
}
When I slide the screen to the left ,ScrollX is less than 0,so the scrollby method should not be called.But when I slide the screen to the left, ViewGroup can still move a short distance to the left.
I guess the solution might have something to do with the getScrollX method.
But because I've only recently learned Custom view,I hava no idea to deal with this.
I am searching for a long time on net. But no use. Please help or try to give some ideas how to achieve this.Thanks in advance.
Problem description gif
Its a animation problem, or you have an translate effect still going before the last scrollX OR probably your case, the dx value + getScrollX() in your last iteration is bigger than 0, your solution is to see if you near the edge and adjust dx to be the exact amount of -getScrollX() if it's bigger.
int dx=mLastX-x;
if (dx < -getScrollX()) dx = -getScrollX(); //not tested but should work
if(getScrollX()>=0&&getScrollX()<mSlideViewWidth)
scrollBy(dx,0);

How to implement swipe and hold gesture in Android?

I am trying to implement a "swipe and hold" gesture in Android where the user swipes from a point on the left to another point on the right, then continues to hold at the right point until a server-side action is complete. The idea being that if the user lets go of the hold, the server-side action will be cancelled.
I've been trying to go about this the following way but have encountered an issue when getting to the hold part of the gesture. What I'd like to have happen is that when the user reaches point B on the right, the ACTION_MOVE is somehow converted into an ACTION DOWN for the view on the right and from then on, as long as the event ACTION_DOWN continues the gesture is valid, but if the user lets go or leaves the view area, it is invalid. So the question is, is it possible to chain the ACTION_MOVE from left to right into a "hold" gesture once the user reaches point B on the right? I've tried adding an onTouch to point B after the swipe, but the only way that works is if the user lets go of the swipe, then presses point B again. Will this be possible, or should I go about this a different way, such as drag and drop?
Point A and B as found below are currently image views, but that's more placeholder than anything.
private boolean mValidGesture = false;
Rect outRect = new Rect();
int[] location = new int[2];
private boolean isViewInBounds(View view, int x, int y){
view.getDrawingRect(outRect);
view.getLocationOnScreen(location);
outRect.offset(location[0], location[1]);
return outRect.contains(x, y);
}
...
mPointA.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int)event.getRawX();
int y = (int)event.getRawY();
if(event.getAction() == MotionEvent.ACTION_MOVE){
if (isViewInBounds(mPointB, x, y)) {
mPointB.dispatchTouchEvent(event);
Log.d(TAG, "onTouch ViewB");
Toast.makeText(MainActivity.this, "Swipe complete", Toast.LENGTH_SHORT).show();
//This is the part that happens only after you let go of the swipe :(
mPointB.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
mValidGesture = true;
Log.d(TAG, "Gesture: " + String.valueOf(mValidGesture));
return true;
case MotionEvent.ACTION_UP:
mValidGesture = false;
Log.d(TAG, "Gesture: " + String.valueOf(mValidGesture));
return true;
}
return false;
}
});
} else if(isViewInBounds(mPointA, x, y)){
Log.d(TAG, "onTouch ViewA");
}
}
// Further touch is not handled
return false;
}
});
You don't need to put touchListener on pointB. Try something like this:
boolean serverActionStarted = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int)event.getRawX();
int y = (int)event.getRawY();
if(event.getAction() == MotionEvent.ACTION_MOVE){
if (isViewInBounds(mPointB, x, y)) {
// TODO : swipe completed. Start server action
serverActionStarted=true;
}
}else if(event.getAction() == MotionEvent.ACTION_UP && serverActionStarted){
// TODO : cancel the server action
serverActionStarted = false;
}
So basically, when the user swipes from pointA to pointB, you start the server action and set a boolean serverActionStarted to true. After that, if ACTION_UP event occurs, with the severAction having started, you cancel the server action.

MotionEvent.ACTION_CANCEL is not triggered during onTouch

I am having this problem where ACTION_CANCEL is not triggered, I have implemented it in my other project and it's working fine. It seems that ACTION_UP is the only MotionEvent that is called after ACTION_DOWN. I wanted to trigger ACTION_CANCEL once my finger is not anymore in the view or outside the screen.
Sample scenario: I click on the view which is a LinearLayout btw, on ACTION_DOWN its background is changed to a "clicked/dimmed" version of the image and when ACTION_UP is triggered its background changes back to the default image only if the finger is within the LinearLayout. Now the problem is when I press it and kept my finger on the screen, and drag my finger outside the LinearLayout, ACTION_UP is still triggered where it shouldn't have.
Here's my code:
dimView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(final View view,
final MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
Log.d("TAG", "DOWN");
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
Log.d("TAG", "UP");
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
Log.d("TAG", "CANCEL");
return true;
}
return false;
}
});
where: dimView is a LinearLayout
I've been debugging this for a really long time and it bothered me a lot since this came up very randomly. I then tested my code on different devices and realized the API implementation changed with Android 4.2.
The expected behaviour and code work absolutely fine with Android 4.1.2 (tested on Galaxy Tab 2) but the bug you describe can be seen on a Nexus 7 (Android 4.2).
Apparently Android changed the way MotionEvents are handled in API 17.
One particular case when the bug does not occur is when the view is located in a GroupLayout under a ScrollView. When scrolling is possible the ACTION_CANCEL gets fired. However when no scrolling is possible the bug persists.
At first I tried combining an OnClickListener and OnTouchListener so that the last can handle just the animations but to no avail. Dispatching the Events from parents also doesn't work.
One workaround is to capture ACTION_MOVE events and check if the finger is located outside of the view's boundaries using v.getX() and v.getY() and comparing them to event.getX() and event.getY() respectably. A global boolean variable (isOutside) can be used to store the most current information. Before firing up the ACTION_UP you can check the latest state of isOutside and perform your animations and action accordingly. You can also return true or false depending on whether you captured the event or not.
Update: After digging a bit here i found this solution:
Android: Detect if user touches and drags out of button region? and compiled this code. The idea is the same except that it creates a rectangle and checks if the event boundaries are within the rectangle of the view.
someView.setOnTouchListener(new View.OnTouchListener() {
private Rect rect;
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d(TAG,"Touched: "+event.getAction());
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.d(TAG,"ACTION_DOWN");
animateImageButtonOnClick(v, event);
rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
}
if (event.getAction() == MotionEvent.ACTION_UP) {
Log.d(TAG,"ACTION_UP");
if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) {
Log.d(TAG,"ACTION_UP - outside");
animateImageButtonOnRelease(v, event);
} else {
Log.d(TAG,"ACTION_UP - inside");
// do your stuff here
}
}
if(event.getAction() == MotionEvent.ACTION_MOVE){
if(!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){
animateImageButtonOnReleaseWithLowDuration(v, event);
}
}
if (event.getAction() == MotionEvent.ACTION_CANCEL){
Log.d(TAG,"ACTION_CANCEL");
animateImageButtonOnRelease(v, event);
return true;
}
return true;
}
});
Override dispatchTouchEvent method maybe deal with it;
dimView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
// to call super touch method
return false;
}
});
#Override
public boolean dispatchTouchEvent(MotionEvent motionEvent) {
// TODO Auto-generated method stub
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
Log.d("TAG", "DOWN");
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
Log.d("TAG", "UP");
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
Log.d("TAG", "CANCEL");
return true;
}
return super.dispatchTouchEvent(motionEvent);
}

Drag and Drop a Button in Android

I need some tutorials on Drag and Drop a Button in Android. I mean, I have some buttons in a row and when I Long press any of the button than i can reposition the selected button in between my existing buttons and all other buttons moves aside.
Can anybody provide some nice tutorials or guides for this.
Thanks
Call below listener in button:
myOnTouchListener = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent me){
if (me.getAction() == MotionEvent.ACTION_DOWN){
oldXvalue = me.getX();
oldYvalue = me.getY();
}else if (me.getAction() == MotionEvent.ACTION_MOVE ){
LayoutParams params = new LayoutParams(v.getWidth(), v.getHeight(),(int)(me.getRawX() - (v.getWidth() / 2)), (int)(me.getRawY() - (v.getHeight())));
v.setLayoutParams(params);
}
return true;
}
};

Crop image ala Google Goggles

I'm trying to do some ROI (region of interest) selection in my app, but I donĀ“t know, how to create some kind of resizable (by fingers) rectangle like you can see in Google Goggles.
Can you help me? Is there any source code example?
My final solution is to draw and rectangle in the midle of a view and implement onTouchEvent() in my activity to set new corners coordinates like this:
#Override
public boolean onTouchEvent(MotionEvent me) {
if(SETTING_ROI == true){
if (me.getAction() == MotionEvent.ACTION_DOWN) {
START_DRAGGING = true;
myView.selectCorner((int) me.getRawX(), (int) me.getRawY()); // selecst nearest corner
}
if (me.getAction() == MotionEvent.ACTION_MOVE){
Log.d(TAG, "ACTION_MOVE");
myView.moveCorner((int) me.getRawX(), (int) me.getRawY()); // move selected corner continuously
}
if (me.getAction() == MotionEvent.ACTION_UP){
if (START_DRAGGING == true) {
START_DRAGGING = false;
myView.moveCorner((int) me.getRawX(), (int) me.getRawY()); // final selected corner move
}
}
}
return false;
}
Could you reuse code from the Gallery-Cropper?
The CropImage class source code is available here.

Categories

Resources