Android: Cách thích hợp để sử dụng onBackPressed () với Toast


85

Tôi đã viết một đoạn mã sẽ cung cấp cho người dùng lời nhắc yêu cầu họ nhấn lại lần nữa nếu họ muốn thoát. Tôi hiện đang có mã của mình hoạt động ở một mức độ nào đó nhưng tôi biết nó được viết kém và tôi cho rằng có một cách tốt hơn để làm điều đó. Bất kỳ đề nghị sẽ là hữu ích!

Mã:

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

    if (backpress>1) {
        this.finish();
    }
}

5
Thay thế this.finish()bằng super.onBackPressed();.
Fred

5
thay vì this.finish()thay vì gọi NavUtils.navigateUpFromSameTask(this);để trở lại màn hình / hoạt động trước đó
Để Kra

Câu trả lời:


213

Tôi sẽ thực hiện một hộp thoại hỏi người dùng nếu họ muốn thoát và sau đó gọi super.onBackPressed()nếu họ làm vậy.

@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();
}

Trong ví dụ trên, bạn cần thay thế WelcomeActivity bằng tên hoạt động của mình.


điều này hoạt động, nhưng trong trường hợp của tôi, cửa sổ bật lên chỉ hiển thị trong vài phần nghìn giây và sau khi biến mất và cửa sổ mới được hiển thị. Tôi không có thời gian để nhấp vào có hoặc không và nếu tôi gỡ lỗi, nó sẽ không chuyển cho phương thức onClick. Tại sao?
Accollativo

4
@Accollativo, có vẻ như bạn vẫn có lệnh gọi super.onBackPressed()trong onBackPressed()định nghĩa của mình (khác với lệnh gọi bên trong phương thức onClick)?
Steve Prentice

6
Mọi ứng dụng tôi đã thấy đều ủng hộ phương pháp "nhấn lại lần thứ hai". Người dùng vô tình nhấn phím quay lại sẽ thấy khó chịu nếu hộp thoại hiển thị. Bánh mì nướng ít xâm phạm hơn.
Karmic Coder

@Steve Prentice Tôi sử dụng đoạn mã đó trong ứng dụng của mình nhưng nếu chúng tôi có một quy trình đang chạy trong khi chúng tôi đang sao lưu hoạt động của mình thì sao - quy trình vẫn đang chạy. Làm thế nào để khắc phục điều đó? Nếu tôi sử dụng android.os.Process.killProcess(android.os.Process.myPid());nhưng hoạt ảnh giữa các hoạt động không được mượt mà. Thay vì điều này, nó sẽ nhấp nháy màn hình đen trong khoảng một nửa giây.
Stanimir Yakimov

1
@Stanimir Yakimov, hãy xem xét các dịch vụ của Android để chạy các quy trình nền. Điều đó sẽ giúp quản lý vòng đời của bạn dễ dàng hơn. Nếu bạn vẫn không thể tìm ra, tôi khuyên bạn nên tạo một câu hỏi mới.
Steve Prentice

19

Bạn không cần một bộ đếm để bấm lưng.

Chỉ cần lưu trữ một tham chiếu đến bánh mì nướng được hiển thị:

private Toast backtoast;

Sau đó,

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();
    }
}

Thao tác này sẽ gọi finish()nếu bạn nhấn lại trong khi bánh mì nướng vẫn hiển thị và chỉ khi nhấn lùi sẽ dẫn đến thoát ứng dụng.


thay vì this.finish()thay vì gọi NavUtils.navigateUpFromSameTask(this);để trở lại màn hình / hoạt động trước đó
Để Kra

Một câu trả lời thay thế để xem xét ở đây . Tôi vẫn chưa quyết định cách tiếp cận nào tôi thích hơn. Một số chi tiết của câu trả lời được liên kết có thể được thêm vào câu trả lời này, cụ thể là logic để hủy bánh mì nướng ngay khi người dùng thoát ra.
ToolmakerSteve

14

Tôi sử dụng cách tiếp cận đơn giản hơn nhiều này ...

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
        }
    }
}

Một điều kỳ lạ xảy ra trên máy tính bảng Samsung Note. Cần phải đánh lại nhiều lần nhanh chóng. Nó cũng không thích cách tiếp cận 'backToast' ...
SoloPilot

Nó có hoạt động tốt hơn trên Note nếu bạn hủy bánh mì nướng trước khi thoát không? Xem cái này
ToolmakerSteve

2

Cả cách của bạn và cách của @ Steve đều là những cách có thể chấp nhận được để ngăn những lần thoát ra ngoài tình cờ.

Nếu chọn tiếp tục quá trình triển khai của mình, bạn sẽ cần đảm bảo đã khởi tạo backpress về 0 và có thể thực hiện một Timersố loại để đặt lại nó về 0 khi nhấn phím, sau một khoảng thời gian hồi chiêu. (~ 5 giây có vẻ đúng)


2

Bạn cũng có thể cần đặt lại bộ đếm onPauseđể tránh trường hợp người dùng nhấn nút home hoặc điều hướng đi bằng một số phương tiện khác sau lần nhấn trở lại đầu tiên. Nếu không, tôi không thấy có vấn đề gì.


1

Nếu bạn muốn thoát ứng dụng của mình khỏi Hoạt động thứ hai trực tiếp mà không cần đến Hoạt động đầu tiên, hãy thử mã này..`

Trong Hoạt động thứ hai đặt mã này ..

 @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();
}

Và hoạt động đầu tiên của bạn Đặt mã này .....

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

Đây là cách tốt nhất, bởi vì nếu người dùng không quay lại quá hai giây thì hãy đặt lại giá trị được nhấn ngược.

khai báo một biến toàn cục.

 private boolean backPressToExit = false;

onBackPressedPhương pháp Ghi đè .

@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);
}

khai báo một biến như là tin backPressToExit boolean = false
Yogesh Rathi

1) Vui lòng chỉnh sửa câu trả lời của bạn để bao gồm boolean mà bạn đề cập, thay vì nói điều đó trong một nhận xét. Vì vậy, mọi người có thể xem nơi khai báo nên được. 2) Thật vậy, đây là một cách thay thế để nhận thức về thời gian. Vui lòng giải thích lý do tại sao bạn coi điều này là "tốt nhất". Cụ thể, điều này có nghĩa là phải tạo một trình xử lý - bạn thu được gì khi làm như vậy?
ToolmakerSteve

0

Ngoài ra, bạn cần phải tách hộp thoại ra trước khi gọi activity.super.onBackPressed(), nếu không bạn sẽ gặp lỗi "Hoạt động đã bị rò rỉ ..".

Ví dụ trong trường hợp của tôi với thư viện 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();
    }

0

sử dụng .onBackPressed () để quay lại Hoạt động chỉ định

@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
Vui lòng giải thích những gì bạn đã thêm vào mã gốc và tại sao.
ToolmakerSteve

0

Tôi vừa gặp sự cố này và đã giải quyết nó bằng cách thêm phương pháp sau:

@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

Bạn cũng có thể sử dụng onBackPressed theo những cách sau bằng cách sử dụng Bánh mì nướng tùy chỉnh:

nhập mô tả hình ảnh ở đây

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

Sử dụng cái này, nó có thể hữu ích.

@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();
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.