Back button double click - java

I am new android developer. I want to ask a question. Here is what I need: When the user click Back Button it counts as double click?
#Override
public void onBackPressed() {
--> what to write here?
return;
}
}

You need to check an interval between to presses and determine whether you it can be counted as a double click or not:
private static final long DOUBLE_PRESS_INTERVAL = /* some value in ns. */;
private long lastPressTime;
#Override
public void onBackPressed() {
long pressTime = System.nanoTime();
if(pressTime - lastPressTime <= DOUBLE_PRESS_INTERVAL) {
// this is a double click event
}
lastPressTime = pressTime;
}

You should probably include the reasoning behind wanting this functionality in the question instead of a comment. It makes it a lot easier for us to point you in the right direction. There are a few ways to achieve what you want but I would not recommend the 'double back' method.
Instead, if you show the progress bar in a dialog or somewhere in the search activity, there is no activity between the search and the second activity. That way you do not need to do a double back.
Also, you could display the progress bar in the second activity until the work is done and then replace it with the actual content with another call to setContentView(View). Note that this would require threading though (otherwise the progress bar would never show).

Double Key Button
private static long back_pressed;
#Override
public void onBackPressed()
{
if (back_pressed + 2000 > System.currentTimeMillis()) super.onBackPressed();
else Toast.makeText(getBaseContext(), "Press once again to exit!", Toast.LENGTH_SHORT).show();
back_pressed = System.currentTimeMillis();
}

Related

How to reset CountDownTimer without having to pause first

Novice looking for some help~
I have a CountDownTimer with start, pause, and reset buttons. When the timer is running, I'd like to be able to hit the reset button to restart it from the original value (edittext.) Currently, the only way I am able to accomplish this is to hit "pause" then "reset."
To give an example of what I'm hoping to accomplish:
If timer is set to 10s,
10-9-8-reset-10-9-8-7-6-5-reset-10-9....
Thanks in advance!
I've looked through the forums and android dev site
EDIT: Original problem solved but another has arisen. Code below shows changes made. If I hit start-pause-start too quickly, one second is added to the original countdown time. For example: 15-14-pause-start-15-pause-start-16-pause-start-17-pause-start-18
private void pauseTimer(boolean actualPause) {
mCountdowntimer.cancel();
mTimerRunning = false;
if(actualPause)
updateWatchInterface();
}
private void resetTimer() {
if(mTimerRunning)
pauseTimer(false);
mTimeLeftInMillis = mStartTimeInMillis;
updateCountDownText();
updateWatchInterface();
}
I am not sure what your exact problem is, so I will mention a couple of approaches.
Option 1: If you don't have any problems remembering the 'start time' (that's what mStartTimeInMillis denotes, right?), then you can simply change the signature of the function pauseTimer as follows:
private void pauseTimer(boolean actualPause) {
mCountdowntimer.cancel();
mTimerRunning = false;
if(actualPause)
updateWatchInterface();
}
private void resetTimer() {
if(mTimerRunning)
pauseTimer(false);
mTimeLeftInMillis = mStartTimeInMillis;
updateCountDownText();
updateWatchInterface();
}
Also modify the top portion as:
public void onClick(android.view.View view) {
if (mTimerRunning) {
pauseTimer(true);
}
//...Other code
}
This will ensure that the watch interface is not updated to show the paused interface when you press the reset button, but the actual working would be as if you had pressed pause first and then reset. Also, we put a check to ensure that the pause timer is not called if it was actually pause followed by reset.
Option 2: If you can't get the reference to mStartTimeInMillis without calling pause first, you can use SharedPreferences, and save the start time every time you start the timer, thus allowing you access to the variable as follows:
//Put
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putString("time", *Your_value* );
editor.apply();
//Get
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String name = prefs.getString("time", "00:00");//"00:00" is the default value if the //entry doesn't exist.
I hope these will be helpful :)

Android SeekBar talkback, talking too much

