Android - jak zastąpić przycisk „Wstecz”, aby nie kończył () mojej aktywności?

199

Obecnie mam Aktywność, która kiedy zostanie wyświetlona, ​​Powiadomienie zostanie również wyświetlone na pasku powiadomień.

Dzieje się tak, gdy użytkownik naciska do domu, a działanie zostaje zepchnięte w tło, może wrócić do działania za pośrednictwem powiadomienia.

Problem pojawia się, gdy użytkownik naciśnie przycisk Wstecz, moja Aktywność zostanie zniszczona, ale Powiadomienie pozostanie, ponieważ chcę, aby użytkownik mógł się cofnąć, ale nadal będzie mógł uzyskać dostęp do Aktywności za pośrednictwem Powiadomienia. Ale gdy UŻYTKOWNIK spróbuje tego, otrzymuję Null Pointers jako próbę rozpoczęcia nowej działalności zamiast przywracania starej.

Zasadniczo chcę, aby przycisk Wstecz działał dokładnie tak samo jak przycisk Początek, a oto, jak próbowałem do tej pory:


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

Jednak powyższy kod nadal pozwala na zniszczenie mojej aktywności. Jak mogę zapobiec zniszczeniu mojej aktywności po naciśnięciu przycisku Wstecz?

Donal Rafferty
źródło
Istnieje podobne pytanie: stackoverflow.com/questions/2459848/...
aleung
1
Podobna odpowiedź .. stackoverflow.com/questions/5914040/…
Zar E Ahmer
Myślę też, że musisz zmienić kod na `if (Integer.parseInt (android.os.Build.VERSION.SDK)> 5 , the <'powinno stać się a >.
SudoPlz
1
Nawet jeśli to rozwiążesz, nadal musisz poradzić sobie z możliwością zabicia aplikacji przez system, prawda? Mam na myśli, że zerowy przypadek jest nadal możliwy? A jeśli system z jakiegoś powodu zabije Twoją aplikację, czy to również usunie twoje powiadomienie? Myślę, że to musi być problem, ponieważ celem powiadomienia jest istnienie, nawet jeśli aplikacja nie.
ToolmakerSteve
Sprawdź tutaj przykładowy kod aplikacji freakyjolly.com/how-to-add-back-arrow-in-android-activity
Code Spy

Odpowiedzi:

276

Usuń kluczowy program nasłuchujący lub wróć, truegdy masz KEY_BACK.

Potrzebujesz tylko następujących rzeczy, aby złapać klawisz powrotu (pamiętaj, aby nie wywoływać super- in onBackPressed()).

Ponadto, jeśli planujesz uruchomić usługę w tle, koniecznie spójrz startForeground()i upewnij się, że masz ciągłe powiadomienie, w przeciwnym razie Android zabije twoją usługę, jeśli będzie potrzebowała zwolnić pamięć.

@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);
}
ekawas
źródło
70

Łatwiej było go wdrożyć tylko za pomocą jednego wiersza kodu:

@Override
public void onBackPressed() {
   moveTaskToBack(true);
}
Teo Inke
źródło
To powinna być zaakceptowana odpowiedź. Robi dokładnie to, o co pyta i korzysta z czystej wbudowanej funkcjonalności.
Shadoninja,
Dziękuję :) czy możesz opracować koncepcję tego?
Farrukh Faizy
1
Po prostu przesłonisz zdarzenie onBackPressed (), co spowoduje przeniesienie działania do tyłu.
Squirrelkiller
1
To rozwiązanie nie przywróci aktywności po ponownym uruchomieniu aplikacji z ekranu głównego (jeśli na stosie zadań znajduje się inna aktywność).
IgorGanapolsky
12

Myślę, że nie chcesz zastąpić przycisku Wstecz (to po prostu nie wydaje się dobrym pomysłem - system operacyjny Android definiuje takie zachowanie, po co je zmieniać?), Ale użyć cyklu życia aktywności i zachować ustawienia / dane w Zdarzenie onSaveInstanceState (pakiet) .

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

Następnie użyj onCreate (pakiet), aby uzyskać wszystko z tego utrwalonego pakietu i odtworzyć swój stan.

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

Rozważ powyższy kod psuedo, aby skierować Cię we właściwym kierunku. Czytanie cyklu życia aktywności powinno pomóc Ci określić najlepszy sposób na osiągnięcie tego, czego szukasz.

kiswa
źródło
Cześć Kiswa, to prawda, nie chcę zmieniać domyślnego zachowania. Próbowałem użyć onSavedInstanceState i nie działało, ale wydaje mi się, że zauważyłem teraz mój błąd. Dzięki
Donal Rafferty
5
Natknąłem się na co najmniej kilka sytuacji, w których chciałem zasymulować standardowe zachowanie stosu działań bez faktycznego rozpoczynania nowych działań. Myślę, że w takich przypadkach należy zastąpić domyślne zachowanie onBackPressed (). Ogólnie jednak zgadzam się: unikaj przesłonięcia.
Matt Briançon,
4
Zgadzam się z @Matt. Obecnie pracuję nad grą międzyplatformową, która korzysta z NDK. W związku z tym najłatwiej jest, jeśli wszystko jest pojedynczym działaniem. Z tego powodu domyślnym zachowaniem przycisku Wstecz jest ucieczka z aplikacji, czego nie oczekuje większość użytkowników. Musiałem więc zastąpić domyślne zachowanie, aby działanie zachowywało się inaczej, tak jakby użytkownik faktycznie przeszedł na inne działanie, i wychodził z aplikacji tylko w określonych okolicznościach.
Leif Andersen,
1
Czy onSaveInstanceState i zapisywanie danych to zupełnie inne pytanie?
Ted
@Ted - jeśli mówisz, że oprócz onSaveInstanceState, musi istnieć kod, który utrwala dane aplikacji nie będące interfejsem użytkownika, to zgadzam się. Gdy tylko zrezygnujesz z pierwszego planu, Twoja aplikacja może zostać zabita bez dalszego ostrzeżenia. Zawsze musisz ratować wszystko, co ma znaczenie. Z drugiej strony, myślę, że metody cyklu życia aplikacji będą wywoływane bez względu na to, jakiej techniki użyjesz do ukrycia aplikacji, ale zachowaj ją, więc nie powinno być konieczne dodawanie logiki składowania tylko w tym przypadku. Twoja aplikacja potrzebuje tego kodu we wszystkich właściwych miejscach, niezależnie od tego.
ToolmakerSteve
11

po prostu zrób to ...

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

komentowanie //super.onBackPressed (); da rade

androCoder-BD
źródło
1
Przydatna obserwacja, ale czy nie spowoduje to, że przycisk Wstecz nic nie zrobi, jakby był zepsuty? To nie jest dobra rzecz - dezorientująca i denerwująca dla użytkowników. IMHO musi dodać logikę z innej odpowiedzi, aby działała jak przycisk Home, zgodnie z żądaniem. Przyjęta odpowiedź wspomina , że celowo nie nazywali super metody.
ToolmakerSteve
Tak, masz całkowitą rację. Po prostu zastąpi przycisk Wstecz i nic nie zrobi, dopóki nie wprowadzisz logiki. Może być warunkiem dwukrotnego naciśnięcia przycisku, aby zamknąć aplikację lub po prostu chcesz wyłączyć trwającą operację (okno dialogowe postępu) itp., Ale jest to całkowicie zależne od wymagań.
androCoder-BD,
5

Spróbuj tego:

@Override
public void onBackPressed() {
    finish();
}
Thakur
źródło
3

Na wypadek, gdybyś chciał poradzić sobie z zachowaniem przycisku Wstecz (u dołu telefonu) i przycisku Początek (ten po lewej stronie paska akcji), ta niestandardowa aktywność, której używam w moim projekcie, może ci pomóc .

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

Przykład zastosowania w twojej działalności:

public class SomeActivity extends BackActivity {

    // ....

    @Override
    public void onBackPressed()
    {
        // Example of logic
        if ( yourConditionToOverride ) {
            // ... do your logic ...
        } else {
            super.onBackPressed();
        }
    }    
}
Ferran Maylinch
źródło
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)
użytkownik3156040
źródło
0

W Kotlinie:

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

Aby uzyskać więcej informacji, można sprawdzić to .

Istnieje również konkretne pytanie dotyczące zastąpienia przycisku Wstecz w Kotlinie.

solaza
źródło