Zastąp przycisk Wstecz, aby działał jak przycisk Początek


253

Po naciśnięciu przycisku Wstecz chciałbym, aby moja aplikacja przechodziła w stan zatrzymania, a nie stan zniszczony.

W dokumentach Androida napisano:

... nie wszystkie działania mają takie zachowanie, że są niszczone po naciśnięciu BACK. Gdy użytkownik zaczyna odtwarzać muzykę w aplikacji Muzyka, a następnie naciska BACK, aplikacja zastępuje normalne zachowanie wstecz, zapobiegając zniszczeniu aktywności odtwarzacza, i kontynuuje odtwarzanie muzyki, nawet jeśli jej aktywność nie jest już widoczna

Jak mogę replikować tę funkcjonalność we własnej aplikacji?

Myślę, że muszą być trzy możliwości ...

  1. Uchwyć przycisk Wstecz, naciśnij (jak poniżej), a następnie wywołaj dowolną metodę wywołania przycisku Home.

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
            Log.d(this.getClass().getName(), "back button pressed");
        }
        return super.onKeyDown(keyCode, event);
    }
  2. Zrób zdjęcie przycisku Wstecz, a następnie sfałszuj przycisk Home.

  3. Zrób zdjęcie przycisku Wstecz, a następnie uruchom Aktywność na ekranie głównym, skutecznie wprowadzając Aktywność mojej aplikacji w stan zatrzymania.

Edycja: Wiem o usługach i używam jednej w aplikacji, z którą ten problem jest związany. To pytanie dotyczy w szczególności wprowadzenia działania do stanu zatrzymania, a nie stanu zniszczonego po naciśnięciu przycisku Wstecz.


Odpowiedzi:


338

Przez większość czasu musisz utworzyć usługę, aby wykonać coś w tle, a Twoja widoczność Activitypo prostu to kontroluje Service. (Jestem pewien, że odtwarzacz muzyki działa w ten sam sposób, więc przykład w dokumentach wydaje się nieco mylący.) Jeśli tak jest, to Activitymożesz finishjak zwykle i Servicenadal będzie działać.

Prostszym podejściem jest przechwycenie Backnaciśnięcia przycisku i wywołanie moveTaskToBack (true) w następujący sposób:

// 2.0 and above
@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

// Before 2.0
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

Myślę, że preferowaną opcją powinno być normalne zakończenie działania i możliwość odtworzenia się, np. W razie potrzeby odczytanie bieżącego stanu z usługi. Ale moveTaskToBackczasami może być używana jako szybka alternatywa.

UWAGA : jak wskazał Dave poniżej Android 2.0 wprowadził nową onBackPressedmetodę i te zalecenia dotyczące obsługi przycisku Wstecz.


1
Wygląda na to, że moveTaskToBack () działa zgodnie z potrzebami. Jakie mogą być wady korzystania z tej metody? Czy istnieją przypadki, w których może to nie działać zgodnie z oczekiwaniami?
bdls

1
Po dokładniejszym przeczytaniu dokumentu uważam, że powinien on działać dobrze. (Początkowo myślałem, że odnosi się to do działania, ale tak naprawdę mówi „zadanie zawierające to działanie”). Ale oczywiście powinieneś to sprawdzić sam. :)
Mirko N.

Dzięki Mirko metoda wydaje się działać dobrze. To może być fajne, jeśli uwydatnisz swoją edycję na dole odpowiedzi dla tych, którzy patrzą na to pytanie później - bo tego właśnie szukałem!
bdls

4
Zapoznaj się z Android-developers.blogspot.com/2009/12/..., aby uzyskać informacje na temat zalecanego sposobu obsługi klawisza Wstecz.
hackbod

1
@bdls teoretycznie twoja aktywność w tle mogłaby zostać zabita przez system, jeśli zabraknie zasobów, więc aby być bezpiecznym, i tak powinna móc się odtworzyć. Rzuciłem okiem na kod źródłowy aplikacji Android Music i nie widzę żadnej specjalnej obsługi przycisku Wstecz.
Mirko N.

46

Użyj następującego kodu:

public void onBackPressed() {    
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_HOME);
    startActivity(intent);
}

23

Jeśli chcesz złapać przycisk Wstecz, zajrzyj do tego postu na blogu programistów Androida . Obejmuje to łatwiejszy sposób na zrobienie tego w Androidzie 2.0 i najlepszy sposób na to w przypadku aplikacji działającej w wersji 1.xi 2.0.

