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();.
Fred

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

4
@Accollativo ดูเหมือนว่าคุณยังมีสายเรียกเข้าsuper.onBackPressed()ในonBackPressed()คำจำกัดความของคุณ(นอกเหนือจากที่อยู่ในวิธี onClick)?
Steve Prentice

6
ทุกแอปที่ฉันเคยเห็นชอบวิธี "กดถอยหลังครั้งที่สอง" ผู้ใช้กดปุ่มย้อนกลับโดยไม่ได้ตั้งใจจะรู้สึกรำคาญหากกล่องโต้ตอบปรากฏขึ้น ขนมปังปิ้งจะรบกวนน้อยกว่า
Karmic Coder

@Steve Prentice ฉันใช้ตัวอย่างข้อมูลนั้นในแอปพลิเคชันของฉัน แต่ถ้าเรามีกระบวนการทำงานในขณะที่เราสำรองกิจกรรมของเรา - กระบวนการยังคงทำงานอยู่ จะแก้ไขได้อย่างไร? ถ้าฉันใช้android.os.Process.killProcess(android.os.Process.myPid());แต่ภาพเคลื่อนไหวระหว่างกิจกรรมไม่ราบรื่นนัก แต่จะกะพริบเป็นหน้าจอสีดำประมาณครึ่งวินาที
Stanimir Yakimov

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()หากคุณกดย้อนกลับในขณะที่ยังมองเห็นขนมปังปิ้งอยู่และเฉพาะในกรณีที่การกดย้อนกลับจะส่งผลให้ออกจากแอปพลิเคชัน


แทนที่จะ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
        }
    }
}

มีบางอย่างแปลก ๆ เกิดขึ้นบนแท็บเล็ต Samsung Note ต้องตีกลับเร็ว ๆ หลายครั้ง มันไม่ชอบแนวทาง 'backToast' เหมือนกัน ...
SoloPilot

มันทำงานได้ดีขึ้นในหมายเหตุถ้าคุณยกเลิกขนมปังก่อนออก? ดูสิ่งนี้
ToolmakerSteve

2

ทั้งวิธีของคุณและวิธีของ @ สตีฟเป็นวิธีที่ยอมรับได้ในการป้องกันการออกโดยบังเอิญ

หากเลือกที่จะใช้งานต่อไปคุณจะต้องแน่ใจว่าได้เริ่มต้นแบ็คเพรสเป็น 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
Yogesh Rathi

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

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 โดยใช้ Toast แบบกำหนดเองดังต่อไปนี้:

ใส่คำอธิบายภาพที่นี่

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();
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.