Android - Як перекрити кнопку «Назад», щоб вона не закінчила () мою активність?


199

На даний момент у мене є активність, яка, коли вона відображається, Повідомлення також відображатиметься на панелі сповіщень.

Це відбувається так, що коли користувач натискає будинок і активність відсувається на задній план, вони можуть повернутися до активності за допомогою повідомлення.

Проблема виникає, коли користувач натискає кнопку "Назад", мою активність знищують, але повідомлення залишається таким, як я хочу, щоб користувач міг натискати назад, але все-таки мати можливість дістатися до активності за допомогою повідомлення. Але коли USER намагається це, я отримую Null Pointers як його намагається розпочати нову діяльність, а не повертати стару.

Тому по суті я хочу, щоб кнопка "Назад" діяла так само, як і кнопка "Головна", і ось, як я намагався до цього часу:


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

Однак, як видається, вищезазначений код все ще дозволяє знищити мою активність, як я можу зупинити знищення своєї активності при натисканні кнопки "назад"?


Існує аналогічне питання: stackoverflow.com/questions/2459848 / ...
aleung

1
Подібний відповідь .. stackoverflow.com/questions/5914040 / ...
Зар E Ahmer

Також я думаю, що вам доведеться змінити код на `if (Integer.parseInt (android.os.Build.VERSION.SDK)> 5 , the <` повинен стати >.
SudoPlz

1
Навіть якщо ви вирішите це, ви все одно маєте вирішити можливість того, що система вбиває ваш додаток, правда? Я маю на увазі, нульовий випадок все-таки можливий? Або якщо система з будь-якої причини вбиває вашу програму, це також видалить ваше повідомлення? Я думаю, що це має бути проблемою, оскільки мета сповіщення існує, навіть якщо додаток цього не робить.
ToolmakerSteve

Ознайомтеся з прикладом цього коду програми freakyjolly.com/how-to-add-back-arrow-in-android-activity
Code Spy

Відповіді:


276

Видаліть слухача ключів або поверніться, trueколи у вас є KEY_BACK.

Вам просто потрібно наступне зловити клавішу повернення (Переконайтеся , що не називати супер в onBackPressed()).

Крім того, якщо ви плануєте запускати послугу у фоновому режимі, переконайтесь, startForeground()що ви маєте сповіщення про постійне сповіщення, інакше Android знищить ваш сервіс, якщо йому потрібно звільнити пам'ять.

@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

Простіше було реалізувати його лише одним рядком коду:

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

Це має бути прийнятою відповіддю. Це саме те, що задається питанням, і використовує чистий вбудований функціонал.
Shadoninja

Дякую :) Ви можете розробити цю концепцію?
Farrukh Faizy

1
Ви просто перекриєте подію onBackPress (), змусивши її перемістити активність назад.
Squirrelkiller

1
Це рішення не поверне активність при повторному запуску програми з головного екрану (якщо в стеку завдань є ще одна активність).
ІгорГанапольський

12

Я думаю, що ви хочете, це не переосмислити кнопку назад (це просто не здається гарною ідеєю - ОС Android визначає таку поведінку, навіщо її змінювати?), А використовувати життєвий цикл діяльності та зберігати свої налаштування / дані в подія onSaveInstanceState (Bundle) .

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

Тоді ви використовуєте onCreate (Bundle), щоб отримати все з цього збереженого пакета і відтворити свій стан.

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

Розглянемо вищевказаний psuedo-код, щоб направити вас у правильному напрямку. Читання на життєвому циклі діяльності повинно допомогти вам визначити найкращий спосіб досягти того, що ви шукаєте.


Привіт Kiswa, це правда, я не хочу змінювати поведінку за замовчуванням. Я спробував використовувати onSavedInstanceState, і він не працював, але я вважаю, що зараз помітив свою помилку. Спасибі
Donal Rafferty

5
Я натрапив щонайменше на кілька ситуацій, коли я хотів імітувати стандартну поведінку стека активності, не починаючи фактично нових заходів. Я думаю, що в цих випадках доцільно змінити типову поведінку onBackPress (). В цілому, однак, я згоден: уникайте перекреслювання.
Метт Брайансон

4
Я згоден з @Matt. Зараз я працюю над кросовою платформою, яка використовує NDK. Таким чином, найпростіше, якщо все - це одна діяльність. Через це поведінка кнопки "назад" за замовчуванням полягає у тому, щоб уникнути програми, чого не очікують більшість користувачів. Тому мені довелося перезаписати поведінку за замовчуванням, щоб активність поводилася по-різному, як ніби користувач насправді пішов на іншу діяльність, і лише вийшов із програми лише у певних обставинах.
Лейф Андерсен

1
Хіба не onSaveInstanceState і збереження даних зовсім інше питання?
Тед

@ Ted - якщо ви говорите, що в додатку до OnSaveInstanceState також повинен бути код, який зберігає дані додатків, що не належать до інтерфейсу користувача, тоді я згоден. Як тільки ви відмовитесь від переднього плану, ваш додаток може бути знищений без подальшого попередження. Завжди потрібно зберігати все, що має значення. З іншого боку, я думаю, що методи життєвого циклу додатків будуть називатися незалежно від того, яку техніку ви використовуєте, щоб приховати додаток, але тримати його навколо, тому не слід додавати логіку збереження лише для цього випадку. Ваш додаток потребує цього коду в усіх потрібних місцях незалежно.
ToolmakerSteve

11

просто зробіть це ..

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

коментуючи //super.onBackPress (); зробить трюк


1
Корисне спостереження, але чи не це призведе до того, що кнопка "назад" взагалі нічого не робить, як ніби вона зламана? Це не дуже добре - заплутати і дратувати користувачів. ІМХО має додати логіку з іншої відповіді, щоб діяти як кнопка «Головна», як було запропоновано у питанні. У прийнятій відповіді зазначається, що вони навмисно не називали супер метод.
ToolmakerSteve

Так, ви абсолютно праві. Він просто скасує кнопку назад і нічого не зробить, поки ви не вкладете туди якусь логіку. Це може бути умовою для подвійного натискання кнопки, щоб закрити програму, або ви просто хочете відключити діючу операцію (діалогове вікно прогресу) тощо, але це повністю відповідає вимозі.
androCoder-BD


3

На випадок, якщо ви хочете керувати поведінкою кнопки "Назад" (внизу телефону) та кнопки "додому" (тієї, що знаходиться зліва від панелі дій), ця спеціальна діяльність, яку я використовую у своєму проекті, може допомогти вам .

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

Приклад використання у вашій діяльності:

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

У Котліні:

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

Для отримання додаткової інформації ви можете перевірити це .

Існує також специфічне питання щодо перемикання кнопки повернення в Котліні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.