How do I set a button to listen for a long press event, where the button is on a view which is already using gesture detector to listen to onFling event?
I have added the code for reference. Please explain how I can implement multiple listeners in an activity. Also, can multiple listeners be implemented for a single view? One of which is a long press listener while the other is a onfling listener
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.knowledge);
summary =(TextView)findViewById(R.id.textSummary);
buckview = (View) findViewById(R.id.bucketView);
ball = (View)findViewById(R.id.meatBall);
gestureDetector = new GestureDetector(new MyGestureDetector());
View mainview = (View) findViewById(R.id.mainView);
/*
//Set touch release listener for bucket view
mainview.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_UP)
{
buckview.setVisibility(RelativeLayout.GONE);
}
return false;
}
});
*/
// Set the touch listener for the main view to be our custom gesture listener
mainview.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
});
ball.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
buckview.setVisibility(ImageView.VISIBLE);
return false;
}
});
ball.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction()==MotionEvent.ACTION_UP)
{
buckview.setVisibility(ImageView.GONE);
return false;
}
else
return true;
}
});
}
class MyGestureDetector extends SimpleOnGestureListener {
public void onShowPress(MotionEvent event){
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Intent intent = new Intent(Knowledge.this.getBaseContext(), Knowledge.class);
/* If only horizontal allowed
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
return false;
}
*/
// right to left swipe
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
startActivity(intent);
Knowledge.this.overridePendingTransition(
R.anim.slide_in_right,
R.anim.slide_out_left
);
return false;// left to right swipe
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
startActivity(intent);
Knowledge.this.overridePendingTransition(
R.anim.slide_in_left,
R.anim.slide_out_right
);
return false;// top to bottom swipe
} else if(e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
startActivity(intent);
Knowledge.this.overridePendingTransition(
R.anim.slide_in_top,
R.anim.slide_out_bottom
);
return false;// bottom to top swipe
} else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
startActivity(intent);
Knowledge.this.overridePendingTransition(
R.anim.slide_in_bottom,
R.anim.slide_out_top
);
return false;
}else
return true;
}
// It is necessary to return true from onDown for the onFling event to register
#Override
public boolean onDown(MotionEvent event) {
return true;
}
}
}
Simply try
button.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View arg0) {
// TODO Auto-generated method stub
return false;
}
})
It will work perfectly untill you return true from onLongClick. If you return ture from here then setOnLongClickListener only get invoked. If you return false all Listeners belong to this button will get invoked. In your case both Listensers will get invoked whether you made setOnLongClickListener or setOnTouchListener.
I hope this will help you.
Related
I want to add a fast forward button on my code but I did not find how.
this is my code I hope someone will help me.
MusicPlayer.java:
imagePlaypause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mediaPlayer.isPlaying()){
handler.removeCallbacks(updater);
mediaPlayer.pause();
imagePlaypause.setImageResource(R.drawable.playbutton);
}else {
mediaPlayer.start();
imagePlaypause.setImageResource(R.drawable.pausebutton);
updateSeekBar();
}
}
});
new Content().execute(getIntent().getStringExtra("downloadlink"));
textTotalDuration.setText(milliSecondsToTimer(mediaPlayer.getDuration()));
playerSeekBar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
SeekBar seekBar = (SeekBar) view;
int playPosition = (mediaPlayer.getDuration() / 100) * seekBar.getProgress();
mediaPlayer.seekTo(playPosition);
textCurrentTime.setText(milliSecondsToTimer(mediaPlayer.getCurrentPosition()));
return false;
}
});
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
playerSeekBar.setSecondaryProgress(i);
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
playerSeekBar.setProgress(0);
imagePlaypause.setImageResource(R.drawable.playbutton);
textCurrentTime.setText(R.string.zero);
textTotalDuration.setText((R.string.zero));
mediaPlayer.reset();
new Content().execute(getIntent().getStringExtra("downloadlink"));
textTotalDuration.setText(milliSecondsToTimer(mediaPlayer.getDuration()));
}
});
}
I want to add a fast forward button on my code but I did not find how.
this is my code I hope someone will help me.
I found how
if (mediaPlayer != null) {
int currentPosition = mediaPlayer.getCurrentPosition();
if (currentPosition + seekForwardTime <= mediaPlayer.getDuration()) {
mediaPlayer.seekTo(currentPosition + seekForwardTime);
} else {
mediaPlayer.seekTo(mediaPlayer.getDuration());
}
}
The issue is im not getting the Button release Toast.
i've a simple view in xml on which im performing onTouch.
hidenBtn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
firstTime=System.currentTimeMillis();
Toast.makeText(MainActivity.this, "Pressed", Toast.LENGTH_SHORT).show();
} else if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL) {
Toast.makeText(MainActivity.this, "Released", Toast.LENGTH_SHORT).show();
secondTime=System.currentTimeMillis();
if(secondTime-firstTime>=5000){
//do your actions here,prev,curr are fields in a class
ShowDialog();
}
else{
firstTime=0;
secondTime=0;
}
}
// TODO Auto-generated method stub
return false;
}
});
Change your OnTouchListener like this:
hidenBtn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
firstTime=System.currentTimeMillis();
Toast.makeText(MainActivity.this, "Pressed", Toast.LENGTH_SHORT).show();
return true;
} else if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL) {
Toast.makeText(MainActivity.this, "Released", Toast.LENGTH_SHORT).show();
secondTime=System.currentTimeMillis();
if(secondTime-firstTime>=5000){
//do your actions here,prev,curr are fields in a class
ShowDialog();
}
else{
firstTime=0;
secondTime=0;
}
}
// TODO Auto-generated method stub
return false;
}
});
You are returning false at ACTION_DOWN which means you are not consuming your touch event, so no other steps of the same event are triggered. Therefore you need to return true in the ACTION_DOWN so you can intercept ACTION_UP.
I need to change image every 5 seconds, then when we touch the ImageView it will stop changing until we release the touch.
When the application go to OnPause state it pauses the auto changing of the image.
I save the KEY_ID and stop the runnable in onSaveInstanceState
How can I make this change automatically ? Below is my code in java.
public class MainActivity extends AppCompatActivity {
private ImageView im_car;
private Handler mHandler = new Handler();
public static Integer[] mThumbeId = {R.drawable.first, R.drawable.second, R.drawable.thard};
public int i = 0, id = 0;
private String KEY_ID = "key_id";
#SuppressLint("ClickableViewAccessibility")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
im_car = findViewById(R.id.im_car);
mThumbRun.run();
if (savedInstanceState != null) {
i = savedInstanceState.getInt(KEY_ID);
}
im_car.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mHandler.removeCallbacks(mThumbRun);
break;
case MotionEvent.ACTION_UP:
if (i!=0)
{
i = i-1;
}
else i=2;
mThumbRun.run();
break;
}
return false;
}
});
}
#Override
protected void onRestart() {
super.onRestart();
if (i!=0)
{
i = i-1;
}
else i=2;
mThumbRun.run();
}
Runnable mThumbRun = new Runnable() {
#Override
public void run() {
im_car.setImageResource(mThumbeId[i]);
i++;
if (i >= mThumbeId.length) {
i = 0;
}
mHandler.postDelayed(this, 5000);
}
};
}
You can create a touch listener in your imageview.
Keep a boolean to check wether image should change.
boolean imageChangePermission = true;
yourImageView.setOnTouchListener(new OnTouchListener () {
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() == android.view.MotionEvent.ACTION_DOWN) {
Log.d("TouchTest", "Touch down");
}
else if (event.getAction() == android.view.MotionEvent.ACTION_UP) {
Log.d("TouchTest", "Touch up");
imageChangePermission = false;
}
}
}
ACTION_DOWN - when you first touch
ACTION_MOVE - when you are moving your finger on screen
ACTION_UP - when you remove your finger from screen
Create a Handler to periodically call the change Image method of yours.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(imageChangePermission) {
changeImage();
}
}
},5000); //Run after every 5 second
I'm trying to make two buttons that will change add or subtract 1 from a value when tapped, and constantly add or subtract 1 ten times per second while the button is held. I can get the value to be changed when the button is tapped, or when it is held, but I can't get the behavior I want. Here's what I have:
btPlus.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
setTempo(mTempo + 1);
mTempo=mTempo+1;
tvTempo.setText(Integer.toString(mTempo));
return true;
}
return false;
}
});
btMinus.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
setTempo(mTempo - 1);
mTempo=mTempo-1;
tvTempo.setText(Integer.toString(mTempo));
return true;
}
return false;
}
});
btPlus.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
int action = motionEvent.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (getActivity() == null)
return;
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
tvTempo.setText(Integer.toString(mTempo));
mTempo++;
if (mTempo > 300)
mTempo = 300;
}
});
}
}, 100, 100);
break;
case MotionEvent.ACTION_UP:
timer.cancel();
}
return true;
}
});
btMinus.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
int action = motionEvent.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (getActivity() == null)
return;
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
tvTempo.setText(Integer.toString(mTempo));
mTempo--;
if (mTempo < 1)
mTempo = 1;
}
});
}
}, 100, 100);
break;
case MotionEvent.ACTION_UP:
timer.cancel();
}
return true;
}
});
return rootView;
}
Thanks for your help!
You can implement onKeyListener to determine how long button is held, like in this example:
Android long-touch event
or use onLongClickListener to perform a different function from a regular "click" like here:
On long click delete item
i want to catch double click on textview for that i have used below code
but it still not working :(
TextView txtOne;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtOne = (TextView) findViewById(R.id.txtOne);
txtOne.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
System.out.println("DRAG");
return gestureDetector.onTouchEvent(event);
}
});
}
final GestureDetector gestureDetector = new GestureDetector(
new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDoubleTap(MotionEvent e) {
System.out.println("Double Tap");
return super.onDoubleTap(e);
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
System.out.println("One Click");
return super.onSingleTapUp(e);
}
});
only drag is calling but not "Double Tap" and "One Click" never called
Try following steps.
Step 1
Write following code in your activity.
// initialize the Gesture Detector
gd = new GestureDetector(this,new OnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
#Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// TODO Auto-generated method stub
return false;
}
#Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
});
// set the on Double tap listener
gd.setOnDoubleTapListener(new OnDoubleTapListener() {
#Override
public boolean onDoubleTap(MotionEvent e) {
Toast.makeText(SplashActivity.this,"Double Tap",Toast.LENGTH_LONG).show();
return false;
}
#Override
public boolean onDoubleTapEvent(MotionEvent e) {
// if the second tap hadn't been released and it's being moved
return false;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
});
Step 2
Write following code for activity. Here gd will be GestureDetector object.
txt.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
gd.onTouchEvent(event);
return false;
}
});
Instead of:
GestureDetector.SimpleOnGestureListener()
Try:
GestureDetector.OnDoubleTapListener()
For SimpleGestureDetector, you need to override onDown() and return true to trigger double tap detector.
Whether or not you use GestureDetector.OnGestureListener, it's best practice to implement an onDown() method that returns true. This is because all gestures begin with an onDown() message. If you return false from onDown(), as GestureDetector.SimpleOnGestureListener does by default, the system assumes that you want to ignore the rest of the gesture, and the other methods of GestureDetector.OnGestureListener never get called. This has the potential to cause unexpected problems in your app. The only time you should return false from onDown() is if you truly want to ignore an entire gesture.
Source: http://developer.android.com/training/gestures/detector.html
This is a good site for performing double click... I used it and worked
doubleCLICK