Android - Làm cách nào để ghi đè nút Quay lại của nhóm vì vậy nó không kết thúc () Hoạt động của tôi?


199

Tôi hiện có một Hoạt động mà khi nó được hiển thị, Thông báo cũng sẽ được hiển thị trên thanh Thông báo.

Điều này là để khi Người dùng nhấn về nhà và Hoạt động được đẩy xuống nền, họ có thể quay lại Hoạt động thông qua Thông báo.

Sự cố phát sinh khi Người dùng nhấn nút quay lại, Hoạt động của tôi bị hủy nhưng Thông báo vẫn còn vì tôi muốn người dùng có thể nhấn lại nhưng vẫn có thể truy cập Hoạt động thông qua Thông báo. Nhưng khi NGƯỜI DÙNG thử điều này, tôi nhận được Null Pointers vì nó cố gắng bắt đầu một hoạt động mới thay vì mang lại hoạt động cũ.

Vì vậy, về cơ bản tôi muốn nút Quay lại hoạt động giống hệt như nút Home và đây là cách tôi đã thử cho đến nay:


        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event)  {
            if (Integer.parseInt(android.os.Build.VERSION.SDK) < 5
                    && keyCode == KeyEvent.KEYCODE_BACK
                    && event.getRepeatCount() == 0) {
                Log.d("CDA", "onKeyDown Called");
                onBackPressed();
            }

            return super.onKeyDown(keyCode, event);
        }

        public void onBackPressed() {
            Log.d("CDA", "onBackPressed Called");
            Intent setIntent = new Intent(Intent.ACTION_MAIN);
            setIntent.addCategory(Intent.CATEGORY_HOME);
            setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(setIntent); 

            return;
        }   

Tuy nhiên, đoạn mã trên dường như vẫn cho phép Hoạt động của tôi bị hủy, Làm cách nào tôi có thể ngăn Hoạt động của mình bị hủy khi nhấn nút quay lại?


Có một câu hỏi tương tự: stackoverflow.com/questions/2459848/
Kẻ

1
Câu trả lời tương tự .. stackoverflow.com/questions/5914040/
Kẻ

Ngoài ra tôi nghĩ bạn phải thay đổi mã của mình thành `if (Integer.parseInt (android.os.Build.VERSION.SDK)> 5 , the <` nên trở thành một >.
SudoPlz

1
Ngay cả khi bạn giải quyết điều này, bạn vẫn phải xử lý khả năng hệ thống giết ứng dụng của bạn, phải không? Ý tôi là, trường hợp null vẫn có thể? Hoặc nếu hệ thống giết ứng dụng của bạn vì bất kỳ lý do gì, điều đó cũng sẽ xóa thông báo của bạn? Tôi nghĩ rằng đây phải là một vấn đề, vì mục đích của thông báo là tồn tại ngay cả khi ứng dụng không có.
ToolmakerSteve

Kiểm tra ở đây ví dụ mã ứng dụng freakyjolly.com/how-to-add-back-arrow-in-android-activity
Code Spy

Câu trả lời:


276

Xóa trình nghe chính của bạn hoặc trả lại truekhi bạn cóKEY_BACK .

Bạn chỉ cần những điều sau đây để bắt phím quay lại (Đảm bảo không gọi siêu trongonBackPressed() ).

Ngoài ra, nếu bạn có kế hoạch chạy dịch vụ ở chế độ nền, hãy đảm bảo xem startForeground()và đảm bảo có thông báo liên tục nếu không Android sẽ giết dịch vụ của bạn nếu cần giải phóng bộ nhớ.

@Override
public void onBackPressed() {
   Log.d("CDA", "onBackPressed Called");
   Intent setIntent = new Intent(Intent.ACTION_MAIN);
   setIntent.addCategory(Intent.CATEGORY_HOME);
   setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(setIntent);
}

70

Nó dễ dàng hơn để thực hiện nó chỉ với một dòng mã:

@Override
public void onBackPressed() {
   moveTaskToBack(true);
}

Đây phải là câu trả lời được chấp nhận. Điều này thực hiện chính xác những gì câu hỏi đang hỏi và đang sử dụng chức năng được xây dựng sạch.
Shadoninja

Thankyou :) bạn có thể xây dựng khái niệm đằng sau nó?
Farrukh Faizy

1
Bạn chỉ cần ghi đè sự kiện onBackPression (), làm cho nó di chuyển hoạt động về phía sau.
Squirrelkiller

1
Giải pháp này sẽ không đưa hoạt động trở lại khi bạn khởi chạy lại ứng dụng từ màn hình chính (nếu có một hoạt động khác trên ngăn xếp tác vụ).
IgorGanapolsky

12

Tôi nghĩ điều bạn muốn không phải là ghi đè nút quay lại (điều đó dường như không phải là một ý tưởng hay - Hệ điều hành Android xác định hành vi đó, tại sao lại thay đổi nó?), Mà là sử dụng Vòng đời hoạt động và duy trì cài đặt / dữ liệu của bạn trong sự kiện onSaveInstanceState (Gói) .

@Override
onSaveInstanceState(Bundle frozenState) {
    frozenState.putSerializable("object_key",
        someSerializableClassYouWantToPersist);
    // etc. until you have everything important stored in the bundle
}

Sau đó, bạn sử dụng onCreate (Gói) để lấy mọi thứ ra khỏi gói đó và duy trì trạng thái của bạn.