(Android) On a music player, you update the seekbar as expected with this:
PRECISION_SEEKBAR = 100000;
((SeekBar) findViewById(R.id.seekBar2)).setMax(PRECISION_SEEKBAR);
timerSeekBarUpdate.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
final SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar);
#Override
public void run() {
if (control == null || player == null) {
cancel();
return;
}
seekBar.setProgress((int) (player.getCurrentPosition() * PRECISION_SEEKBAR / player.getDuration()));
...
However, if the focus is on the seek bar, talkback steadily and nonstop gives feedback for the progress. Like "seek control 25%", "seek control 25%", "seek control 25%", "seek control 26%", "seek control 26%", "seek control 27%"
I'm missing sth but couldnot solve the problem. I have set the contentDescription to other than #null. But then it reads the content description this time without stopping.
On Spotify client, I checked, it reads the progress as "xx percent" just once. Despite saving the focus on the seekbar.
When I edit the precision for 1 or 100, then you lose the precision on the seekbar. It looks like there are a few parts in the song. You either play one or another by swiping on the seekbar.
Has anybody experienced sth like this? I couldn't find anything on google docs, stack network or somewhere else.
You can just override sendAccessibilityEvent() so it ignores description updates:
#Override
public void sendAccessibilityEvent(int eventType) {
if (eventType != AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION) {
super.sendAccessibilityEvent(eventType);
}
}
As Altoyyr mentioned, this has the side effect of ignore ALL description updates, including scrolling with volume buttons. So you'll need add back sending the event for volume press actions:
#Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
super.sendAccessibilityEvent(AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
}
}
return super.performAccessibilityAction(action, arguments);
}
I had the problem and found that SeekBar reads the percentage on every update.
It helped, that I update the SeekBar only when the percentage changes but still keep a high precision (in my case in ms).
#Override
public void updateSeekBar(final int currentPosInMillis, final int durationInMillis) {
long progressPercent = calculatePercent(currentPosInMillis, durationInMillis);
if (progressPercent != previousProgressPercent) {
seekBar.setMax(durationInMillis);
seekBar.setProgress(currentPosInMillis);
}
previousProgressPercent = progressPercent;
}
private int calculatePercent(int currentPosInMillis, int durationInMillis) {
if(durationInMillis == 0) {
return 0;
}
return (int) (((float)currentPosInMillis / durationInMillis) * 100);
}
previousProgressPercent is initialized to -1.
Please note that this solution is not the same as Spotify does it.
Spotify overrides the message announced by the system when the SeekBar gets selected.
This has following 2 effects:
Updates can be made as often as you want without the percentage beeing repeated
When the percentage changes while the SeekBar is selected then nothing gets announced
Point 2 might me a drawback depending on what you want to achieve.

How do I delay a button performing an action by a certain timeframe, if the button wasn't pressed again in that timeframe?

