I know this question have been asked many times around here, but i didn't find the propert answer for my issue.
this code can disable back button:
#Override
public void onBackPressed() {
// Do Here what ever you want do on back press;
}
but is there anyway that i can disable back button for a temporary time,not for the whole Activity ?
nice answer by Dixit. Just another option
public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean result = false;
if (keyCode == KEYCODE_BACK) {
if (condition) {
result = true;
}
}
return result;
}
N.B ..
it will work on ancient version also
returning true from onKeyDown consumes the default behavior
You have to set on boolean flag where you have to require disable back button set flag value true;
In onBackPressed() you have to put condition as per #Dixit says
#Override
public void onBackPressed() {
if(condition to check){
// this block disable back button
}else{
// this block enable back button
super.onBackPressed();
}
}
If you want to disable backbutton for certain time use this,
//for 5 sec = 5000
countDownTimer = new CountDownTimer(5000,1000) {
#Override
public void onTick(long millisUntilFinished) {
txtWait.setTextColor(getResources().getColor(R.color.errorcolor));
txtWait.setText("Wait( " + millisUntilFinished / 1000+" sec)");
onBackPressed();
}
#Override
public void onFinish() {
YourActivityName.super.onBackPressed();
}
}.start();
And in the override method:
#Override
public void onBackPressed() {
//super.onBackPressed(); commented this to disable the back press
}
Full working code:
YourActivity extends AppCompatActivity{
boolean isBackButtonDisabled = false;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState)
setContentView(R.layout.somelayout);
disableBackButton(4000); //<--Back button is disabled
}
#Override
public void onBackPressed(){
if(!sBackButtonDisabled){
super.onBackPressed();
}
}
private void disableBackButton(final int timeInMilis){
if(!isBackButtonDisabled) {
isBackButtonDisabled = true; //<-- Keep it outside Thread code
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(timeInMilis);
} catch (InterruptedException e) {
} finally {
isBackButtonDisabled = false;
}
}
});
t.start();
}
}
}
Note: You can use disableBackButton(time) in other scenarios as well. For example Button click. If
you click button multiple times the Thread will only run once. Because in this code
isBackButtonDisable variable is thread-safe "in a way".
Related
My app is built with around 50-60 screens. Each screen has a button to open a new screen. Now the issue I am facing is when user double tap button, a new screen is open twice.
For this issue, I found a solution like below.
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000){
return;
}
mLastClickTime = SystemClock.elapsedRealtime();
But to prevent double click, I need to write the above code in each button click. I have not created common custom button which used everywhere.
Is there any way to double tap on app level?
i got same issue i solved it as below it might be helpfull for you.
you can achive by two ways
One:
try to using a boolean variable:
public class Blocker {
private static final int BLOCK_TIME = 1000;
private boolean isBlockClick;
/**
* Block any event occurs in 1000 millisecond to prevent spam action
* #return false if not in block state, otherwise return true.
*/
public boolean block(int blockInMillis) {
if (!isBlockClick) {
isBlockClick= true;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
isBlockClick= false;
}
}, blockInMillis);
return false;
}
return true;
}
public boolean block() {
return block(BLOCK_TIME );
}
}
use this as below in every click.
button.setOnClickListener(new View.OnClickListener() {
private Blocker blocker = new Blocker();
#Override
public void onClick(View v) {
if (!blocker.block(block-Time-In-Millis)) {
// do your action
}
}
});
Two
or you can set button.setEnable(false) on every clickevent of button as below
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btn.setEnabled(false);
}
});
actually you can set the activities not to have multiple instances by adding the flag Intent.FLAG_ACTIVITY_REORDER_TO_FRONT to the intent.
see answer from other question
If the activity is in the stack, it will not be created twice
use this custom class it can handle any doubletab or single tab on button click event
public class DoubleTabCustomButton implements View.OnClickListener {
private boolean isRunning = true;
private int resetInTime = 500;
private int counter = 0;
private DoubleClickCallback listener;
public DoubleTabCustomButton(Context context) {
listener = (DoubleClickCallback) context;
}
#Override
public void onClick(View v) {
if (isRunning) {
if (counter == 1) {
listener.onDoubleClick(v);
}
else if (counter==0){
listener.onSingleClick(v);
}
counter++;
if (!isRunning) {
isRunning = true;
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(resetInTime);
isRunning = false;
counter = 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
}
it's interface
public interface DoubleClickCallback {
public void onDoubleClick(View v);
public void onSingleClick(View V);
}
and finally you can use in activity like this
public class ButtonDoubleTab extends AppCompatActivity implements DoubleClickCallback {
Button btndoubletab;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button_double_tab);
btndoubletab=findViewById(R.id.btndoubletab);
// btndoubletab.setOnClickListener(this);
btndoubletab.setOnClickListener(new DoubleTabCustomButton(this));
}
#Override
public void onDoubleClick(View v) {
//do double tab action
}
#Override
public void onSingleClick(View V) {
//single tab action
}
}
If you have a base activity class, you can override the startActivity(Intent) method to add the Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
abstract class BaseActivity: AppCompatActivity() {
final override fun startActivity(intent: Intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
super.startActivity(intent)
}
}
Use this inline function:
inline fun View.onSingleClick(minimumClickInterval: Long = 800, crossinline onClick: (View?) -> Unit) {
var isViewClicked = false
var mLastClickTime = 0L
setOnClickListener { view ->
val currentClickTime = SystemClock.uptimeMillis()
val elapsedTime = currentClickTime - mLastClickTime
mLastClickTime = currentClickTime
if (elapsedTime <= minimumClickInterval)
return#setOnClickListener
if (!isViewClicked) {
isViewClicked = true
Handler(Looper.getMainLooper()).postDelayed({ isViewClicked = false }, 600)
} else {
return#setOnClickListener
}
onClick(view)
Log.d(this.javaClass.simpleName, "onSingleClick successfully called")
}
}
Use with any view like this:
button.onSingleClick {
// do something here on the button click
}
You can also set the minimum click interval like this:
button.onSingleClick(1000) {
// do something here on the button click
}
make the button disable on click .
b.setEnabled(false);
You can make it back enable it onResume or any other certain callback
b.setEnabled(true);
I am using a CountDownTimer in a Fragment and trying to stop it if the user hit the physical back button in the phone. I have tried overriding onPause, onDestroy, onStop, onDestroyView but nothing seems to be working. Kind of lost here. Can some one give me a pointer here?
public class Foo extends Fragment {
CountDownTimer myTimer;
#Override
public void onStop() {
super.onStop();
myTimer.cancel();
}
#Override
public void onPause() {
super.onPause();
myTimer.cancel();
}
#Override
public void onDestroyView() {
super.onDestroyView();
myTimer.cancel();
}
#Override
public void onDestroy() {
super.onDestroy();
myTimer.cancel();
}
#OnClick(R.id.btn_greenleft_no)
public void goBack() {
myTimer.cancel();
Objects.requireNonNull(getActivity()).onBackPressed();
}
#OnClick(R.id.btn_greenright_yes)
public void showSuccess(View view) {
markAll();
myTimer.cancel();
(new MusicPlayer()).playSound(getContext(), "cheers.mp3");
final Snackbar snackbar = Snackbar.make(snackBarView, R.string.congratulations, Snackbar.LENGTH_SHORT);
snackbar.show();
myTimer.cancel();
}
private void startTimer(final View view) {
int Seconds = 5;
myTimer = new CountDownTimer(Seconds * 1000 + 1000, 1000) {
public void onTick(long millisUntilFinished) {
String rem = String.valueOf(millisUntilFinished / 1000);
Log.d("APP_DEBUG", "Timer: " + rem);
}
public void onFinish() {
goBack();
}
}.start();
}
}
Here is my 2 cents. Fragment doesn't have an onBackPressed() method which is present in the Activity class. It gets called when physical back button is pressed by the user. Here is what docs says:
Called when the activity has detected the user's press of the back key. The default implementation simply finishes the current activity, but you can override this to do whatever you want.
What you can do is override the onBackPressed() method in the parent activity of your Foo fragment, then using an interface communicate to the fragment that back button was pressed by the user. Inside the fragment you can have the desired code to cancel the timer. This answer in the question How to implement onBackPressed() in Fragments? can help with sample code.
Try to modify onBackPressed in Your fragment's parent activity.
#Override
public void onBackPressed() {
// I assume this is the way how You add fragment to fragment manager
//getSupportFragmentManager().beginTransaction().replace(android.R.id.content, Foo.getInstance(), Foo.TAG).commit()
// Find fragment by its string TAG and when You get it, call to stop countDownTimer
Foo foo = (Foo) getSupportFragmentManager().findFragmentByTag(Foo.TAG);
if (foo != null) {
foo.stopCountDownTimer();
}
super.onBackPressed();
}
Next step is to declare in Your Foo fragment two things:
public static final String TAG = "Foo";
and
public void stopCountDownTimer() {
myTimer.cancel();
}
For fragment you cant use onBackPressed method, Instead please use this code
#Override
public void onResume() {
super.onResume();
if (getView() == null) {
return;
}
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
myTimer.cancel();
return false;
}
return true;
}
});
}
You have to call countDownTime.finish() as well. I have used it and it works for me.
#Override
public void onDetach()
{
super.onDetach();
if (countDownTimer != null)
{
countDownTimer.cancel();
countDownTimer.onFinish();
}
}
have you tried onBackPressed()
#Override
public void onBackPressed() {
super.onBackPressed();
myTimer.cancel();
myTimer =null;
}
Have you tried adding an OnKeyListener in your fragment like this:
Here "view" is the parent layout of your fragment , the one that hosts the timer.
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.i(tag, "keyCode: " + keyCode);
if( keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
myTimer.cancel();
return true;
}
return false;
}
});
I want to implement the function : if user dosen't checked the autoLogin CheckBox, clear the login user information and logout when the application is quit normally or force closed(clean the memeory).
I write the code clearAutoStart() to clear user information both in finish() and OnDestory().
When the user press back button twice, the finish() will execute, and will logout success. But as you know, if the application force closed, OnDestory() will not execute all the time. So in this situation, it will not logout success.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK) {
exitBy2Click(); //quit normal
}
return false;
}
private static Boolean isExit = false;
private void exitBy2Click() {
Timer tExit = null;
if (isExit == false) {
isExit = true;
Toast.makeText(this, "press again to quit", Toast.LENGTH_SHORT).show();
tExit = new Timer();
tExit.schedule(new TimerTask() {
#Override
public void run() {
isExit = false;
}
}, 2000);
} else {
finish();
System.exit(0);
}
}
#Override
protected void onDestroy() {
clearAutoStart();
super.onDestroy();
}
#Override
public void finish() {
clearAutoStart();
super.finish();
}
#Override
protected void onStop() {
Log.i("ws", "---->>SmarterActivity onStop");
super.onStop();
}
public void clearAutoStart() {
RememberUser rememberUser = RememberUser.getInstance();
if (rememberUser.getIsAutoStart() == false) {
Log.i("ws", "---->>clearAutoStart getIsAutoStart false ");
UserLocalStore userLocalStore = UserLocalStore.getInstance();
userLocalStore.setUserLoggedIn(false);
userLocalStore.clearUserData();
Log.i("ws", "---->>clearAutoStart getIsAutoStart false OK ");
} else {
Log.i("ws", "---->>clearAutoStart getIsAutoStart true ");
}
}
I try to add the clearAutoStart() in onStop(), but this means if I press the HOME button , the application will logout.
When you press HOME onPause() is called and then onStop().
So you can put a member variable that keep the track of what is happening:
#Override
protected void onPause() {
mIsPause = true;
super.onPause();
}
#Override
protected void onStop() {
Log.i("ws", "---->>SmarterActivity onStop");
if(!mIsPause)
clearAutoStart();
super.onStop();
}
I have an issue here
when I click on the exit button on my android app which I debug it with my Samsung Note 3. it will looping from the start of the app instead of exiting it to the main screen of my note 3
below is my code:
public class MainActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
Button start=(Button)findViewById(R.id.btnStart);
Button exit=(Button)findViewById(R.id.btnExit);
start.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
/** start game */
startLoop();
}
});
exit.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
onDestory();
}
});
}
public void startLoop(){
Intent game = new Intent(this, Splash.class);
startActivity(game);
}
protected void onDestory(){
int pid=android.os.Process.myPid();
android.os.Process.killProcess(pid);
}
}
Just call finish() - no need to do any of the onDestroy() stuff.
finish() will close the app for you.
Furthermore, any time you override onDestroy(), make sure to call super.onDestroy()!
call finish() on your exit button's on click listener. You could also use java's System.exit(0)
This is how I handle my game...
GameWorld.java (or something else) need to take controle over the game state
public void pauseThread() {
gameLoop.setKeepPlaying(false);
}
GameLoop.java
// method for accessing the game logic
public void setKeepPlaying(boolean run) {
keepPlaying = run;
}
and the loop itself:
/** MAIN GAME LOOP */
while (keepPlaying) {
[...]
}
btw: driven is this loop by a Thread
EDIT: example which part onDestroy takes in Android....
#Override
protected void onDestroy() {
Log.d("MainActivity", "***onDestroy()***");
disableKeepScreenOn(getWindow(), TAG);
unregisterReceiverAndStopServices();
NotificationManager nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nManager.cancel(NOTIFICATION_GENERAL);
super.onDestroy();
}
And here is a Menu, which provides one entry to close the application...
#Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
[...]
case (OPM_EXIT):
MainActivity.this.finish();
return true;
default:
return false;
}
}
In the app i m looking for the users location using gps.In the Async pre execute method i m showing a toast.I want that while i show that toast the back button should be disabled
aftr the location is found i want to enable the back button in the post execute!
to disable the back button i have used.But this is not working
OnKeyListener mainScreenKeyListener = new OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
boolean disableEvent = false;
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
disableEvent = true;
}
return disableEvent;
}
};
You can declare global variable disableEvent by
final boolean disableEvent;
Your Preexecute method can set it to false by
disableEvent = false;
Your Postexecute method can set it to true by
disableEvent = true;
You can override onBackPressed as shown below:
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
if (disableEvent)
{
// do nothing
}
else
{
// do something
}
}
Here you go
Assign one static variable.and set its value to "NO" in onPreExecute.
in onPostExecute assign its value to "YES".
And write following code in your onBackPressed.
#Override
public void onBackPressed() {
if (decision.equals("NO")) { //Here no means dont allow user to go back
} else {
super.onBackPressed(); // Process Back key default behavior.
}
}
hi for disable you simply call the above function
public void onBackPressed()
{
}
for enable
public void onBackPressed()
{
super.onBackPressed();
super.finish();
//Intent
}
if you want both set flag inside the function
override onBackPress method in your activity
Class A
{
public static boolean isToastShown=false;
#Override
public void onBackPressed() {
if(isToastShown==true)
return false;
else
super.onBackPressed();
}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//Show your toast here
A.isToastShown=true;
new CountDownTimer(2000,2000) {
#Override
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
A.isToastShown=false;
}
}.start();
}