<rmcreative>

RSS

Android: обрабатываем нажатие back в фрагментах

28 октября 2014

В Android-приложениях иногда требуется особым образом обработать нажатие кнопки back. Если у вас не используются фрагменты, всё просто. Перекрываем метод onBackPressed у Activity и делаем что нам нужно. Если же используются фрагменты и по нажатию back необходимо что-то поменять в фрагменте, обработку хочется сделать именно в нём.

Посмотрев ответы на эту тему на StackOverflow я был несколько удивлён. Предлагается либо ненадёжный способ через OnKeyListener, либо жёсткий хардкод. Попробуем сделать это более красиво и удобно.

Начнём с интерфейса для фрагментов. Готового в фреймворке нет, сделаем свой:

public interface OnBackPressedListener {
    public void onBackPressed();
}

Далее перекроем метод onBackPressed в нашем FragmentActivity:

public class MyActivity extends FragmentActivity {
    @Override
    public void onBackPressed() {
        FragmentManager fm = getSupportFragmentManager();
        OnBackPressedListener backPressedListener = null;
        for (Fragment fragment: fm.getFragments()) {
            if (fragment instanceof  OnBackPressedListener) {
                backPressedListener = (OnBackPressedListener) fragment;
                break;
            }
        }
 
        if (backPressedListener != null) {
             backPressedListener.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }
}

Вытаскиваем все фрагменты, которые у нас есть. Ищем первый попавшийся, который реализует наш интерфейс OnBackPressedListener. Тут можно было придумать что-то, чтобы работать с несколькими обработчиками, но чаще всего он один. Если есть фрагмент, который реализует OnBackPressedListener, вызываем его единственный метод. Если нет — обрабатываем back как обычно.

Ну и, наконец, сам фрагмент:

public class MyFragment extends Fragment implements OnBackPressedListener {
    @Override
    public void onBackPressed() {
        // полезный код
    }
}

Плюс данного подхода в том, что можно, например, отнаследовать все наши activity от MyActivity и использовать OnBackPressedListener без каких-либо изменений в коде MyActivity.

Комментарии RSS

  1. №9323
    Yuriy Firs
    Yuriy Firs 28 окт. 2014 г., 16:54:51

    Александр, смотрю ты уже на Android перешел. Мобильная разработка всех поглощает? Или это просто хобби :)

  2. №9325
    Sam
    Sam 28 окт. 2014 г., 17:33:51

    Я не ограничиваю себя какой-то одной технологией или языком. В случае андройда это не хобби. Коммерческий проект.

  3. №9326
    Yuriy Firs
    Yuriy Firs 28 окт. 2014 г., 17:38:10

    Согласен. Я то в моб. разработке дальше ionicframework(cordova) не пошел пока.

  4. №10021
    Богдан
    Богдан 14 окт. 2015 г., 23:40:13

    Спасибо за ваш вариант. На основе вашего у меня родилось следующее решение:

    @Override
        public void onBackPressed() {
            Fragment fragment = getFragmentManager().findFragmentByTag("name");
            if (fragment != null && fragment.isVisible()) {
                    //  do something
            }else {
                super.onBackPressed();
            }
        }

    Я новечек важно ваше мнение. Конструкция вроде работает. Но могут ли быть с ней проблемы?

  5. №10025
    Sam
    Sam 20 окт. 2015 г., 15:49:57

    Могут. Как минимум, стоит учитывать, что использоваться может более одного фрагмента в одном activity.

  6. №10050
    Dont
    Dont 09 нояб. 2015 г., 23:55:02

    В ListActivity это выглядит примерно так:

    @Override
        public void onBackPressed()
        {
            try
            {
                if (file.getCanonicalPath().equals("/"))
                    super.onBackPressed();
                else
                    getPath(file.getParent());
            }
            catch (IOException e)
            {
                Toast.makeText(this, "IOException :" + e, Toast.LENGTH_SHORT).show();
            }
        }

    А как такое сделать в ListFragment и обычном Activity?

  7. №10137
    Капитан О.
    Капитан О. 23 дек. 2015 г., 19:20:55

    Sam, а почему вы пишете "андроЙд"? Или вы с такой же ошибкой пишите слова "плазмоЙд", "гиперболоЙд", "стероЙд" и "планетоЙд"? Домашнее задание: попробуйте произнести вслух эти слова так, как они написаны - с буквой "Й". Постарайтесь при этом не завязать язык в узел.

  8. №10139
    Sam
    Sam 23 дек. 2015 г., 23:54:27

    Капитан О., описочка вышла. Кстати, произнести с «й» вполне получается и при этом ничего в узел не завязывается. Это сочетание звуков вполне характерно для английского.

  9. №10190
    Гайрат
    Гайрат 13 янв. 2016 г., 16:01:40

    Спасибо за статью! Очень наглядный пример как ловить onBackPressed в фрагментах)

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.