Jeśli jednak twoja aktywność zostanie zatrzymana, nadal może zostać zabita, w zależności od dostępności pamięci w urządzeniu. Jeśli chcesz, aby proces działał bez interfejsu użytkownika, powinieneś utworzyć Service. Dokumentacja mówi o usługach:

Usługa nie ma wizualnego interfejsu użytkownika, ale działa w tle na czas nieokreślony. Na przykład usługa może odtwarzać muzykę w tle, gdy użytkownik zajmuje się innymi sprawami, lub może pobierać dane przez sieć lub obliczać coś i zapewniać wynik potrzebnym działaniom.

Wydaje się to odpowiednie dla twoich wymagań.



14

jeśli to pomaga komuś innemu, miałem aktywność z 2 układami, które włączałem i wyłączałem dla widoczności, próbując emulować strukturę page1> page2. jeśli byli na stronie 2 i nacisnęli przycisk Wstecz, chciałem, aby wrócili do strony 1, jeśli nacisnęli przycisk Wstecz na stronie 1, powinien nadal działać normalnie. Jest dość prosty, ale działa

@Override
public void onBackPressed() {
// check if page 2 is open
    RelativeLayout page2layout = (RelativeLayout)findViewById(R.id.page2layout);
    if(page2layout.getVisibility() == View.VISIBLE){
        togglePageLayout(); // my method to toggle the views
        return;
    }else{
        super.onBackPressed(); // allows standard use of backbutton for page 1
    }

}

mam nadzieję, że to komuś pomaga, na zdrowie


10

Przykład roboczy ..

Upewnij się, że nie wywołujesz super.onBackPressed ();

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

W ten sposób Twój przycisk Wstecz działa jak przycisk Początek. To nie kończy twojej aktywności, ale przenieś ją w tło

Drugim sposobem jest zwrócenie moveTaskToBack(true);się onBackPressedi pamiętaj, aby usunąćsuper.onBackPressed


0

Jeszcze lepiej, a może OnPause () :

Wywoływany jako część cyklu życia aktywności, gdy aktywność przechodzi w tło, ale nie została (jeszcze) zabita. Odpowiednik onResume ().

Gdy działanie B zostanie uruchomione przed działaniem A, to wywołanie zwrotne zostanie wywołane na A. B nie zostanie utworzone, dopóki nie powróci funkcja onPause () A, więc pamiętaj, abyenter code here nie rób tutaj nic długiego.

To wywołanie zwrotne jest najczęściej używane do zapisywania dowolnego trwałego stanu, który edytuje działanie i upewnienia się, że nic nie zostanie utracone, jeśli nie będzie wystarczających zasobów, aby rozpocząć nowe działanie bez uprzedniego zabicia tego.

Jest to również dobre miejsce do robienia rzeczy, takich jak zatrzymywanie animacji i innych rzeczy, które pochłaniają zauważalną ilość procesora, aby jak najszybciej przejść do następnej czynności lub zamknąć zasoby, do których dostęp jest wyłączny, np. Kamera.


0

Zastąp onBackPressed () po Androidzie 2.0. Jak na przykład

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

0

Wypróbowałem wszystkie powyższe rozwiązania, ale żadne z nich nie działało dla mnie. Poniższy kod pomógł mi, gdy próbowałem wrócić do MainActivity w sposób, który wywołuje onCreate:

Intencja.FLAG_ACTIVITY_CLEAR_TOP jest kluczem.

  @Override
  public void onBackPressed() {
      Intent intent = new Intent(this, MainActivity.class);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
      startActivity(intent);
  }

-1

Korzystam z @Mirko N. answser przy użyciu nowego niestandardowego tekstu edycji

 public class EditViewCustom extends EditText {

    Button cancelBtn;
    RelativeLayout titleReleLayout;
    public EditViewCustom(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public EditViewCustom(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditViewCustom(Context context) {
        super(context);
    }

    public void setViews(Button cancelBtn,RelativeLayout titleReleLayout){
        this.cancelBtn = cancelBtn;
        this.titleReleLayout = titleReleLayout;
    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            Log.d("KEYCODE_BACK","KEYCODE_BACK");
            cancelBtn.setVisibility(View.GONE);
            this.setFocusableInTouchMode(false);
            this.setFocusable(false);
            titleReleLayout.setVisibility(View.VISIBLE);

            return super.onKeyPreIme(keyCode, event);
          }

        return super.onKeyPreIme(keyCode, event);
    }

}

Następnie ustaw dane ze swojej aktywności

 searchEditView.setViews(cancelBtn, titleRelativeLayout);

Dziękuję Ci.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.