How to Use View.Ontouchlistener Instead of Onclick

How to use View.OnTouchListener instead of onClick

The event when user releases his finger is MotionEvent.ACTION_UP. I'm not aware if there are any guidelines which prohibit using View.OnTouchListener instead of onClick(), most probably it depends of situation.

Here's a sample code:

imageButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){

// Do what you want
return true;
}
return false;
}
});

Is it possible to use OnClickListener and OnTouchListener at the same time for a button?

It depends on your requirement.

onTouch gives you Motion Event. Thus, you can do a lot of fancy things as it help you separate state of movement. Like:

ACTION_UP
ACTION_DOWN
ACTION_MOVE

On the other hand, onClick doesn't give you much except which view user interacts. onClick is a complete event comprising of focusing,pressing and releasing. So, you have little control over it. One side up is it is very simple to implement.

So, It is not necessary unless you want to mess up with your user. If you just want simple click event, go for onClick. If you want more than click, go for onTouch. Doing both will complicate the process.

how to use both Ontouch and Onclick for an ImageButton?

Try this, It may help you

No need to set onClick() method onTouch() will handle both the case.

package com.example.demo;

import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageButton;

public class MainActivity extends Activity {
private GestureDetector gestureDetector;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gestureDetector = new GestureDetector(this, new SingleTapConfirm());
ImageButton imageButton = (ImageButton) findViewById(R.id.img);

imageButton.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View arg0, MotionEvent arg1) {

if (gestureDetector.onTouchEvent(arg1)) {
// single tap
return true;
} else {
// your code for move and drag
}

return false;
}
});

}

private class SingleTapConfirm extends SimpleOnGestureListener {

@Override
public boolean onSingleTapUp(MotionEvent event) {
return true;
}
}

}

How to handle both OnTouchListener event and OnClickListener event

See, onClickListener won't work with onTouchListener. You will have to implement some logic to differentiate between click and drag in onTouchListener. I did something like this, code is in java but you can get an idea.

switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
x = motionEvent.getX();
y = motionEvent.getY();
return true;

case MotionEvent.ACTION_UP:
// PUT ON CLICK LOGIC HERE
break;
case MotionEvent.ACTION_MOVE:
if ((motionEvent.getX() - x) > 80 || (x - motionEvent.getX()) > 80
|| (motionEvent.getY() - y) > 50 || (y - motionEvent.getY()) > 60) {
view.startDrag(data, new View.DragShadowBuilder(view) {
@Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
shadowSize.set(view.getWidth(), view.getHeight());
shadowTouchPoint.set((int) motionEvent.getX(), (int) motionEvent.getY());
}
}, view, 0);
}
return true;

}

Android: Working with onTouch, onClick and onLongClick Together

Finally, I managed to achieve what I wanted. The solution is based on Viswanath's idea proposed above. Here is my code:

broItemView.setOnTouchListener(new View.OnTouchListener() {
private int deltaX;
private int deltaY;
private float initialTouchX;
private float initialTouchY;
private boolean isMoved;
private int lastTouchX;
private int lastTouchY;

@Override
public boolean onTouch(final View v, final MotionEvent event) {
ViewGroup vg = (ViewGroup) v.getParent();
draggedViewIndex = vg.indexOfChild(v);
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
boolean result = v.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
isMoved = false;
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) v
.getLayoutParams();

deltaX = (int) initialTouchX - params.leftMargin;
deltaY = (int) initialTouchY - params.topMargin;

lastTouchX = (int) initialTouchX;
lastTouchY = (int) initialTouchY;
Log.e(TAG, "ACTION_DOWN lasttouchX: " + lastTouchX);
Log.e(TAG, "ACTION_DOWN lasttouchY: " + lastTouchY);
new Handler().postDelayed(new Runnable() {

@Override
public void run() {
runOnUiThread(new Runnable() {

@Override
public void run() {
if (!isMoved
&& event.getAction() != MotionEvent.ACTION_UP) {
//perform LongClickOperation
}
}
});
}
}, 1000);
break;
}

case MotionEvent.ACTION_MOVE: {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) v
.getLayoutParams();

params.leftMargin = (int) initialTouchX - deltaX;
params.topMargin = (int) initialTouchY - deltaY;

v.setLayoutParams(params);

break;
}
case MotionEvent.ACTION_UP: {

if ((lastTouchX == (int) initialTouchX)
&& (lastTouchY == (int) initialTouchY)) {
isMoved = false;
} else if ((lastTouchX > (int) initialTouchX)) {
if (((lastTouchX - (int) initialTouchX) <= 10)) {
isMoved = false;
} else {
isMoved = true;
}
} else if ((lastTouchX < (int) initialTouchX)) {
if ((((int) initialTouchX - lastTouchX) <= 10)) {
isMoved = false;
} else {
isMoved = true;
}
} else if ((lastTouchY > (int) initialTouchY)) {
if (((lastTouchY - (int) initialTouchY) <= 10)) {
isMoved = false;
} else {
isMoved = true;
}
} else if ((lastTouchY < (int) initialTouchY)) {
if ((((int) initialTouchY - lastTouchY) <= 10)) {
isMoved = false;
} else {
isMoved = true;
}
} else {
isMoved = true;
}

if (!isMoved) {
//perform onClick operation
} else {
isMoved = false;
}
initialTouchX = 0;
initialTouchY = 0;
deltaX = 0;
deltaY = 0;
break;
}
default:
return result;
}
relBroCircle.invalidate();
return true;
}
});

In the ACTION_UP, I had to add additional checks to determine whether view actually moved or not because, I found that, ACTION_MOVE still called up even when user has simply clicked on the view. I have checked this separately, as I have mentioned Update 2 of my post. And, when I tested my code on a 10" Tablet, then, my onclick code never executed. So, to avoid this problem, I had to write those bunch of codes. But, I don't think its an elegant solution and seems hack to me. If anyone has better solution, then please advise so that I can update my code.

Set BOTH, android:onClick AND OnTouchListener

Yes you can use both onClick and onTouch on a same button, but OnTouch callback you'll get motionEvent like ACTION_MOVE, ACTION_UP , ACTION_DOWN etc, Don't forget to return false (Details)in onTouch callback. Please refer the below code

Button button = (Button) findViewById(R.id.button);
button.setOnTouchListener(new OnTouchListener() {

public boolean onTouch(View v, MotionEvent event) {
Log.d("test", "ontouch");
return false;
}
});
button.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
Log.d("test", "onclick");
}

});

Just do the operations you want to do in the call backs onTouch and onClick respectively.
Please NOte click is a action performed when user press the button and release but Touch will be taken when user presses it.

So on a single click the log will be like this. 1.ACTION_DOWN, 2.ACTION_UP 3. onClick

03-22 16:19:39.735: D/test(682): ontouch
03-22 16:19:39.735: D/test(682): ontouch
03-22 16:19:39.735: D/test(682): onclick

JAVA / Android - Ontouchstart instead of onClick

Use View.setOnToucListener(listener)

yourRelativeLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){

//Your stuff here
return true;
}
return false;
}
});


Related Topics



Leave a reply



Submit