Sorry for the terrible title, I am bad at describing these things.
I am building a metronome and have a (-) UI button that decreases the tempo by 1, and a (+) UI button that increases the tempo by 1.
My problem currently is that whenever I press either buttons, the metronome restarts itself since there's a new tempo, and plays immediately. So if you press the (-) button 10 times in a row, each time you press it you hear the initial metronome "beep".
I would like my app to do the following:
When the user clicks either (-) or (+) buttons, wait for 200 milliseconds
IF the user didn't click the buttons again in that timeframe, play the metronome
If the user DID click the button again, don't play the metronome, repeat the process: wait 200 milliseconds, if no click was made play the metronome, etc
The end result would be that if I'm at 100 bpm and I repeatedly press the (+) button 20 times until I am at 120 bpm, the metronome wouldn't start playing until I am done tapping.
How do I go about implementing this? Thank you!
Declare and instantiate the below in your activity:
private Handler timeoutHandler = new Handler();
private Runnable delayStartThread = new Runnable() {
public void run() {
startMetronome();
}
};
Then insert the below code block in your onClickListener for both + and - buttons:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
timeoutHandler.removeCallbacks(delayStartThread);
tempoOfMetronome++; //tempoOfMetronome--; for decrease button
stopMetronome();
timeoutHandler.postDelayed(delayStartThread, 200);
}
});
For more details on how the code works, refer the below links for examples (I used these examples to formulate the answer):
Android: clicking TWICE the back button to exit activity - How to use handler.postDelayed()
How to cancel handler.postDelayed? - How to cancel handler.postDelayed()
You should also look at the Android documentation for those methods.
If you want a delay between the action and the effect, there are several ways you can achieve it. This is one.
private boolean pressedAction = false;
#override
public void onClick(View v) {
if (pressedAction) return;
pressedAction = true;
new Thread(new Runnable(
#override
public void run() {
try {
Thread.sleep(200); // 200 miliseconds
} catch (Exception e) {}
// Update views or do work (program logic)
pressedAction = false;
}
}
}
Then, the metronome logic is your bussiness.

Why doesn't DialogFragment.dismiss kill the dialog right away?

I am building a very basic vocabulary application. The feature I am trying to implement right now is a go to feature, that is taking the user to a specific vocab term. i am doing this by prompting the user with a dialog fragment that asks the user for a page number. (dialog fragment will get triggered via a callback, button press)
This is my code for doing so
public class GoToDialog extends DialogFragment{
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String pgn = pageNumber.getText().toString();
if(!isNumeric(pgn) || pgn.isEmpty()) {
Toast.makeText(getActivity(), "Please enter a valid number", Toast.LENGTH_SHORT).show();
} else {
int pagina = Integer.parseInt(pgn);
if(pagina <= 0 || pagina > total) {
Toast.makeText(getActivity(), String.format("Please enter a valid " +
"term number between 0 and %d", total), Toast.LENGTH_SHORT).show();
} else {
getDialog().dismiss();
getFragmentManager().executePendingTransactions();
communicator.onDialogMessage(pagina);
}
}
}
});
Here are screenshots when I run my application
Screenshot2(right after screenshot 1)
In terms of functionality The dialog loads up fine and is able to take the user to the right location. However in that example of taking the user from term 7 to term 5, the user is taken to the
right term but the dialog doesn't close as it should from getDialog().dismiss(). I know dismiss is being called because I walked through the code and communicator.onDialogMessage(pagina) returns the right term number to the activity. The dialog does close when I select another term number to go to. Does anyone see the issue? This doesn't make sense to me at all.
To close a dialog, dismiss is the correct method to use
- How to correctly dismiss a DialogFragment?
I also tried what a user suggested in Correct way to remove a DialogFragment: dismiss() or transaction.remove()?, which is to call executePendingTransactions().
If anyone's having a similar issue, the issue with my application was my OnTouchListener.
When I set up on OnTouchListener to trigger the DialogFragment, here was my original code for doing so
goTo - TextView
private void setUpGoToTouchListener() {
goTo.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
FragmentManager fm = MainActivity.this.getFragmentManager();
GoToDialog dialog = new GoToDialog();
Bundle bundle = new Bundle();
bundle.putInt("Size", defMan.getTotalCount());
dialog.setArguments(bundle);
dialog.show(fm, "Manager");
return true;
}
});
}
When the gesture(a touch) on the TextView occurs, two MotionEvents will be generated, the press, ACTION_DOWN - first finger has touched the screen, and the release, ACTION_UP - the last of the fingers has stopped touching the screen. Because two motion events occurred, two dialog fragments were created. Thats why dismiss had to be called twice in my situation to get rid of both dialog fragments. I fixed this by having a conditional test for event.getAction()

How to disable multiple clicks on button in Android

When you click button in my app if you are fast enough before the screen/popup loads it loads them multiple times. I know how to disable the click on the button but that's not an option, because when you close the popup or return to the previous screen the button is disabled. I tried with Handler and Runnable to wait for 1s before the button is active again but this solution is not optimal in case if the OS needs more time to open the next screen. So I am searching for the most optimal solution. Any ideas?
Edit: setClickable(false) and then setting it back to true doesn't work because it loads my screen/popup slower than expected the button is enabled again and it opens the screen/popup multiple times again.
You can disable the multiple click at the same time using the following code
private boolean isClicked;
#Override
public void onClick(final View v) {
if(isClicked) {
return;
}
isClicked = true;
v.postDelayed(new Runnable() {
#Override
public void run() {
isClicked = false;
}
}, 1000);
}
Implement logic in your onClick to determine whether you want to ignore the click.
You can disable the button. When you close the popup enable the button and when the popup is visible make it disable. Keep listening the actions for popup and when the user get back to the previous screen.
Maintain one variable on button onClick listener and change the value to determine when you want to click button..
You can stop multiple operations by this way.
button.setOnClickListener(new OnClickListener(){
#Override
public void onClick()
{
performOperation();
}
});
public void performOperation()
{
static boolean working = true;
if(working)
{
return;
}
working = true;
//Do you work here;
working = false;
}

Categories