In our application we handle the events in button to record data.
So initially when i use setOnLongClickListener()
and setOnClickListener()
together with the same button, it work fine for us.
That means it will call both this listener base on the click and LongClick of the button. Now when i tried to use setOnTouchListener()
with the same button together with setOnLongClickListener()
and setOnClickListener()
then only OnTouch event is working, rest onclick and onLongclick event doesnt work.
Can anyone tell me why this happen and if possible explain me with an example.
The code i use is..
Button btnAdd=new Button(this)
btnAdd.setOnLongClickListener(this);
btnAdd.setOnClickListener(this);
btnAdd.setOnTouchClickListener(this);
public void onClick(View v)
{
//Statements;
}
public void onLongClick(View v)
{
//Statements;
}
public boolean onTouch(View v, MotionEvent e)
{
switch (e.getAction())
{
case MotionEvent.ACTION_DOWN:
{
//store the X value when the user's finger was pressed down
m_downXValue = e.getX();
break;
}
case MotionEvent.ACTION_UP:
{
//Get the X value when the user released his/her finger
float currentX = e.getX();
//MotionEvent x=MotionEvent.obtain((long) m_downXValue, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 1, 1, 1, 1,0, 0, 0, 0, 0);
// going forwards: pushing stuff to the left
if (m_downXValue > currentX && currentX < 0)
{
ViewFlipper vf = (ViewFlipper) findViewById(R.id.flipview);
vf.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_left));
vf.showNext();
}
// going backwards: pushing stuff to the right
if (m_downXValue < currentX && currentX > 100)
{
ViewFlipper vf = (ViewFlipper) findViewById(R.id.flipview);
vf.setAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_right));
vf.showPrevious();
}
if (m_downXValue == currentX)
{
onClick(v);
}
break;
}
}
return true;
}
According to the doc Handling UI Events,
onLongClick() - This returns a boolean to indicate whether you have consumed the event and it should not be carried further. That is, return true to indicate that you have handled the event and it should stop here; return false if you have not handled it and/or the event should continue to any other on-click listeners.
And above all about onTouch:
onTouch() - This returns a boolean to indicate whether your listener consumes this event. The important thing is that this event can have multiple actions that follow each other. So, if you return false when the down action event is received, you indicate that you have not consumed the event and are also not interested in subsequent actions from this event. Thus, you will not be called for any other actions within the event, such as a finger gesture, or the eventual up action event.
Indeed, depending on the event, you have to return the right value.
You have to return false instead of true in OnTouch(View v,MotionEvent event) function so that other listeners on the control remains active.
Seems like you have reference problem. Try to set click, long click and touch listener like this:
btnAdd.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
btnAdd.setOnLongClickListener(new Button.OnLongClickListener(){
@Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
return false;
}
});
btnAdd.setOnTouchListener(new Button.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
});
When you need both click and touch events on the same view, use a GestureDetector. It can detect long presses as well.
I'm not sure this is what you're trying to achieve, as you set the onTouchListener for the button - but if what you want to achieve is a swipeable activity (e.g swipe the screen and the content of the screen changes) you could try letting your activity extend the class posted below and then implement the next()
and previous()
methods with what ever actions you want.
import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.SimpleOnGestureListener;
public abstract class SwipeActivity extends Activity {
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gestureDetector = new GestureDetector( new SwipeDetector() );
}
private class SwipeDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// Check movement along the Y-axis. If it exceeds SWIPE_MAX_OFF_PATH, then dismiss the swipe.
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// Swipe from right to left.
// The swipe needs to exceed a certain distance (SWIPE_MIN_DISTANCE) and a certain velocity (SWIPE_THRESHOLD_VELOCITY).
if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
next();
return true;
}
// Swipe from left to right.
// The swipe needs to exceed a certain distance (SWIPE_MIN_DISTANCE) and a certain velocity (SWIPE_THRESHOLD_VELOCITY).
if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
previous();
return true;
}
return false;
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
//TouchEvent dispatcher.
if (gestureDetector != null) {
if (gestureDetector.onTouchEvent(ev))
//If the gestureDetector handles the event, a swipe has been executed and no more needs to be done.
return true;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
protected abstract void previous();
protected abstract void next();
}
Here is how i solved a synchronisation with ontouch and onlongclick
Hope every body can figure out after looking at this code.
What happens is whenever a long press happens the touchlistener is set for a none listener and when the view is touched again the none listener sets the touchlistener of the view to its previous listener
LinearLayout.LayoutParams longpressLP = new LinearLayout.LayoutParams(100,100);
LinearLayout longpress = new LinearLayout(this);
longpress.setBackgroundColor(Color.GREEN);
//any layout you want to add your view in
mainlayout.addView(longpress,longpressLP);
final View.OnTouchListener buttontouch=new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN)
Toast.makeText(getApplicationContext(), "Touched Down", Toast.LENGTH_SHORT).show();
else
Toast.makeText(getApplicationContext(), "Touched", Toast.LENGTH_SHORT).show();
return false;//IMPORTANT
}
};
final View.OnTouchListener buttontouchnone=new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN)//IMPORTANT
{
v.setOnTouchListener(buttontouch);//IMPORTANT
v.dispatchTouchEvent(event);//IMPORTANT
Toast.makeText(getApplicationContext(), "ChangedListener", Toast.LENGTH_SHORT).show();
}
return false;//IMPORTANT
}
};
//set listeners
longpress.setOnTouchListener(buttontouch);
longpress.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "LongClick", Toast.LENGTH_SHORT).show();
v.setOnTouchListener(buttontouchnone);//IMPORTANT
return true;//IMPORTANT
}
});