I'm animating a View that shows if i slide up, and hide if i slide down.
The problem is that only work when sliding up. If i slide down, the view move along with my finger but when i release the touch, it goes up again.
Here is the code that i use for the animation & slide.
v.setY(480);
v.setVisibility(View.VISIBLE);
v.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
if (action == MotionEvent.ACTION_DOWN){
v.animate().translationY(480);
return true;
} else if (action == MotionEvent.ACTION_UP) {
v.animate().translationY(0);
return true;
}
return true;
}
});
What am i missing?
ACTION_UP and ACTION_DOWN don't mean direction.
ACTION_DOWN means an event when you have just touched the screen.
ACTION_UP means an event when you have just released your finger.
Related
OnTouchEvent is being fired after the second time touch; yet, I want it to be fired after the first touch itself.
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
//too avoid touch being detected continuously
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (Function.system[5] == "Gravity: on") {
//some action...
}
}
return super.onTouchEvent(event)
}
You need to tell Android to continue to respond to touch events. Returning true let's you capture events from action down , action move and then action up.
Please add the return true for each event
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
//too avoid touch being detected continuously
if (event.getAction() == MotionEvent.ACTION_DOWN) {
}
return true;
}
Please try and seee if this works for you
i attached a ontouch listener to my listview so i can drag the listview left to right. While im dragging the listview im able to scroll it as well. How can i disable the listview scroll while i'm dragging it.
listView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
return true; // Indicates that this has been handled by you and will not be forwarded further.
}
return false;
}
});
OR
listView.setScrollContainer(false);
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);
}
I have a custom listview in my android application. When a user press an item in the list I want to change the background color of the pressed item. This is the code for that behaviour:
tempView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
isDown = false;
tempView.setBackgroundColor(Color.parseColor("#f47920"));
}
if (event.getAction() == MotionEvent.ACTION_UP) {
tempView.setBackgroundResource(R.drawable.list_selector_focused);
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
tempView.setBackgroundResource(R.drawable.list_selector_focused);
}
return false;
}
});
But when I "Fling" my finger over the screen to scroll the listview, an item is also marked, and the "pressed" color will be static. How can I avoid this?
MotionEvent.ACTION_UP will not be caught unless you return true from onTouch() to inform Android system that you handled the whole touch event.
I am writing a simple code on ontouchevent..the code is
class MyTouchListener implements View.OnTouchListener{
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction()==MotionEvent.ACTION_DOWN)
{ Log.i(TAG, "^^^^^^^^^^^ACTION DOWN^^^^^^^^^^^^");
}
else if(event.getAction()==MotionEvent.ACTION_UP)
{
Log.i(TAG, "^^^^^^^^^^^ACTION UP^^^^^^^^^^^^");
}
}
while i pressed the screen it prints ^^^^^ACTION DOWN^^^^^
But when I released the screen it does not print ^^^^^^ACTION UP^^^^^^....
means MotionEvent.ACTION_UP fails..why this is so??
Try with MotionEvent.ACTION_CANCEL
#Override
public boolean onTouch(final View view, final MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
setColorFilter(Color.argb(155, 185, 185, 185));
}
else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
setColorFilter(Color.argb(0, 185, 185, 185));
}
return false;
}
or add a log in your ontouch method
Log.d("tag", "motionEvent=" + motionEvent);
well ACTION_DOWN is happening just once after that action move should be happening and in the and action up...
but there is one problem , for example if you have a touchable area of 48dip x 48dip and if you touch that area and move you finger away (while dragging) I mean you press and you drag you finger away from the touchable area than action up will not happen !!!
Action up will happen only in case when you take your finer of the screen but you are still in the touchable area. I hope you understand me what I am trying to say.
if you want mouse up to happen that touch the touchable area do not drag you finger away and take you finger away from the screen, you know just like taping then the up event will happen