detecting a long press and press - java

in this function,I want to achieve “if is long press,return flag=true,else open tile”.`
public boolean onTouchEvent(MotionEvent event) {
int x=(int)event.getX();
int y=(int)event.getY();
long DownTime = event.getDownTime();
long UpTime = event.getEventTime();
long longPresstouch = UpTime - DownTime;
int idxX=(x-mine.x)/mine.tileWidth;
int idxY=(y-mine.y)/mine.tileWidth;
if(longPresstouch > longTouchTime)
{
if(x>=mine.x&&y>=mine.y&&x<=(mine.mapWidth+mine.x)&&y<=(mine.y+mine.mapHeight)) {
mine.setflag(new Mine.Point(idxX, idxY), true);
invalidate();
}
}
else if(event.getAction()==MotionEvent.ACTION_DOWN){
if(x>=mine.x&&y>=mine.y&&x<=(mine.mapWidth+mine.x)&&y<=(mine.y+mine.mapHeight)) //in tile or out tile
{
mine.open(new Mine.Point(idxX,idxY),isFirst);
isFirst=false;
if(mine.tile[idxY][idxX].value==-1)
{
mine.isDrawAllMine=true;
new AlertDialog.Builder(context)
.setCancelable(false)
.setMessage("GameOver,你踩到地雷啦!")
.setPositiveButton("再来一局", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
mine.init();
isFalse=true;
isFirst=true;
invalidate();
}
})
.setNegativeButton("退出游戏", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
})
.create()
.show();
}
if(isFalse)
{
isFalse=false;
invalidate();
return true;
}
logic();
invalidate();
}
}
return true;
}
`
but It is not working when I long press the tile. It is executing “open tile”.
How to correct the function? I am a beginner. Maybe this is a very simple question,but this has already perplexed me for a long time.

Every Android components that extend android.view.View will have these 2 methods.
View.setOnClickListener() If you do a click.
View.setOnLongClickListener() If you do long click. Make sure it's View.isLongClickable() returns true, or set it by calling View.setLongClickable(true).

Because you're reacting to the down and showing the dialog. Since you're reacting to the down event immediately, you never wait to see if its a long press. This is why touch events in android generally happen on the up event- so you can figure out if the touch is going to be a press, long press, gesture, etc.
Also, as another poster said, click and long clock are built in events. No reason to write an onTouchEvent unless you want to capture more complex behavior.

Calculate the time difference between ACTION_DOWN and ACTION_UP. If time difference is greater than 1000 ms return true else open the tile.

Related

How to constantly update a Text View

I'm trying out making an app using Android Studio and I want to constantly update a text view.
I at first thought I should use a loop but that ended up not even running for some reason.
TextView amount = findViewById(R.id.amountTextView);
final SeekBar seekBar = findViewById(R.id.seekBar);
int p = seekBar.getProgress() + 1;
amount.setText(String.valueOf(p));
});
}
}
With this method it doesn't update the results text view. I would like it to constantly update the text view so it shows what number the seek bar is on.
You will need an event for update the state of SeekBar and TextView, in this case I user a Handler(android.os) for update the views each 100 milliseconds of time, but you can use another event like the load of a web service or another.
In your case, it doesn't update because you just update the state of variable, but never update the state of seekbar, that is the reason it will never increment the current state.
private void startLoopUntilEnd() {
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
#Override
public void run() {
int progress = seekBar.getProgress();
textView.setText(String.valueOf(progress));
progress++;
seekBar.setProgress(progress);
startLoopUntilEnd();
}
};
if (currentState <seekBar.getMax()){
handler.postDelayed(runnable,100);
}
}
You can call this method from onCreate in case of Activity or onResume in case of Fragment and after it will go until the SeekBar is complete recursively.
If you want to change the max of seekBar, you can set it in xml or in code.
Use onSeekBarChangeListener:
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
amount.setTextprogress);
}
});

How to properly set custom long click listener?

I'm trying to set my own long click listener on Unlock button. Whenever I press the Unlock button it summarize duration and I can unlock permanently clicking.
Unlock.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(final View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Unlock.setText("Press to unlock");
isLongPress = true;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (isLongPress) {
Unlock();
}
}
}, longClickDuration); //amount of time of long click
} else if (event.getAction() == MotionEvent.ACTION_UP) {
Unlock.setText("Unlock");
isLongPress = false;
}
return true;
}
});
}catch (Exception e) {
// TODO: handle exception
}
}
If you want to just handle long clicks consider using the following code:
Unlock.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
your code
}
});
But if the Unlock(); should be invoked after a certain (customizable) amount of time, you should measure this time in MotionEvent.ACTION_UP handler. As #Attaullah Khan said, use SystemClock.elapsedRealtime() system timer to correctly count number of milliseconds at two moments (when button was pressed and released) and if the time is greater than longClickDuration then invoke Unlock
The handler.postDelayed that you call in MotionEvent.ACTION_DOWN handler just invokes a check of pressed state after longClickDuration interval and if your button gets suddenly pressed at that moment, the verification passes that is not correct

