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
How to Keep the Spaces at the End And/Or at the Beginning of a String
How to Add New Column to Android SQLite Database
Set Span for Items in Gridlayoutmanager Using Spansizelookup
How to Take Camera Capture Without a Preview from a Service or Thread
Open Soft Keyboard Programmatically
Intent to Launch the Clock Application on Android
System.Exit(0) Doesnt Close All My Activities
Passing String Array Between Two Class in Android Application
How to Change the Launcher Logo of an App in Android Studio
Update Listview Dynamically with Adapter
How to Get Color-Int from Color Resource
How to Attach the Android Support Library Source in Eclipse
Livedata Update on Object Field Change
Android: How to Change Checkbox Size
Programmatically Obtain the Android API Level of a Device
Android: Using Simplecursoradapter to Get Data from Database to Listview