I'm building a simple counter, it has buttons to add or subtract from a total value, I want it to keep adding if I hold the button, incrementing +5 every second, but i'm having problems to make it work. I'm using onClickListener, but i can't find a way to make it work "together" with on touch listener.
pl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
lf++;
lt.setText(Integer.toString(lf));
}
}
You will have to use handler to schedule a runnable that increments +5 every 1 second (+1 per 200 milliseconds to keep it smooth)
Handler handler = new Handler();
Runnable incrementTask = new Runnable(){
#Override
public void run(){
lf++;
handler.postDelayed(incrementTask, 200); //Execute after 200 milliseconds
}
};
Then you implement onTouchListener and post this runnable when ACTION_DOWN is dispatched and cancel it when ACTION_UP is dispatched.
boolean buttonPressed = false;
pl.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
//This check is imporant since ACTION_DOWN might be called
// multiple times when finger is moving
if(!buttonPressed){
buttonPressed = true;
handler.post(incrementTask);
}
} else if(event.getAction() == MotionEvent.ACTION_UP){
if(buttonPressed)
{
buttonPressed = false;
handler.cancel(incrementTask);
}
}
return false;
}
});
Please note that this logic won't work well with your current click listener. For better user experience, I would recommend that you start this timer/runnable only when your button is long pressed. I had a similar situation in a project so I wrote a utility class to help me detect when a button is being held and released after a long click. Normal clicks work fine as well. You can find my ClickAndHoldManager class on Github.
To use it, you simply pass your view in the constructor and set a listener:
ClickAndHoldManager manager = new ClickAndHoldManager(myButton);
manager.setClickCallback(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Regular Click
}
});
manager.setHoldCallback(new ClickAndHoldManager.HoldListener() {
#Override
public void holdStarted() {
// do handler.post() here
}
#Override
public void holdEnded() {
//do handler.cancel() here
}
});
Related
I am using following code for using a button. I works.(sendBtn is a button in a fragment)
sendText = view.findViewById(R.id.send_text);
View sendBtn = view.findViewById(R.id.send_btn);
sendBtn.setOnClickListener(v -> send(sendText.getText().toString()));
Now i want to disable the button for 1 sec after a click
I found following solution but above code works "without onClick(View v)"method and without implementing View.OnClickListener in class. How to provide delay in such case..How code is working without onClick method.
#Override
public void onClick(View v) {
((Button) findViewById(R.id.click)).setEnabled(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
((Button) findViewById(R.id.click))
.setEnabled(true);
}
}, 1000);
}
});
Use this method when you want to interrupt user clicks:
private static long mLastClickTime = 0L;
public static boolean isOpenRecently() {
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) {
return true;
}
mLastClickTime = SystemClock.elapsedRealtime();
return false;
}
Usage:
if (v.getId() == R.id.sendBtn) {
if (isOpenRecently()) return;
// Your logic
}
Basically you are using lambda in your code, where v->{} represents the onCLick(View v) function.
sendBtn.setOnClickListener(v -> send(sendText.getText().toString()));
You can do the following to disable the button for 1 second
void doOnSendButtonClick(View v){
//Send the message (your logic here)
send(sendText.getText().toString());
//Disable button
sendBtn.setEnabled(false);
//enable button after 1000 millisecond
new Handler(Looper.getMainLooper()).postDelayed(() -> {
sendBtn.setEnabled(true);
}, 1000);
}
And call this method when user clicks on the button
sendButton.setOnClickListener(view -> doOnSendButtonClick(view));
You could use a CountDownTimer.
CountDownTimewr timer = new CountDownTimer(1000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
// enable button
((Button) findViewById(R.id.click)).setEnabled(true);
}
}
#Override
public void onClick(View v) {
// disable btn and start timer of one second in millis
((Button) findViewById(R.id.click)).setEnabled(false);
timer.start();
}
});
Please try this way
Handler(Looper.getmainLooper()) and remove callback after you done your task inside runnable thread...also try to put this logic in any method outside in this class and call from setonclicklistener
Try the Timer.shedule with timertask
you can use runOnUIThread method inside where you can update UI.
you can also try to check the time difference of click and enable again in looping like while.
I have a customView , i want to set onClick which will only be called on the very first click. In which i want to start a thread which will start a counter on other TextView , with simple onClickListener with each click a new threads starts which is a problem . How can i achieve such task ?
Another option is in your onClick() method do set a null listener, i.e.
#Override
public void onClick(View view) {
// disable any other clicks from now on
customView.setOnClickListener(null);
...
}
I think this is only logic problem, So I solve this problem by using a boolean variable for the first click:
boolean isFristClick = true;
#Override
public void onClick(View v) {
if (isFristClick) {
// Start your counter Thread here
isFristClick = false;
} else {
// Do nothing
}
}
What about making a workaround for that?!! like assigning a boolean value to tell if it's the first click:
private boolean first_click = true;
your_view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(first_click){
first_click = false;
// Do something on first click
}else{
// Do another thing on later clicks
}
}
});
I am trying to add both OnClickListener and OnTouchListener to my image view. Following is how the image view is created
dialogImage = (ImageView)findViewById(R.id.dialogImage);
Following is how the listeners are set
dialogImage.setOnClickListener(dialogBoxClicked);
dialogImage.setOnTouchListener(imageViewSwiped);
Following is the listener method implementation
public OnClickListener dialogBoxClicked = new OnClickListener()
{
#Override
public void onClick(View v)
{
//To do has been removed because the code is too big
}
};
OnTouchListener imageViewSwiped = new OnSwipeTouchListener()
{
public void onSwipeRight()
{
currentlyActiveQuestion++;
currentWord = words.get(currentlyActiveQuestion);
setUI();
}
public void onSwipeLeft()
{
currentlyActiveQuestion--;
currentWord = words.get(currentlyActiveQuestion);
setUI();
}
};
Here the OnTouchListener is implemented by a class called OnSwipeTouchListener to monitor left and right swipes. This class can be found here - https://stackoverflow.com/a/12938787/1379286
But the problem now is, when I set the OnTouchListener to the image view, the OnClickListener is not responding / do not do what it should do. ImageView is only responding to OnTouchListener. If I remove OnTouchListener then the OnClickListener works. I tested this in a virtual device WVGA5.1 and Galaxy Nexus in eclipse and not in a real phone because I do not have one.
How can I solve this?
EDIT
Any code example will be greatly appreciated
You may call View.performClick() when action_up. This results in the click event being called when an actual click happens. Hope it helps.
your_txtView.setOnClickListener(new TextView.OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
your_txtView.setOnTouchListener(new TextView.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
} else if (MotionEvent.ACTION_UP == event.getAction()) {
v.performClick();
}
return true;
}
});
The OnTouchListener hooks the click-event. Handle the click event in it instead. Check out the answer on this question
From my experience, If you can't have both onTouchListener and onClickListener for the same view. If you want your onClickListener to work, set clickable="true" in the XML.
i am creating a call/dial button, when i click on that call/dial button, a call will be made based on the input that is displayed in the edittext. I managed to do that part. can you guys advise me whether i can do a longer click on that same call/dial button, so that a toast can come out to ask user to choose something else??
I did some research on "setOnLongClickListener" but i am not sure if i can combine it in the same call/dial button? I have attached on the working dial function which i managed to do, wondering if the "setOnLongClickListener" can be combined together somehere in the code?
private void dialANumber() {
try {
buttonCall = (ImageButton) findViewById(R.id.imageButton2);
buttonCall.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if (display != null) {
Intent callNumber = new Intent();
callNumber
.setAction(android.content.Intent.ACTION_CALL);
callNumber.setData(Uri.parse("tel:" + display.getText()));
startActivity(callNumber);
}
}
});
} catch (ActivityNotFoundException anfe) {
Log.e("DialANumber", "Dialing the number failed", anfe);
}
this code is working. i hope a longer click can be made on the same call/dial button so the button can have a normal click to make a call, and longer click to pop out a toast. Thanks in advance.
Note that returning "false" on the long click listener will have the UI responding to the long click as a short click too. Return "true" if you want to kill that off. "True" means "yes, I used this event" and "false" means "whether I used it or not, the environment is free to respond as well." (I know this because I just used AkashG's answer in my own app.)
A GestureDetector with a SimpleOnGestureListener would help you differentiate between the different types of presses. A GestureDectector is a class which can read different types of touch events (for example, single taps and long presses), and sends them to a listener which handles each type differently. Here's the documentation on the Detector and Listener.
http://developer.android.com/reference/android/view/GestureDetector.html
http://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener.html
First, set up your SimpleOnGestureListener, the important methods for you to override will be onSingleTapUp and onLongPress. In your onCreate, create an instance of GestureDetector that references your listener. Then, attach an OnTouchListener to your button that sends the event to your detector. You'll want it to look something like this:
//Set up the Detector
GestureDetector.SimpleOnGestureListener myGestureListener = new GestureDetector.SimpleOnGestureListener()
{
#Override
public boolean onSingleTapUp(MotionEvent e)
{
//Your onClick code
return false;
}
#Override
public void onLongPress(MotionEvent e)
{
//Your LongPress code
super.onLongPress(e);
}
};
//And make a variable for your GestureDetector
GestureDetector myGestureDetector;
...
#Override
onCreate(Bundle b)
{
...
myGestureDetector = new GestureDetector(myActivity.this, myGestureListener);
...
}
...
//And finally, wherever you are setting up your button
button.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View view, MotionEvent motionEvent)
{
myGestureDetector.onTouchEvent(motionEvent);
return false;
}
There a a bunch of other types of events this class can interpret in case you want to get even more fancy. GestureDetector is a very good class to do a little research on, it can be very useful and isn't too complex. Hope this helps.
Yes you can do this:
XML file:
<Button
android:id="#+id/call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CALL"/>
<ImageButton
android:id="#+id/callBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_launcher"/>
For button click event:
Button button=(Button) findViewById(R.id.call);
button.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
Toast.makeText(getBaseContext(), "Long CLick", Toast.LENGTH_SHORT).show();
return false;
}
});
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (display != null) {
Intent callNumber = new Intent();
callNumber
.setAction(android.content.Intent.ACTION_CALL);
callNumber.setData(Uri.parse("tel:" + display.getText()));
startActivity(callNumber);
}
}
});
For imageButton:
ImageButton imageButton=(ImageButton) findViewById(R.id.callBtn);
imageButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if(check==false){
Toast.makeText(getBaseContext(), "CLick", Toast.LENGTH_SHORT).show();
}
imageButton.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
check=true;
if(check){
Log.d("bool", check+"");
Toast.makeText(getBaseContext(), "Long CLick", Toast.LENGTH_SHORT).show();
check=false;
}
return false;
}
});
Declare this at the top(golbally):
boolean check=false;
I have a Button which sets both onLongClickListener & onClickListener :
onLongClickListener :
#Override
public boolean onLongClick(View v) {
do something ...
return true;
}
onClickListener :
#Override
public void onClick(View v) {
do something else ...
}
When I long click the button, onLongClick fires repeatly
(sometimes onClick fires too when I release the button, it's weird ##")
What I want is to make the onLongClick be triggered only once for one long press.
So I modified the code :
onLongClickListener :
#Override
public boolean onLongClick(View v) {
do something ...
myButton.setLongClickable(false);
return true;
}
onClickListener :
#Override
public void onClick(View v) {
myButton.setLongClickable(true);
do something else ...
}
Unfortunately, the onClick callback was locked too after onLongClick fires!
I cant unlock the button anymore :|
Whats wrong with my code? Also, why onClick sometimes works when I release my button after a long click?
I've got the code you need, give me a minute to post it.
btn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//DO STUFF GRAH!
}
});
btn.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
//OTHER STUFF
return true;
}
});
This worked fine for me. I made an int and onLongClick added one and displayed it in a toast. Always incremented by one, and didn't do the onClick (reset it to 0).