Android apps how to fire long press event in video view

I have survey about this subject in a day.
What I mean is how to show toast when tapping the Videoview for a while.
Below is what I've found,
Android: Why can't I give an onClickListener to a VideoView?
detect double tap (Double click) or long click in a videoview
But these really can't solve my problem.I really don't know what has happend?
And is there any function can fire up long pressing event in the video view?
here's my code
these two event really can't work.
mVideoView.setOnLongClickListener(new OnLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
final int arg2, long arg3) {
Log.e("devon","onitemlongclick");
return true;
}
#Override
public boolean onLongClick(View v) {
Log.e("devon","onLongClick");
return true;
}
});
need help !!!thanks!
add OnLongClickListener in your setupViewComponent call
try using onTouch
try attaching the OnLongClickListener to the videoview's surface
try wrapping the videoview with a transparent imageview/something that grabs focus, and use that as your 'touching pad'
post logcat.
This is a sample example on how to create your own TouchListsners for managing Click and LongClick on VideoView. In this example I pass to the listeners the idex of the data clicked and the index of the view (in behind I have several VideoView in arrays maps to data list, like in an Adapter)
/**
* Simple OnTouchListenerIndexed with Indexes for VideoView ClickListeners
* You have to handle longClick and click by yourself
*/
private abstract class OnTouchListenerIndexed implements OnTouchListener {
private static final int LONG_CLICK_DURATION=600;//in millis
int dataIndex = INDEX_NOT_DEFINED;
int imageViewIndex = INDEX_NOT_DEFINED;
long timeActionDown;
AtomicBoolean stillNotConsumed=new AtomicBoolean(true);
AtomicBoolean actionDone=new AtomicBoolean(false);
public OnTouchListenerIndexed(int dataIndex, int imageViewIndex) {
this.dataIndex = dataIndex;
this.imageViewIndex = imageViewIndex;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
timeActionDown=System.currentTimeMillis();
stillNotConsumed.set(true);
actionDone.set(false);
//launch LongClick in 1s
v.postDelayed(new Runnable() {
#Override
public void run() {
if(stillNotConsumed.get()){
stillNotConsumed.set(false);
actionDone.set(true);
onLongTouch(dataIndex, imageViewIndex);
}
}
},LONG_CLICK_DURATION);
//consumed
return true;
}else if(event.getAction() == MotionEvent.ACTION_UP){
long timeActionUp=System.currentTimeMillis();
stillNotConsumed.set(false);
if(actionDone.get()){
//do nothing
return true;//you have consumed it
}else {
actionDone.set(true);
//Check Click or LongClick
if (timeActionUp - timeActionDown > LONG_CLICK_DURATION) {
//une seconde plus tard
return onLongTouch(dataIndex, imageViewIndex);
} else {
return onTouch(dataIndex, imageViewIndex);
}
}
}else{
//don't consume it
return false;
}
}
public abstract boolean onTouch(int dataIndex, int imageViewIndex);
public abstract boolean onLongTouch(int dataIndex, int imageViewIndex);
}

Custom AlertDialog.Builder class in android won't show

I'm currently writing a program that will use the Geocoder to search for possible GeoPoints of a city search. I then take the geopoints and add it to a map as overlays, the user can then click the overlay, and an alert dialog will pop up to ask if he/she is sure that this is the right one.
I couldn't figure out a way to get the alert dialog to work like swing where after the user clicks yes or no, I can retrieve the answer. So I extended the AlertDialog.Builder class like so, which also happens to be a Dialog.OnClicklistener
public class MyAlertDialog extends AlertDialog.Builder implements DialogInterface.OnClickListener{
final static int positiveMessage = 1;
final static int negativeMessage = 0;
final static int neutralMessage = -1;
private int myMessage;
public MyAlertDialog(Context activity) {
super(activity);
}
#Override
public void onClick(DialogInterface dialog, int which) {
if(which == dialog.BUTTON_POSITIVE){
myMessage = positiveMessage;
}
else if(which == dialog.BUTTON_NEGATIVE){
myMessage = negativeMessage;
}
else{
myMessage = neutralMessage;
}
}
public int getMessage() {
return myMessage;
}
and I implement it like so
protected boolean onTap(int index) {
OverlayItem item = overlays.get(index);
MyAlertDialog dialog = new MyAlertDialog(ctx);
dialog.setTitle(item.getTitle());
dialog.setMessage("Is this the " + item.getTitle()
+ " you're looking for?");
dialog.setPositiveButton("Yes",null);
dialog.setNegativeButton("Cancel", null);
dialog.show();
if(dialog.getMessage()== MyAlertDialog.positiveMessage){
//do some stuff
But for some reason the dialog wont show until after the method has returned, so it never does the stuff. Anyone have any ideas? Oh and ctx is a reference to my mapActivity
This is because the dialog.show(); method does not wait for the user to interact with the Dialog before returning. It does exactly what the name would suggest, and nothing more; it shows the Dialog, and then returns. So, that means that your myMessage field will always be null and this condition will never be true:
if(dialog.getMessage()== MyAlertDialog.positiveMessage){
What you should do instead is pass in OnClickListener for both your positive and negative button, and do whatever you need to in the respective OnClickListener. You won't even need to make a subclass of AlertDialog.Builder, because there won't be any benefit to doing that. Here's how that looks:
dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which){
// Do some positive stuff here!
}
});
dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which){
// Do some negative stuff here!
}
});

