- Android Studio: Переключение между Activity
- Android navigation component. Простые вещи, которые приходится делать самому
- Переключение между пунктами меню
- Открытие новой Activity
- Передача параметров в startDestination
- Навигация для Android с использованием Navigation Architecture Component: пошаговое руководство
- Часть 1. Подготовительные работы
- 1.1. Создание проекта
- 1.2. Зависимости (Dependencies)
- 1.3. Страницы: создание фрагментов
- 1.4. Адреса: файл ресурсов типа «Navigation»
- 1.5. Фрейм: виджет NavHostFragment
- Часть 2. Элементы навигации
- 2.1. Навигация с помощью кнопок
- 2.2. Боковое меню (drawer)
- 2.2.1. Ресурсный файл меню
- 2.2.2. Шаблон DrawerLayout и виджет NavigationView в макете активности
- 2.2.3. Подключение бокового меню в классе активности
- 2.3. Кнопка и название фрагмента на панели инструментов
- 2.4. Нижнее меню (Bottom Navigation)
- 2.5. Всплывающее меню (Overflow Menu)
- Краткие выводы и ссылка на github
Android Studio: Переключение между Activity
Рабочая среда Android Studio позволяет протестировать готовое приложение, для этого Вам необходимо создать виртуальное устройство. Для этого перейдите в AVD Manager.
Назовём рабочую область BackActivity.
Теперь мы возвращаемся к MainActivity, и к кнопке «Старт» пишем обработчик, для начала добавим строку:
Можно и в режиме дизайна, указать метод onClick:
Сразу укажем кнопке ID (buttonBack).
После, открываем MainActivity.java, и в метод Create добавляем строку:
Button buttonBack = (Button)findViewById(R.id.buttonBack);
Далее необходимо навести каретку на (Button), вызвать контекстное меню зажав клавиши Alt+Enter и выбрать импорт класса.
Теперь, сразу после, добавим строку:
Программа нам говорит об ошибке, чтобы её исправить нужно отредактировать строку:
public class MainActivity extends AppCompatActivity <
и заменить её на:
public class MainActivity extends AppCompatActivity implements View.OnClickListener<
Теперь добавляем следующие строки:
И импортируем класс Intent (в противном случае выдаст ошибку Cannot find symbol class Intent).
Шалость удалась, у нас есть работающая кнопка, которая переносит нас на новую Activity. Наполнять Activity содержимым буду уже в следующих обзорах.
Источник
Android navigation component. Простые вещи, которые приходится делать самому
Всем привет! Хочу рассказать об особенностях в работе Navigation Architecture Component, из-за которых у меня сложилось неоднозначное впечатление о библиотеке.
Эта статья не пошаговая инструкция, в ней опущены детали реализации, чтобы сосредоточить внимание на ключевых моментах. В интернете есть немало одинаковых примеров использования (есть и переводы) — они помогут познакомиться с библиотекой. Так же перед чтением предлагаю изучить документацию.
Сразу скажу, библиотеку безусловно считаю полезной и не исключаю возможности неверного использования, но, пожалуй, я перепробовал всё прежде чем писать эту статью.
Итак, вот сценарии, при реализации которых ожидания по функционалу не совпали с реальностью в реализации:
- переключение между пунктами меню в navigation drawer
- открытие новой Activity со своим графом навигации
- передача параметров в startDestination
Переключение между пунктами меню
Это одна из тех функций, которые повлияли на решение использовать Navigation Component.
Нужно всего лишь сделать одинаковыми id пунктов меню
и id экранов (destination в графе навигации)
затем нужно связать меню с контроллером навигации:
Навигация в меню заработала — ну разве не чудо?!
Обратите внимание на «гамбургер» (иконка меню), при переключении между пунктами меню он меняет своё состояние на кнопку «назад». Такое поведение показалось непривычным (привычное — как в приложении play market) и, какое-то время, я пытался разобраться, что же сделал не так?
Всё так! Перечитав документацию по принципам навигации (а именно: пункты два и три), понял, что «гамбургер» показывается только для startDestination, вернее так: кнопка «назад» показывается для всех, кроме startDestination. Ситуацию можно поменять применив различные уловки в подписке (addOnNavigatedListener()) на изменение destination, но их даже описывать не стоит. Работает так, нужно смириться.
Открытие новой Activity
Activity может выступать в качестве navigation host и, в то же время, в графе навигации может выступать в роли одного из destination. Открытие Activity без вложенного графа навигации работает как ожидается, то есть вызов:
осуществит переход (как в случае с фрагментами) и откроет запрошенную Activity.
Гораздо интереснее рассмотреть случай, когда целевая Activity сама выступает в роли navigation host, то есть вариант 2 из документации:
В качестве примера давайте рассмотрим Activity для добавления заметки. В ней будет основной фрагмент с полями ввода EditFragment, он в графе навигации будет startDestination. Давайте положим, что при редактировании нам нужно прикрепить фото, для этого будем переходить к PhotoFragment для получения снимка с камеры. Граф навигации будет выглядеть так:
EditActivity мало отличается от MainActivity. Основное отличие в том, что на EditActivity нет меню:
Activity открывается, навигация внутри неё работает:
Опять обратим внимание на кнопку навигации в toolbar — на стартовом EditFragment нет кнопки «Назад к parent Activity» (а хотелось бы). С точки зрения документации, тут всё законно: новый граф навигации, новое значение startDestination, на startDestination не показывается кнопка «Назад», конец.
Для тех, кому хочется вернуть привычное поведение c parent activity, сохранив при этом функционал переключения между фрагментами, могу предложить такой костыль подход:
Подписка нужна для того, чтобы для NavigationUI.ActionBarOnNavigatedListener все destination не являлись startDestination. Таким образом NavigationUI.ActionBarOnNavigatedListener не будет скрывать кнопку навигации (за деталями стоит обратиться к исходникам). Добавим к этому обработку onSupportNavigateUp() штатным образом на startDestination и получим то, что хотелось.
Стоит сказать, что решение это далеко от идеала хотя бы потому, что это неочевидное вмешательство в поведение библиотеки. Полагаю, могут возникнуть проблемы в случае использования deep links (ещё не проверял).
Передача параметров в startDestination
В Navigation Component есть механизм передачи параметров от одного destination другому. Есть даже инструмент для обеспечения безопасности типов за счёт кодогенерации (неплохо).
Сейчас мы разберём случай, из-за которого я не смог поставить твёрдую пятёрку этому функционалу.
Вернёмся к EditActivity, достаточно привычный сценарий, когда одна Activity используется для создания и редактирования объектов. При открытии объекта для редактирования в Activity нужно передать, например, id объекта — давайте сделаем это штатным образом:
Я добавил параметр непосредственно в корневой элемент графа (navigation), но можно добавить в целевой фрагмент. От этого изменится только способ получения параметра.
Я добавил add и edit action’s в одни из фрагментов, так они будут доступны только из него.
В этом примере ImportFragmentDirections — автоматически сгенерированый safe-args класс.
Вы, наверняка, обратили внимание на особенности получения параметров в EditFragment. Так работает, потому что edit action (из пункта 1) передаёт аргументы в EditActivity, а она, в свою очередь, почему-то жадничает не передаёт её в граф (например, вызовом navController.graph.setDefaultArguments()). Эту особенность можно обойти, если вручную подготовить navigation controller. Один из способов описан на StackOwerflow.
Пожалуй, наибольшая сложность возникнет при одновременном использовании в качестве startDestination и обычного destination. То есть, при переходе и передаче параметров в startDestination из любого другого destination этого графа, фрагменту придётся самостоятельно определять, откуда извлекать параметры: из arguments или из intent.extras. Это нужно иметь ввиду при проектировании переходов с передачей параметров.
Резюмируя, хочу отметить, что сам не перестал использовать библиотеку и, несмотря на перечисленные недостатки особенности, считаю её достаточно полезной, чтобы рекомендовать к использованию. Очень надеюсь, что в следующих релизах изменится ситуация по крайней мере с передачей параметров в startDestination.
Источник
Навигация для Android с использованием Navigation Architecture Component: пошаговое руководство
Попробуем, пользуясь официальным руководством и примерами кода, построить работающую систему навигации для будущего многоэкранного приложения в соответствии со стандартами Navigation Architecture Component. Статья включает следующие разделы:
Часть 1. Подготовительные работы
— 1.1. Создание проекта
— 1.2. Зависимости (Dependencies)
— 1.3. Страницы: создание фрагментов
— 1.4. Адреса: файл ресурсов типа «Navigation»
— 1.5. Фрейм: виджет NavHostFragment
Часть 2. Элементы навигации
— 2.1. Навигация с помощью кнопок
— 2.2. Боковое меню (Drawer)
— 2.3. Панель инструментов: Toolbar вместо ActionBar
— 2.4. Нижнее меню (Bottom Navigation)
— 2.5. Всплывающее меню (Overflow Menu)
Краткие выводы и ссылка на github
Часть 1. Подготовительные работы
1.1. Создание проекта
Нам понадобятся базовые знания Котлина, IDE Android Studio версии не ниже 3.3, смартфон или эмулятор с версией API 14 или выше.
Создадим в Android Studio новый проект под названием «Navigation2019».
IDE создаст файл главной активности «MainActivity.kt» и его макет (шаблон) «activity_main.xml».
1.2. Зависимости (Dependencies)
Откроем файл «build.gradle» модуля (не проекта, а именно модуля) и в блок «dependencies» добавим необходимые зависимости:
Мы использовали библиотеки версии 1.0.0, но в будущем ситуация может измениться. Проверить, какие версии библиотек являются актуальными, можно здесь.
1.3. Страницы: создание фрагментов
Фрагменты — это «страницы» нашего будущего приложения. Кликнув правой кнопкой на каталоге с файлами классов, командой «New -> Fragment -> Fragment(Blank)» создадим «Fragment1».
IDE создаст kt-файл с классом фрагмента и xml-файл с макетом фрагмента. Таким же образом сгенерируем ещё три фрагмента («Fragment2», «Fragment3», «Fragment4»). Мы будем использовать их для создания четырёх разных типов навигации по приложению.
1.4. Адреса: файл ресурсов типа «Navigation»
Кликнув правой кнопкой мыши по папке «res», создадим файл ресурсов типа «Navigation» с названием «routes.xml» («маршруты»).
Откроем созданный файл и с помощью кнопки «New Destination» добавим в навигационную схему наши фрагменты.
«Хватаясь» мышкой за точку в середине правой стороны фрагмента, соединим фрагменты друг с другом так, как они должны быть связаны в приложении.
В соответствии с их названиями, наши фрагменты получат идентификаторы (id) «fragment1», «fragment2», «fragment3», «fragment4». Это «адреса», которые будут использоваться при указании пунктов назначения («destinations») в инструкциях навигационному контроллеру.
Кроме «id», каждый тег «fragment» содержит ещё три параметра: «name», «label» и «layout». Параметры «name» и «layout» нас сейчас не интересуют. Единственное, что стоит отредактировать в файле «routes.xml» — это названия («label») фрагментов. Заменим их на «Фрагмент №1», «Фрагмент №2», «Фрагмент №3» и «Фрагмент №4».
1.5. Фрейм: виджет NavHostFragment
Откроем файл макета «res/layout/activity_main.xml» и удалим текстовый виджет «Hello World!», он нам не понадобится. В палитре (Palette) выберем раздел «Контейнеры» (Containers) и перетащим оттуда на макет активности виджет NavHostFragment (указав наш файл «routes» в качестве источника информации для него). Он выполнит роль фрейма, в котором будут выводиться различные фрагменты приложения.
Изменим id фрагмента на «navFragment». Код макета главной активности будет выглядеть теперь так:
На этом подготовительные работы завершены, теперь можно приступать непосредственно к созданию элементов навигации.
Часть 2. Элементы навигации
2.1. Навигация с помощью кнопок
Откроем макет первого фрагмента («fragment_fragment1.xml»). Удалим ненужный текстовый виджет, изменим тип макета с «FrameLayout» на линейный вертикальный и добавим три кнопки с идентификаторами «button2», «button3», «button4» и соответствующими названиями «Фрагмент 2», «Фрагмент 3», «Фрагмент 4».
В методе «onCreateView» фрагмента получим ссылку на навигационный контроллер (объект «NavController») и запрограммируем поведение при нажатии на кнопки: командой «setOnClickListener» для каждой кнопки создадим слушателя кнопки, который при клике по кнопке будет передавать навигационному контроллеру адрес (id) точки назначения вместе с командой переместиться (navigate) на указанный адрес.
Проверим, как работают наши кнопки.
Одна кнопка — одна строчка кода — и клик по кнопке перемещает нас к указанному фрагменту. Просто, не так ли?
Но без меню не очень удобно, приходится использовать кнопку «Назад» для возвращения на стартовый экран.
2.2. Боковое меню (drawer)
2.2.1. Ресурсный файл меню
В каталоге «res/menu» создадим ресурсный файл меню «drawer_menu.xml». Добавим в него пункты меню, каждый из которых представляет собой тег «item» с параметрами «id» (должен соответствовать таковому в навигационном графе «routes.xml», «title» (заголовок, он может быть другим), «icon» (мы используем одну и ту же картинку для всех пунктов, но, конечно же, они могут быть разными) и др. Наше меню будет выглядеть так:
2.2.2. Шаблон DrawerLayout и виджет NavigationView в макете активности
Откроем файл макета активности «activity_main.xml».
После первого тега (xml version…) добавим начало тега «DrawerLayout».
В конец файла добавим виджет «NavigationView» и окончание тега «DrawerLayout».
2.2.3. Подключение бокового меню в классе активности
Откроем файл «MainActivity.kt» и в методе «onCreate» получим ссылку на «navController» (в активности это выглядит чуть сложнее, чем было во фрагментах).
Затем включим боковое меню:
Код класса теперь выглядит так:
Теперь меню появляется в ответ на свайп от левого края экрана:
Хорошо было бы добавить и кнопку слева-вверху для вызова бокового меню, верно?
2.3. Кнопка и название фрагмента на панели инструментов
Существующий по умолчанию ActionBar, как рекомендует официальное руководство, заменим на Toolbar.
Чтобы отключить существующий ActionBar, в файле «res/values/styles.xml» найдём строку
и заменим «DarkActionBar» на «NoActionBar».
Отлично, ActionBar мы отключили.
Теперь добавим Toolbar. Откроем файл «activity_main.xml», в палитре (Palette) выберем раздел «Контейнеры» (Containers) и перетащим оттуда на макет активности виджет «Toolbar». Панель инструментов добавлена, но она пока пуста.
Переходим в файл активности «MainActivity.kt». Чтобы на Toolbar вывести кнопку и название текущего фрагмента, в метод «onCreate()» добавим следующие строки:
Toolbar теперь выводит название фрагмента и кнопку «Вверх» (Up) для вложенных фрагментов.
Кнопка «вверх» в android’е почему-то обозначается стрелкой «влево»:
Чтобы на стартовом экране приложения выводилась кнопка-гамбургер, нам необходимо в конфигурацию панели инструментов добавить параметр «drawerLayout», который содержит id виджета DrawerLayout из файла «activity_main.xml».
Клик по этой кнопке выводит боковое меню.
2.4. Нижнее меню (Bottom Navigation)
Иногда бывает необходимо акцентировать внимание пользователя на определённых действиях, и эффективно сделать это помогает нижнее меню. Добавим его в третий фрагмент.
Сначала создадим ресурсный файл меню «bottom_nav_menu.xml» с парой ссылок. Затем откроем макет фрагмента №3 (файл «fragment_fragment3.xml») и перетащим на него виджет «BottomNavigationView», попутно согласившись с предложением IDE добавить в dependencies библиотеку «com.android.support:design».
Если бы мы создавали нижнее меню не для одного фрагмента, а сразу для всех, то в метод «onCreate» класса активности (файл «MainActivity.kt») нужно было бы включить следующий код:
Конечно, и виджет «BottomNavigationView» в таком случае надо было бы поместить в макет активности, а не фрагмента.
Но поскольку данное меню нам требуется только во фрагменте №3, то и редактировать мы будем класс фрагмента (файл «Fragment3.kt»), а код будет выглядеть чуть сложнее:
В итоге мы получим нижнее меню, которое будет выводиться только в 3-м фрагменте.
То же самое, но с другими ссылками, сделаем и в 4-м фрагменте.
2.5. Всплывающее меню (Overflow Menu)
Ещё один вид меню — всплывающее меню, которое выводится при клике по кнопке (трём вертикально расположенным точкам) в правом верхнем углу экрана.
Создадим ресурсный файл меню «top_right_menu.xml» с необходимыми ссылками.
В файле «MainActivity» в метод «onCreate» перед «toolBar.setupWithNavController. » добавим строку «setSupportActionBar(toolBar)».
И далее в этом же классе переопределим два метода:
Нажатие на верхнюю правую кнопку теперь отображает всплывающее меню:
Краткие выводы и ссылка на github
Очевидно, что Navigation Architecture Component существенно облегчает труд разработчика. Сложные в прошлом задачи теперь решаются несколькими строчками кода.
Поскольку главной целью данной публикации было осветить базовые алгоритмы создания навигации в android-приложении, многие детали реализации были умышленно оставлены за кадром.
Мой график работы обычно не позволяет поддерживать дискуссии, но Ваши комментарии в любом случае будут полезны для посетителей сайта и потому всегда приветствуются.
Источник