Android: правильный способ использования onBackPressed () с Toast

85

Я написал фрагмент кода, в котором пользователю будет предложено нажать еще раз, если он захочет выйти. В настоящее время мой код работает в определенной степени, но я знаю, что он написан плохо, и полагаю, что есть способ сделать это лучше. Любые предложения будут полезны!

Код:

public void onBackPressed(){
    backpress = (backpress + 1);
    Toast.makeText(getApplicationContext(), " Press Back again to Exit ", Toast.LENGTH_SHORT).show();

    if (backpress>1) {
        this.finish();
    }
}
Ник
источник
5
Заменить this.finish()на super.onBackPressed();.
Фред
5
вместо this.finish()звонка, NavUtils.navigateUpFromSameTask(this);чтобы вернуться к предыдущему экрану / активности
К Кра,

Ответы:

213

Я бы реализовал диалог, спрашивающий пользователя, хотят ли они выйти, а затем звонил, super.onBackPressed()если они это сделали.

@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
        .setTitle("Really Exit?")
        .setMessage("Are you sure you want to exit?")
        .setNegativeButton(android.R.string.no, null)
        .setPositiveButton(android.R.string.yes, new OnClickListener() {

            public void onClick(DialogInterface arg0, int arg1) {
                WelcomeActivity.super.onBackPressed();
            }
        }).create().show();
}

В приведенном выше примере вам нужно заменить WelcomeActivity названием вашей активности.

Стив Прентис
источник
это работает, но в моем случае всплывающее окно отображается только на несколько миллисекунд, а затем исчезает и отображается новое окно. У меня нет времени нажимать «да» или «нет», и если я его отлаживаю, он не подходит для метода onClick. Зачем?
Accollativo 03 окт.13,
4
@Accollativo, похоже, у вас все еще есть вызов super.onBackPressed()в вашем onBackPressed()определении (кроме того, который находится внутри метода onClick)?
Стив Прентис,
6
Каждое приложение, которое я видел, поддерживает метод «повторного нажатия». Пользователь, случайно нажавший клавишу возврата, будет раздражен, если появится диалоговое окно. Тост менее навязчивый.
Karmic Coder
@Steve Prentice Я использую этот фрагмент в своем приложении, но что насчет того, если у нас есть запущенный процесс, пока мы поддерживаем нашу деятельность - процесс все еще выполняется. Как это исправить? Если я использую, android.os.Process.killProcess(android.os.Process.myPid());но анимация между действиями не такая плавная. Вместо этого мигает черный экран примерно на полсекунды.
Станимир Якимов
1
@Stanimir Yakimov, посмотрите сервисы android для запуска фоновых процессов. Это упростит управление вашим жизненным циклом. Если вы все еще не можете понять это, я бы предложил создать новый вопрос.
Steve Prentice
19

Вам не нужен счетчик для жима со спины.

Просто сохраните ссылку на показанный тост:

private Toast backtoast;

Затем,

public void onBackPressed() {
    if(USER_IS_GOING_TO_EXIT) {
        if(backtoast!=null&&backtoast.getView().getWindowToken()!=null) {
            finish();
        } else {
            backtoast = Toast.makeText(this, "Press back to exit", Toast.LENGTH_SHORT);
            backtoast.show();
        }
    } else {
        //other stuff...
        super.onBackPressed();
    }
}

Это будет вызвано, finish()если вы нажмете назад, пока тост еще виден, и только если обратное нажатие приведет к выходу из приложения.

оборота Siidheesh
источник
вместо this.finish()звонка, NavUtils.navigateUpFromSameTask(this);чтобы вернуться к предыдущему экрану / активности
К Кра,
Альтернативный ответ для рассмотрения здесь . Я еще не решил, какой подход предпочитаю. К этому можно добавить некоторые детали связанного ответа, в частности логику отмены тоста, как только пользователь уйдет.
ToolmakerSteve,
14

Я использую гораздо более простой подход ...

public class XYZ extends Activity {
    private long backPressedTime = 0;    // used by onBackPressed()


    @Override
    public void onBackPressed() {        // to prevent irritating accidental logouts
        long t = System.currentTimeMillis();
        if (t - backPressedTime > 2000) {    // 2 secs
            backPressedTime = t;
            Toast.makeText(this, "Press back again to logout",
                                Toast.LENGTH_SHORT).show();
        } else {    // this guy is serious
            // clean up
            super.onBackPressed();       // bye
        }
    }
}
SoloPilot
источник
Что-то странное происходит на планшете Samsung Note. Нужно несколько раз быстро дать ответный удар. Ему тоже не нравится подход
backToast
Будет ли лучше работать в Note, если отменить тост перед выходом? Смотрите это
ToolmakerSteve
2

И ваш путь, и путь @ Steve - приемлемые способы предотвратить случайный выход.

Если вы решите продолжить свою реализацию, вам нужно будет убедиться, что обратное нажатие инициализировано на 0, и, вероятно, реализовать какой Timer-то тип, чтобы сбросить его обратно на 0 при нажатии клавиши после периода восстановления. (~ 5 секунд кажется правильным)

Ага
источник
2

Вам также может потребоваться сбросить счетчик, onPauseчтобы предотвратить случаи, когда пользователь нажимает кнопку домой или уходит другим способом после первого нажатия кнопки. В противном случае я не вижу проблемы.