@Override
onCreate(Bundle savedInstanceState) {
    if(savedInstanceState!=null){ //It could be null if starting the app.
        mCustomObject = savedInstanceState.getSerializable("object_key");
    }
    // etc. until you have reloaded everything you stored
}

Hãy xem xét mã psuedo ở trên để chỉ cho bạn đi đúng hướng. Đọc lên Vòng đời hoạt động sẽ giúp bạn xác định cách tốt nhất để thực hiện những gì bạn đang tìm kiếm.


Xin chào Kiswa, đây là sự thật, tôi không muốn thay đổi hành vi mặc định. Tôi đã thử sử dụng onSattedInstanceState và nó không hoạt động nhưng tôi tin rằng tôi đã phát hiện ra lỗi của mình. Cảm ơn
Donal Rafferty

5
Tôi đã gặp ít nhất một vài tình huống mà tôi muốn mô phỏng hành vi ngăn xếp Hoạt động tiêu chuẩn mà không thực sự bắt đầu Hoạt động mới. Trong những trường hợp này, tôi nghĩ rằng, nó phù hợp để ghi đè hành vi onBackPression () mặc định. Tuy nhiên, nói chung, tôi đồng ý: tránh ghi đè.
Matt Briançon

4
Tôi đồng ý với @Matt. Tôi hiện đang làm việc trên một trò chơi đa nền tảng sử dụng NDK. Như vậy, thật dễ dàng nếu mọi thứ chỉ là một hoạt động. Bởi vì điều này, hành vi mặc định của nút quay lại là để thoát khỏi ứng dụng, đây không phải là điều mà hầu hết người dùng mong đợi. Vì vậy, tôi đã phải ghi đè lên hành vi mặc định để làm cho hoạt động khác đi, như thể người dùng thực sự đã đi đến một hoạt động khác và chỉ thoát khỏi ứng dụng trong một số trường hợp nhất định.
Leif Andersen

1
Có phải onSaveInstanceState và lưu dữ liệu là một câu hỏi hoàn toàn khác không?
Ted

@Ted - nếu bạn nói rằng ngoài việc sử dụng onSaveInstanceState, cũng cần phải có mã duy trì dữ liệu ứng dụng không phải UI, thì tôi đồng ý. Ngay khi bạn từ bỏ tiền cảnh, ứng dụng của bạn có thể bị giết mà không cần cảnh báo gì thêm. Phải luôn luôn tiết kiệm bất cứ điều gì quan trọng. Mặt khác, tôi nghĩ rằng các phương thức vòng đời của ứng dụng sẽ được gọi bất kể bạn sử dụng kỹ thuật nào để ẩn ứng dụng nhưng giữ nó xung quanh, vì vậy không cần thiết phải thêm logic lưu chỉ trong trường hợp này. Ứng dụng của bạn cần mã đó ở tất cả các vị trí phù hợp bất kể.
ToolmakerSteve

11

chỉ cần làm điều này ..

@Override
public void onBackPressed() {
    //super.onBackPressed();
}

nhận xét //super.onBackPression (); sẽ làm trò bịp


1
Một quan sát hữu ích, nhưng điều này sẽ không làm cho nút quay lại không làm gì cả, như thể nó bị hỏng? Đó không phải là một điều tốt để làm - gây nhầm lẫn và gây phiền nhiễu cho người dùng. IMHO phải thêm logic từ một câu trả lời khác, để hoạt động như nút Home, như được yêu cầu trong câu hỏi. Câu trả lời được chấp nhận đề cập rằng họ đã cố tình không gọi siêu phương thức.
ToolmakerSteve

Vâng, chắc chắn bạn đúng rồi. Nó sẽ chỉ ghi đè nút quay lại và sẽ không làm gì cho đến khi bạn đặt một số logic ở đó. Có thể là một điều kiện để nhấn đúp nút để đóng ứng dụng hoặc bạn chỉ muốn vô hiệu hóa một hoạt động đang diễn ra (hộp thoại tiến trình), v.v., nhưng nó hoàn toàn theo yêu cầu.
androCoder-BD

5

Thử cái này:

@Override
public void onBackPressed() {
    finish();
}

3

Chỉ trong trường hợp bạn muốn xử lý hành vi của nút quay lại (ở dưới cùng của điện thoại) và nút home (một nút bên trái của thanh hành động), hoạt động tùy chỉnh này tôi đang sử dụng trong dự án của tôi có thể giúp bạn .

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;

/**
 * Activity where the home action bar button behaves like back by default
 */
public class BackActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupHomeButton();
    }

    private void setupHomeButton() {
        final ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeButtonEnabled(true);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onMenuHomePressed();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    protected void onMenuHomePressed() {
        onBackPressed();
    }
}

Ví dụ về việc sử dụng trong hoạt động của bạn:

public class SomeActivity extends BackActivity {

    // ....

    @Override
    public void onBackPressed()
    {
        // Example of logic
        if ( yourConditionToOverride ) {
            // ... do your logic ...
        } else {
            super.onBackPressed();
        }
    }    
}

1
@Override
public void onBackPressed() {
// Put your code here.
}

//I had to go back to the dashboard. Hence,

@Override
public void onBackPressed() {
    Intent intent = new Intent(this,Dashboard.class);
    startActivity(intent);
}
Just write this above or below the onCreate Method(within the class)

0

Trong Kotlin:

val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
    // Handle the back button event
}

Để biết thêm thông tin bạn có thể kiểm tra điều này .

Ngoài ra còn có câu hỏi cụ thể về ghi đè nút quay lại trong Kotlin.

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.