I use onTouch as it is the best and more modifiable than for an instance onClick. It is a custom view that is being touched that I want to respond with action, and I have allready limited so you can't just touch and it does it over and over. Now I need it to limit the amount of simountanious taps.
EDIT:
#Override
public boolean onTouch(View v, MotionEvent event) {
lines++;
return false;
}
I have prevented constant action, but not the possibility to press with more than 1 finger, so that if you tap with more the rest of the fingers get ignored
There are several ways to do it.
best for you may be limit it inside in your overrided onTouch event.
if(event.getPointerCount() > 1) {
System.out.println("Multitouch detected!");
return true;
}
else
return super.onTouchEvent(event);
Another option is set attribute android:splitMotionEvents = false in your xml file.
I am currently trying to detect an ongoing touch event in my Android app.
In detail I want to recognize within a fragment whether the user touches any part of the app's screen.
Android's OnTouchListener works as expected except if the touch event lasts longer than a few seconds without moving.
For example the first 1-2 seconds of touch are being detected but everything after won't.
Is there something like an "OnPressListener" or a workaround?
If it's a well defined gesture you are trying to detect, have a look at GestureDetector.
http://developer.android.com/reference/android/view/GestureDetector.html
You can use
aButton.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View arg0) {
Toast.makeText(getApplicationContext(), "Long Clicked " ,
Toast.LENGTH_SHORT).show();
return true; // <- set to true
}
});
on your aButton and if you are using API < 19 you have to add
android:longClickable="true"
Attribute to your aButton in layout xml.
I finally found it out.
The solution is to use a simple OnTouchListener:
private boolean pressed = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
pressed = true;
} else if ((action == MotionEvent.ACTION_UP)
|| (action == MotionEvent.ACTION_CANCEL)) {
pressed = false;
}
return true;
}
Is there any way to know when user touch the screen?
Actually i want to know user is using the phone or not. And i thought if user doesn't touch the screen he/she doesn't use the phone. I've already goggled it but i couldn't find any proper things, that's why i want to ask this question in here, and i couldn't find any similar question in here.
I find some code like this :
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return super.onTouchEvent(event);
}
but i don't know how to use properly.
thanks in advance.
You can check the last touch of screen using
System.curTimeMillis();
And use
long lastTouchTime;
#Override
public boolean onTouchEvent(MotionEvent event) {
lastTouchTime = System.curTimeMillis();
return true;
}
Or you can check is screen touched now or not :
boolean isScreenTouchedNow;
#Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN :
isScreenTouched = true;
break;
case MotionEvent.ACTION_UP:
isScreenTouched = false;
break;
}
return true;
}
public boolean isScreenTouchedNow()
{
return isScreenTouched;
}
Does anyone have any idea why getPressure() returns always 0.4 and getSize() returns 0.12...?
Code snippet:
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
System.out.println(event.getPressure());
System.out.println(event.getSize())
return true;
}
I think getPressure might not work, because there is no any physical functionality. But I can't figure out why getSize doesn't work?
TF300TG is android4.0, in Settings->Developer Options, check the "Pointer Location".
Could it be that these are the values generated at the very first part of the motion event only?
Try outputting the values on touch MOVE, as this is where the shape normally changes. This should give you some variation.
#Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction())
{
case MotionEvent.ACTION_MOVE:
System.out.println(event.getPressure());
System.out.println(event.getSize());
break;
}
return true;
}
My class extends View and I need to get continuous touch events on it.
If I use:
public boolean onTouchEvent(MotionEvent me) {
if(me.getAction()==MotionEvent.ACTION_DOWN) {
myAction();
}
return true;
}
... the touch event is captured once.
What if I need to get continuous touches without moving the finger?
Please, tell me I don't need to use threads or timers. My app is already too much heavy.
Thanks.
Use if(me.getAction() == MotionEvent.ACTION_MOVE). It's impossible to keep a finger 100% completely still on the screen so Action_Move will get called every time the finger moves, even if it's only a pixel or two.
You could also listen for me.getAction() == MotionEvent.ACTION_UP - until that happens, the user must still have their finger on the screen.
You need to set this properties for the element
android:focusable="true"
android:clickable="true"
if not, just produce the down action.
Her is the simple code snippet which shows that how you can handle the continues touch event. When you touch the device and hold the touch and move your finder, the Touch Move action performed.
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
if(isTsunami){
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Write your code to perform an action on down
break;
case MotionEvent.ACTION_MOVE:
// Write your code to perform an action on contineus touch move
break;
case MotionEvent.ACTION_UP:
// Write your code to perform an action on touch up
break;
}
}
return true;
}
Try this. It works to me:
public static OnTouchListener loadContainerOnTouchListener() {
OnTouchListener listener = new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
LinearLayout layout = (LinearLayout)v;
for(int i =0; i< layout.getChildCount(); i++)
{
View view = layout.getChildAt(i);
Rect outRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
if(outRect.contains((int)event.getX(), (int)event.getY()))
{
Log.d(this.getClass().getName(), String.format("Over view.id[%d]", view.getId()));
}
}
}
Remember: the listener you´ll set must be a container layout (Grid, Relative, Linear).
LinearLayout layout = findViewById(R.id.yourlayoutid);
layout.setOnTouchListener(HelperClass.loadContainerOnTouchListener());
This might help,
requestDisallowInterceptTouchEvent(true);
on the parent view, like this -
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
view.getParent().requestDisallowInterceptTouchEvent(true);
switch(motionEvent.getAction()){
}
return false;
}
I was making a game with a custom view used as a thumb control. . . here is what I did
float x = 0, y = 0;
#Override
public boolean onTouchEvent(MotionEvent event) {
x = event.getX();
y = event.getY();
// handle touch events with
switch( event.getActionMasked() ) {
case MotionEvent.ACTION_DOWN :
if(cont)
{
// remove any previous callbacks
removeCallbacks(contin);
// post new runnable
postDelayed(contin, 10);
}
invalidate();
return true;
case MotionEvent.ACTION_MOVE :
if(!cont && thumbing != null)
{
// do non-continuous operations here
}
invalidate();
return true;
case MotionEvent.ACTION_UP :
// set runnable condition to false
x = 0;
// remove the callbacks to the thread
removeCallbacks(contin);
invalidate();
return true;
default :
return super.onTouchEvent(event);
}
}
public boolean cont = false;
// sets input to continuous
public void set_continuous(boolean b) { cont = b; }
public Runnable contin = new Runnable()
{
#Override
public void run() {
if(x != 0)
{
// do continuous operations here
postDelayed(this, 10);
}
}
};
A quick note however, make sure in your main activity that is calling this view removes the callbacks manually via the onPause method as follows
#Override
protected void onPause() {
if(left.cont) left.removeCallbacks(left.contin);
if(right.cont) right.removeCallbacks(left.contin);
super.onPause();
}
That way if you pause and come back touch events aren't being handled twice and the view is free from it's thread's overhead.
** tested on Samsung Galaxy S3 with hardware acceleration on **
All these answer are partially correct but they do not resolve in the right way the problem.
First of all, for everyone out there that decide to track when the event is ACTION_MOVE. Well that works only guess when? When user move his finger, so could if you decide to implement a custom thumb control is okay but for a normal custom button that's not the case.
Second, using a flag inside ACTION_DOWN and check it in ACTION_UP seems the logic way to do it, but as Clusterfux find out if you implement a while(!up_flag) logic you get stuck into troubles ;)
So the proper way to do it is mentioned here:
Continuous "Action_DOWN" in Android
Just keep in mind that if the logic you're going to write during the continuous press has to modify the UI in some way, you have to do it from the main thread in all the other cases it's better use another thread.
You can use the below code snippet as a reference in which I used the background to detect if the screen is held or not...
Main_Layout.setOnTouchListener(new View.OnTouchListener() {
#SuppressLint("ResourceAsColor")
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
Main_Layout.setBackgroundColor(R.color.green);
event.setAction(MotionEvent.ACTION_DOWN);
break;
default:
Main_Layout.setBackgroundColor(R.color.blue);
break;
}
return false;
}
});