How to determine a long touch on android?

I am looking for a way for when a user long touches a mapview (lets say for 1000ms) that i can some how do a certain action.
How would i go about judging how long a user long touches a mapsview(or any view).
It would be similar to android google maps app, when you long touch, it brings up a balloon overlay item.
Edit added
mapView.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
Toast.makeText(mapView.getContext(), "Hello 123", 2000);
return false;
}
});
the above does not work... any ideas why?
Edit added
This is what i am trying at the moment, but it does not seem to work, even if i only press on the phone, it says the event is an action_move,
i am using an inner class in my MapActivity
private long startTime=0;
private long endTime=0;
class MapOverlay extends Overlay {
#Override
public boolean onTouchEvent(MotionEvent ev, MapView mapView) {
if(ev.getAction() == MotionEvent.ACTION_DOWN){
//record the start time
startTime = ev.getEventTime();
Log.d("LC", "IN DOWN");
}else if(ev.getAction() == MotionEvent.ACTION_UP){
//record the end time
endTime = ev.getEventTime();
Log.d("LC", "IN UP");
}else if(ev.getAction() == MotionEvent.ACTION_MOVE){
Log.d("LC", "IN move");
endTime=0;
}
//verify
if(endTime - startTime > 1000){
//we have a 1000ms duration touch
//propagate your own event
Log.d("LC", "time touched greater than 1000ms");
Toast.makeText(getBaseContext(), "Hello 123", Toast.LENGTH_SHORT).show();
startTime=0;
endTime=0;
return true; //notify that you handled this event (do not propagate)
}
return false;//propogate to enable drag
}
}
and here is my error log that does not make any sense to me
06-29 14:29:55.509: DEBUG/LC(7693): IN move
06-29 14:29:56.149: DEBUG/LC(7693): IN UP
06-29 14:29:56.149: DEBUG/LC(7693): 6346707 6349261
06-29 14:29:56.149: DEBUG/LC(7693): time touched greater than 1000ms
the end time should be set to zero...but it is not...any idea why?
This is how do you normally create an onLongClickListener. Try this:
mapView.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View arg0) {
Toast.makeText(mapView.getContext(), "Hello 123", 2000);
return false;
}
});
Reference to your edit:
This might be the way to get what you want.
private final Handler handler = new Handler();
private final Runnable runnable = new Runnable() {
public void run() {
checkGlobalVariable();
}
};
// Other init stuff etc...
#Override
public void onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
// Execute your Runnable after 1000 milliseconds = 1 second.
handler.postDelayed(runnable, 1000);
mBooleanIsPressed = true;
}
if(event.getAction() == MotionEvent.ACTION_UP) {
if(mBooleanIsPressed) {
mBooleanIsPressed = false;
handler.removeCallbacks(runnable);
}
}
}
And now you can check with checkGlobalVariable function:
if(mBooleanIsPressed == true)
This is how you can handle this case. Good luck.
Your are probably looking for a normal long click?
You will have to set your view to be long clickable by adding android:longClickable to your views xml, or by calling setLongClickable(true).
Then you can add an OnLongClickListener to the view.
I dont know of a way to determine exactly how long the long click is. But the default long click is the same as the google maps long click that you mentioned.
OnLongClickListener
You can set up a longClickListener and a touchListener. Add a boolean class data member variable longClicked and set it to false initially. This is how you can set the longClickListener.
view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
longClicked = true;
return false;
}
});
For touchListener
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(longClicked){
//Do whatever you want here!!
longClicked = false;
}
return false;
}
});
It will give you the same effect as google maps long click. Hope it helps.
use System.currentTimeMillis() instead of ev.getEventTime();
When MotionEvent.ACTION_UP, endTime will be set to ev.getEventTime(), this make setting endTime to zero when MotionEvent.ACTION_MOVE be not affect.
Instead of setting endTime to zero, you should set startTime to ev.getEventTime()
This is how I use long and short touches
View.setOnTouchListener(new View.OnTouchListener() {
double firsttouch=0;
boolean isup=false;
int millistotouch=1000;
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction()==MotionEvent.ACTION_DOWN) {
firsttouch = (double) System.currentTimeMillis();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (!isup) {
//
// Do your long click work
//
}
else
{
firsttouch=0;
isup=false;
}
}
}
}, millistotouch);
return true;
}
if (motionEvent.getAction()==MotionEvent.ACTION_UP) {
if (((double) System.currentTimeMillis()-firsttouch)<millistotouch)
{
isup=true;
//
// Do your short click work
//
}
}
return false;
}
});

Categories

Resources