Алексей Гительман
источник
1

Если вы хотите выйти из приложения непосредственно из второго действия, не переходя в первое действие, попробуйте этот код ...

Во втором действии поместите этот код ..

 @Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
            .setTitle("Really Exit?")
            .setMessage("Are you sure you want to exit?")
            .setNegativeButton(android.R.string.no, null)
            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface arg0, int arg1) {
                    setResult(RESULT_OK, new Intent().putExtra("EXIT", true));
                    finish();
                }

            }).create().show();
}

И ваше первое действие Поместите этот код ...

public class FirstActivity extends AppCompatActivity {

Button next;
private final static int EXIT_CODE = 100;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    next = (Button) findViewById(R.id.next);
    next.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {

            startActivityForResult(new Intent(FirstActivity.this, SecondActivity.class), EXIT_CODE);
        }
    });
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == EXIT_CODE) {
        if (resultCode == RESULT_OK) {
            if (data.getBooleanExtra("EXIT", true)) {
                finish();
            }
        }
    }
}

}

Табиш хан
источник
1

Это лучший способ, потому что, если пользователь не вернется назад более чем на две секунды, сбросит значение с обратным сжатием.

объявить одну глобальную переменную.

 private boolean backPressToExit = false;

onBackPressedМетод переопределения .

@Override
public void onBackPressed() {

    if (backPressToExit) {
        super.onBackPressed();
        return;
    }
    this.backPressToExit = true;
    Snackbar.make(findViewById(R.id.yourview), getString(R.string.exit_msg), Snackbar.LENGTH_SHORT).show();
    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            backPressToExit = false;
        }
    }, 2000);
}
Йогеш Рати
источник
объявить одну переменную как частное логическое значение backPressToExit = false
Йогеш Рати
1) Измените свой ответ, включив в него упомянутое вами логическое значение, а не говорите это в комментарии. Чтобы люди могли видеть, где должно быть объявление. 2) Действительно, это альтернативный способ узнать время. Объясните, почему вы считаете это «лучшим». В частности, это накладные расходы на создание обработчика - что от этого выиграет?
ToolmakerSteve,
0

Кроме того, перед вызовом необходимо закрыть диалоговое окно activity.super.onBackPressed(), иначе вы получите ошибку « Действие просочилось ..».

Пример в моем случае с библиотекой sweetalerdialog:

 @Override
    public void onBackPressed() {
        //super.onBackPressed();
        SweetAlertDialog progressDialog = new SweetAlertDialog(this, SweetAlertDialog.WARNING_TYPE);
        progressDialog.setCancelable(false);
        progressDialog.setTitleText("Are you sure you want to exit?");
        progressDialog.setCancelText("No");
        progressDialog.setConfirmText("Yes");
        progressDialog.setCanceledOnTouchOutside(true);
        progressDialog.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
            @Override
            public void onClick(SweetAlertDialog sweetAlertDialog) {
                sweetAlertDialog.dismiss();
                MainActivity.super.onBackPressed();
            }
        });
        progressDialog.show();
    }
kaMChy
источник
0

используйте для .onBackPressed (), чтобы вернуться в действие.

@Override
public void onBackPressed(){
    backpress = (backpress + 1);
    Toast.makeText(getApplicationContext(), " Press Back again to Exit ", Toast.LENGTH_SHORT).show();

    if (backpress>1) {
        this.finish();
    }
}
М.зар
источник
1
Пожалуйста, объясните, что вы добавили в исходный код и почему.
ToolmakerSteve,
0

У меня была эта проблема, и я решил ее, добавив следующий метод:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
             // click on 'up' button in the action bar, handle it here
             return true;

        default:
            return super.onOptionsItemSelected(item);
    }
}    
Марк
источник
0

Вы также можете использовать onBackPressed следующими способами с помощью настраиваемого тоста:

введите описание изображения здесь

custom_toast.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/txtMessage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableStart="@drawable/ic_white_exit_small"
    android:drawableLeft="@drawable/ic_white_exit_small"
    android:drawablePadding="8dp"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:gravity="center"
    android:textColor="@android:color/white"
    android:textSize="16sp"
    android:text="Press BACK again to exit.."
    android:background="@drawable/curve_edittext"/>

MainActivity.java

@Override
public void onBackPressed() {

    if (doubleBackToExitPressedOnce) {
        android.os.Process.killProcess(Process.myPid());
        System.exit(1);
        return;
    }

    this.doubleBackToExitPressedOnce = true;
    Toast toast = new Toast(Dashboard.this);
    View view = getLayoutInflater().inflate(R.layout.toast_view,null);
    toast.setView(view);
    toast.setDuration(Toast.LENGTH_SHORT);
    int margin = getResources().getDimensionPixelSize(R.dimen.toast_vertical_margin);
    toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_VERTICAL, 0, margin);
    toast.show();

    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            doubleBackToExitPressedOnce=false;
        }
    }, 2000);
}
Панкадж Лилан
источник
0

Используйте это, это может помочь.

@Override
public void onBackPressed() {
    new AlertDialog.Builder(this)
            .setTitle("Message")
            .setMessage("Do you want to exit app?")
            .setNegativeButton("NO", null)
            .setPositiveButton("YES", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    UserLogin.super.onBackPressed();
                }
            }).create().show();
}
Маниса
источник