Нажмите "Enter", чтобы перейти к содержанию

Навигация на андроид: Рейтинг лучших навигаторов для Android 2021 года. ТОП 5 GPS-навигаторов для Андроид

Содержание

Урок 13. Навигация в Android приложении. Интеграция в новый проект, добавление пунктов назначения (destinations) и переходов между ними (actions)

Продолжаем серию уроков по разработке android-приложений в Android Studio на языке Kotlin.

На прошлом уроке мы познакомились с библиотекой Navigation Architecture Component, которая позволяет пользователям перемещаться между различными экранами и расположениями контента в андроид-приложении. Но, судя по комментариям к уроку на нашем канале, урок был понятен не всем, кому-то не понравилась подача материала с использованием готового проекта. Поэтому мы решили исправиться и сделать новый урок с созданием проекта с нуля и добавлением в него навигации.

В этом уроке мы создадим новый проект и добавим в него навигацию пошагово с самого начала, создадим несколько мест назначения для навигации в приложении, а также переход между ними.

Создаем новый проект в Android Studio

Откройте среду разработки Android Studio. Создайте новый проект с использованием шаблона Empty Activity.

Для работы с компонентом навигации понадобится среда разработки Android Studio 3.3 или более новой версии. При разработке приложений я рекомендую всегда использовать стабильный релиз. На данный момент, это версия 3.6.1.

Чтобы убедиться, что вы используете стабильный релиз Android Studio, проверьте, что для обновления среды разработки используется стабильный канал. Для этого откройте меню Help> Check for updates> Configure automatic updates. В поле Автоматической проверки обновления должен быть выбран Stable Channel.

Добавляем в проект библиотеку Navigation Architecture Component

Чтобы добавить библиотеку Navigation Architecture Component в наш проект, откройте файл сборки build.

gradle модуля App. Добавьте в секцию dependencies{}  такие зависимости:

// Navigation implementation «androidx.navigation:navigation-fragment-ktx:2.3.0-beta01″ implementation «androidx.navigation:navigation-ui-ktx:2.3.0-beta01″ // Dynamic Feature Module Support implementation «androidx.navigation:navigation-dynamic-features-fragment:2.3.0-beta01″ // Testing Navigation androidTestImplementation «androidx.navigation:navigation-testing:2.3.0-beta01»

// Navigation

    implementation «androidx.navigation:navigation-fragment-ktx:2.3.0-beta01»

    implementation «androidx.navigation:navigation-ui-ktx:2.3.0-beta01»

 

    // Dynamic Feature Module Support

    implementation «androidx.navigation:navigation-dynamic-features-fragment:2.3.0-beta01»

 

    // Testing Navigation

    androidTestImplementation «androidx. navigation:navigation-testing:2.3.0-beta01″

 

 

Также убедитесь, что в общем файле сборки build.gradle проекта присутствуют ссылки на репозитории google() и jcenter() :

allprojects {     repositories {         google()         jcenter()     } }

allprojects {

    repositories {

        google()

        jcenter()

    }

}

 

 

После всех изменений синхронизируйте проект с Gradle.

Navigation graph

Навигация в приложении происходит между пунктами назначения, или destinations. Пункты назначения  содиняются между собой при помощи действий – actions. Другими словами, destinations – это экраны приложения, а actions —  пути между ними, по которым может перемещаться пользователь.

В приложении должен быть специальный XML-документ, который описывает все пункты назначения и связывающие их действия – это навигационный граф. Давайте его создадим.

Кликните правой кнопкой мыши на папке res вашего проекта и в контекстном меню выберите пункты New > Android Resource File. Откроется диалог New Resource File, где нужно указать имя файла, например, «nav_graph». В выпадающем списке Resource type  выберите Navigation. Нажмите кнопку ОК для закрытия диалога и создания файла навигационного графа.

В результате Android Studio создаст в папке res папку navigation, и в ней файл nav_graph.xml.

Navigation Editor

После создания навигационного графа он откроется в редакторе навигации. Как и файлы разметки его можно редактировать двумя способами – либо в визуальном редакторе, либо в XML. Окно редактора навигации похоже на окно редактора макетов – слева список пунктов назначения, в центре визуальное представление, справа панель атрибутов выбранного компонента. Кнопками можно переключаться между представлениями – дизайн, текст или комбинированное представление.

Переключитесь на текстовое представление:

<?xml version=»1. 0″ encoding=»utf-8″?> <navigation xmlns:android=»http://schemas.android.com/apk/res/android»             xmlns:app=»http://schemas.android.com/apk/res-auto»             android:id=»@+id/nav_graph»> </navigation>

<?xml version=»1.0″ encoding=»utf-8″?>

<navigation xmlns:android=»http://schemas.android.com/apk/res/android»

            xmlns:app=»http://schemas.android.com/apk/res-auto»

            android:id=»@+id/nav_graph»>

 

</navigation>

 

 

В среде разработки можно увидеть, что тег navigation подчеркнут красным, а при наведении на него отображается  сообщение о том, что навигационный граф не связан ни с одним файлом разметки, содержащим компонент NavHostFragment. Давайте это исправим.

NavHostFragment

Для каждого навигационного графа должен быть определен хост. Например, хостом может служить активити, к которому привязаны фрагменты, представляющие пункты назначения для навигации. Причем для каждого такого активити должен быть определен свой навигационный граф.

Чтобы добавить хост, откройте файл разметки activity_main.xml в редакторе макетов. Переключитесь на вкладку дизайна. В палитре компонентов слева найдите в группе Containers компонент NavHostFragment и перетащите его в макет активити. При этом откроется окно выбора навигационного графа, где показан тот, который мы недавно создали – выберите его. Выполните привязку компонента к краям экрана, нажав и потянув поочередно каждый из маркеров к своему краю экрана. Затем переключитесь в режим текста и укажите размеры для компонента NavHostFragment – 0dp. Компонент займет весь экран.

Добавление пунктов назначения

Давайте добавим новый фрагмент в приложение, шелкнув правой клавишей мыши по главному пакету приложения и выбрав пункты контекстного меню: New> Fragment> Fragment (Blank). После содания макет разметки этого фрагмента будет доступен для выбора в редакторе навигации. Кликните по кнопке с изображением экрана с зеленым плюсиком в правом нижнем углу, и в окне добавления пункта назначения вы увидите список макетов разметки. Выберите только что добавленный фрагмент, и он добавится на центральную панель. Обратите внимание – он обозначен иконкой в виде домика – это значит, что это домашний, стартовый экран для этого навигационного графа.

Вы можете добавить существующий фрагмент или активити в качестве пункта назначения, или создать его прямо из редактора навигации. Для создания нового пункта назначения нажмите кнопку Create new destination. Будет создан и добавлен на центральную панель новый фрагмент.

Также вместо пункта назначения можно добавить временный заполнитель —  placeholder. В редакторе навигации с заполнителями можно взаимодействовать так же, как и с обычными пунктами назначения, например, определять действия – actions. В текстовом представлении заполнитель обозначается тегами <fragment></fragment>, как и обычные фрагменты.

Перед тестированием приложения нужно заменить все заполнители настоящими пунктами назначения, иначе попытка перехода в приложении на placeholder завершится ошибкой.

Добавление переходов

Давайте пока удалим заполнитель и оставим два фрагмента. Добавим действие для перехода с одного экрана на другой. Как вы уже поняли, для этого нужно нажать маркер одного фрагмента и протянуть до другого. Добавится стрелочка, обозначающая действие – переход с одного фрагмента на другой.

Если мы посмотрим на текстовое представление, то увидим, что у домашнего фрагмента появился тег <action></action>, внутри которого обозначен идентификатор действия и пункт назначения.

Теперь откройте макет домашнего фрагмента и вместо шаблонного текста в поле TextView добавьте цифру 1, а размер текста установите побольше. Также добавьте сюда кнопку. В макете второго фрагмента аналогично напишите цифру 2.

Теперь в классе первого фрагмента переопределите метод жизненного цикла onViewCreated() и внутри него напишите код слушателя нажатия кнопки:

button. setOnClickListener{ view : View ->     view.findNavController().navigate(R.id.action_blankFragment_to_blankFragment222) }

button.setOnClickListener{ view : View ->

    view.findNavController().navigate(R.id.action_blankFragment_to_blankFragment222)

}

 

Здесь мы находим контроллер навигации и вызываем его метод navigate, которому передаем идентификатор действия (action), добавленного в редакторе навигации между фрагментами.

Проверка переходов в приложении

Теперь запустите приложение в эмуляторе или смартфоне. Обратите внимание – при открытии отображается домашний фрагмент, хотя мы его не прописывали в макете активити. Мы просто определили макет активити как хост навигационного графа, и теперь при старте этого активити библиотека навигации отображает нам фрагмент, указанный как домашний в этом графе.

Нажмите на кнопку, и выполнится действие – переход от первого фрагмента ко второму. Нажатие системной кнопки «Назад» вернет вас на первый экран. Это простейший пример навигации, а на следующем уроке мы разнообразим его и добавим более сложную навигацию в приложение.

Надеюсь, теперь вам будет более понятен материал прошлого урока, при желании вы можете пересмотреть его снова.

Исходный код проекта можно скачать по ссылке. Вопросы задавайте в комментариях. Спасибо за просмотр, до встречи на следующем уроке, и всем добра!

Урок 14. Навигация по условию в андроид приложении. Android Conditional Navigation & Firebase Authentication

Навигация для 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» добавим необходимые зависимости:

def nav_version = «1.0.0»
implementation «android.arch.navigation:navigation-fragment-ktx:$nav_version»
implementation «android.arch.navigation:navigation-ui-ktx:$nav_version»

Мы использовали библиотеки версии 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» найдём строку

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

и заменим «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-приложении, многие детали реализации были умышленно оставлены за кадром.

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

Файлы проекта находятся здесь.

Навигация в Android-приложении с помощью координаторов / Хабр

За последние несколько лет мы выработали общие подходы создания Android-приложений. Чистая архитектура, архитектурные шаблоны (MVC, MVP, MVVM, MVI), шаблон “репозиторий” и другие. Однако до сих пор нет общепринятых подходов к организации навигации по приложению. Сегодня я хочу поговорить с вами о шаблоне “координатор” и возможностях его применении в разработке Android-приложений.


Шаблон “координатор” часто используется в iOS-приложениях и был представлен Сорушем Ханлоу (Soroush Khanlou) с целью упростить навигацию по приложению. Есть мнение, что работа Соруша основана на подходе Application Controller, описанном в книге Patterns of Enterprise Application Architecture Мартином Фаулером (Martin Fowler).

Шаблон “координатор” призван решить следующие задачи:

  • борьба с Massive View Controller проблемой (о проблеме уже писали на хабре — прим. переводчика), которая зачастую проявляется с появлением God-Activity (активити с большим количеством обязанностей).
  • выделение логики навигации в отдельную сущность
  • переиспользование экранов приложения (активити/фрагментов) благодаря слабой связи с логикой навигации

Но, прежде чем начать знакомство с шаблоном и попробовать его реализовать, давайте взглянем на используемые реализации навигации в Android-приложениях.



Логика навигации описана в активити/фрагменте

Поскольку Android SDK требует Context для открытия новой активити (или FragmentManager для того, чтобы добавить фрагмент в активити), довольно часто логику навигации описывают непосредственно в активити/фрагменте. Даже примеры в документации к Android SDK используют этот подход.

class ShoppingCartActivity : Activity() {  
  override fun onCreate(b : Bundle?){
    super.onCreate(b)
    setContentView(R.layout.activity_shopping_cart)
    val checkoutButton = findViewById(R.id.checkoutButton)
    checkoutButton.setOnClickListener {
      val intent = Intent(this, CheckoutActivity::class.java)
      startActivity(intent)
    }
  }
}

В приведенном примере навигация тесно связана с активити. Удобно ли тестировать подобный код? Можно было бы возразить, что мы можем выделить навигацию в отдельную сущность и назвать ее, к примеру, Navigator, который может быть внедрен. Давайте посмотрим:

class ShoppingCartActivity : Activity() {
  @Inject lateinit var navigator : Navigator  
  override fun onCreate(b : Bundle?){
    super.onCreate(b)
    setContentView(R.layout.activity_shopping_cart)
    val checkoutButton = findViewById(R.id.checkoutButton)
    checkoutButton. setOnClickListener {
      navigator.showCheckout(this)
    }
  }
}
class Navigator {
   fun showCheckout(activity : Activity){
    val intent = Intent(activity, CheckoutActivity::class.java)
    activity.startActivity(intent)
  }
}

Получилось неплохо, но хочется большего.

Навигация с MVVM/MVP

Начну с вопроса: где бы вы расположили логику навигации при использовании MVVM/MVP?

В слое под презентером (назовем его бизнес-логикой)? Не очень хорошая идея, потому что скорее всего вы будете повторно использовать вашу бизнес-логику в других моделях представления или презентерах.

В слое представления? Вы действительно хотите перебрасывать события между представлением и презентером/моделью представления? Давайте посмотрим на пример:

class ShoppingCartActivity : ShoppingCartView, Activity() {
  @Inject lateinit var navigator : Navigator
  @Inject lateinit var presenter : ShoppingCartPresenter

  override fun onCreate(b : Bundle?){
    super. onCreate(b)
    setContentView(R.layout.activity_shopping_cart)
    val checkoutButton = findViewById(R.id.checkoutButton)
    checkoutButton.setOnClickListener {
      presenter.checkoutClicked()
    }
  }

  override fun navigateToCheckout(){
    navigator.showCheckout(this)
  }
}
class ShoppingCartPresenter : Presenter<ShoppingCartView> {
  ...
  override fun checkoutClicked(){
    view?.navigateToCheckout(this)
  }
}

Или если вы предпочитаете MVVM, можно использовать SingleLiveEvents или EventObserver

class ShoppingCartActivity : ShoppingCartView, Activity() {
  @Inject lateinit var navigator : Navigator
  @Inject lateinit var viewModel : ViewModel

  override fun onCreate(b : Bundle?){
    super.onCreate(b)
    setContentView(R.layout.activity_shopping_cart)
    val checkoutButton = findViewById(R.id.checkoutButton)
    checkoutButton.setOnClickListener {
      viewModel.checkoutClicked()
    }

    viewModel.navigateToCheckout.observe(this, Observer {
      navigator. showCheckout(this)
    })
  }
}
class ShoppingCartViewModel : ViewModel() {
  val navigateToCheckout = MutableLiveData<Event<Unit>>
  fun checkoutClicked(){
    navigateToCheckout.value = Event(Unit) // Trigger the event by setting a new Event as a new value
  }
}

Или давайте поместим навигатор в модель представления вместо использования EventObserver’а как было показано в предыдущем примере

class ShoppingCartViewModel @Inject constructor(val navigator : Navigator)  : ViewModel() {
  fun checkoutClicked(){
    navigator.showCheckout()
  }
}

Обратите внимание, что это подход может быть применен и к презентеру. Также мы игнорируем возможную утечку памяти в навигаторе в случае если он будет держать ссылку на активити.

Координатор

Так где же нам разместить логику навигации? Бизнес-логика? Ранее мы уже рассмотрели этот вариант и пришли к выводу, что это не лучшее решение. Перебрасывание событий между представлением и моделью представления может сработать, но это не выглядит элегантным решением. Более того, представление все еще отвечает за логику навигации, хоть мы и вынесли ее в навигатор. Следуя методу исключения у нас остается вариант с размещением логики навигации в модели представления и этот вариант кажется перспективным. Но должна ли модель представления заботиться о навигации? Разве это не просто прослойка между представлением и моделью? Вот почему мы пришли к понятию координатора.

“Зачем нам еще один уровень абстракции?” — спросите вы. Стоит ли того усложнение системы? В маленьких проектах действительно может получиться абстракция ради абстракции, однако в сложных приложениях или в случае использования A/B тестов координатор может оказаться полезным. Допустим, пользователь может создать аккаунт и залогиниться. У нас уже появилась некоторая логика, где мы должны проверить залогинился ли пользователь и показать либо экран логина либо главный экран приложения. Координатор может помочь в приведенном примере. Обратите внимание, что координатор не помогает писать меньше кода, он помогает вынести код логики навигации из представления или модели представления.

Идея координатора предельно проста. Он знает только какой экран приложения надо открыть следующим. Например, когда пользователь нажимает на кнопку оплаты заказа, координатор получает соответствующее событие и знает, что далее необходимо открыть экран оплаты. В iOS координатор используется в качестве сервис локатора, для создания ViewController’ов и управления бэкстеком. Это достаточно много для координатора (помним про принцип единственной ответственности). В Android-приложениях система создает активити, у нас множество инструментов для внедрения зависимостей и есть бекстек для активити и фрагментов. А теперь давайте вернемся к оригинальной идее координатора: координатор просто знает какой экран будет следующим.

Пример: Новостное приложение с использованием координатора

Давайте наконец-то поговорим непосредственно о шаблоне. Представим, что нам нужно создать простое новостное приложение. В приложении есть 2 экрана: “список статей” и “текст статьи”, который открывается по клику на элемент списка.

class NewsFlowCoordinator (val navigator : Navigator) {

  fun start(){
    navigator.showNewsList()
  } 

  fun readNewsArticle(id : Int){
    navigator.showNewsArticle(id)
  }
}

Сценарий (Flow) содержит один или несколько экранов. В нашем примере новостной сценарий состоит из 2 экранов: “список статей” и “текст статьи”. Координатор получился предельно простым. При старте приложения мы вызываем NewsFlowCoordinator#start() чтобы показать список статей. Когда пользователь кликает по элементу списка вызывается метод NewsFlowCoordinator#readNewsArticle(id) и показывается экран с полным текстом статьи. Мы все еще работаем с навигатором (об этом мы поговорим немного позже), которому мы делегируем открытие экрана. У координатора отсутствует состояние, он не зависит от реализации бекстека и реализует только одну функцию: определяет куда пойти дальше.

Но как соединить координатор с нашей моделью представления? Мы последуем принципу инверсии зависимостей: мы будем передавать в модель представления лямбду, которая будет вызываться когда пользователь тапает по статье.

class NewsListViewModel(
  newsRepository : NewsRepository, 
  var onNewsItemClicked: ( (Int) -> Unit )?
) : ViewModel() {
  
  val newsArticles = MutableLiveData<List<News>>

  private val disposable = newsRepository.getNewsArticles().subscribe { 
      newsArticles.value = it
  }

  fun newsArticleClicked(id : Int){
    onNewsItemClicked!!(id) // call the lambda
  }

  override fun onCleared() {
    disposable.dispose()
    onNewsItemClicked = null // to avoid memory leaks
  }
}

onNewsItemClicked: (Int) -> Unit — это лямбда, у которой один целочисленный аргумент и возвращает Unit. Обратите внимание, что лямбда может быть null, это позволит нам очистить ссылку для того чтобы избежать утечки памяти. Создатель модели представления (например, даггер) должен передать ссылку на метод координатора:

return NewsListViewModel(
  newsRepository = newsRepository,
  onNewsItemClicked = newsFlowCoordinator::readNewsArticle
)

Ранее мы упоминали навигатор, который и осуществляет смену экранов. Реализация навигатора остается на ваше усмотрение, поскольку зависит от вашего конкретного подхода и личных предпочтений. В нашем примере мы используем одну активити с несколькими фрагментами (один экран — один фрагмент со своей моделью представления). Я привожу наивную реализацию навигатора:

class Navigator{
  var activity : FragmentActivity? = null

  fun showNewsList(){
    activty!!.supportFragmentManager
      .beginTransaction()
      .replace(R.id.fragmentContainer, NewsListFragment())
      .commit()
  }

  fun showNewsDetails(newsId: Int) {
    activty!!.supportFragmentManager
      .beginTransaction()
      .replace(R.id.fragmentContainer, NewsDetailFragment.newInstance(newsId))
      .addToBackStack("NewsDetail")
      .commit()
    }
}

class MainActivity : AppCompatActivity() {
  @Inject lateinit var navigator : Navigator

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    navigator. activty = this
  }

  override fun onDestroy() {
    super.onDestroy()
    navigator.activty = null // Avoid memory leaks
  }
}

Приведенная реализация навигатора не идеальна, однако основная идея этого поста — введение в паттерн координатора. Стоит отметить, что поскольку навигатор и координатор не имеют состояния, то они могут быть объявлены в рамках приложения (например

Singleton

скоуп в даггере) и могут быть инстанциированы в Application#onCreate().

Давайте добавим авторизацию в наше приложение. Мы определим новый экран логина (LoginFragment + LoginViewModel, для простоты мы опустим восстановление пароля и регистрацию) и LoginFlowCoordinator. Почему бы не добавить новый функционал в NewsFlowCoordinator? Мы же не хотим получить God-Coordinator, который будет отвечать за всю навигацию в приложении? Также сценарий авторизации не относится к сценарию чтения новостей, верно?

class LoginFlowCoordinator(
  val navigator: Navigator
) {
  fun start(){
    navigator. showLogin()
  }

  fun registerNewUser(){
    navigator.showRegistration()
  }

  fun forgotPassword(){
    navigator.showRecoverPassword()
  }
}
class LoginViewModel(
  val usermanager: Usermanager,
  var onSignUpClicked: ( () -> Unit )?,
  var onForgotPasswordClicked: ( () -> Unit )?
) {
  fun login(username : String, password : String){
    usermanager.login(username, password)
    ...
  }
  ...
}

Здесь мы видим, что на каждый UI-ивент есть соответствующая лямбда, однако нет лямбды для коллбека успешного логина. Это также деталь реализации и вы можете добавить соответствующую лямбду, однако у меня есть идея получше. Давайте добавим RootFlowCoordinator и подпишемся на изменения модели.

class RootFlowCoordinator(
  val usermanager: Usermanager,
  val loginFlowCoordinator: LoginFlowCoordinator,
  val newsFlowCoordinator: NewsFlowCoordinator,
  val onboardingFlowCoordinator: OnboardingFlowCoordinator
) {

  init {
    usermanager.currentUser.subscribe { user ->
      when (user){
        is NotAuthenticatedUser -> loginFlowCoordinator. start()
        is AuthenticatedUser -> if (user.onBoardingCompleted)
                                    newsFlowCoordinator.start()
                                else
                                    onboardingFlowCoordinator.start()
      }
    }
  }

  fun onboardingCompleted(){
    newsFlowCoordinator.start()
  }
}

Таким образом, RootFlowCoordinator будет входной точкой нашей навигации вместо NewsFlowCoordinator. Давайте остановим наше внимание на RootFlowCoordinator. Если пользователь залогинен, то мы проверяем прошел ли он онбординг (об этом чуть позже) и начинаем сценарий новостей или онбординга. Обратите внимание, что LoginViewModel не принимает участия в этой логике. Опишем сценарий онбординга.

class OnboardingFlowCoordinator(
  val navigator: Navigator,
  val onboardingFinished: () -> Unit // this is RootFlowCoordinator.onboardingCompleted()
) {

  fun start(){
    navigator.showOnboardingWelcome()
  }

  fun welcomeShown(){
    navigator. showOnboardingPersonalInterestChooser()
  }

  fun onboardingCompleted(){
    onboardingFinished()
  }
}

Онбординг запускается вызовом OnboardingFlowCoordinator#start(), который показывает WelcomeFragment (WelcomeViewModel). После клика по кнопке “next” вызывается метод OnboardingFlowCoordinator#welcomeShown(). Который показывает следующий экран PersonalInterestFragment + PersonalInterestViewModel, на котором пользователь выбирает категории интересных новостей. После выбора категорий пользователь тапает по кнопке “next” и вызывается метод OnboardingFlowCoordinator#onboardingCompleted(), который проксирует вызов RootFlowCoordinator#onboardingCompleted(), который запускает NewsFlowCoordinator.

Посмотрим как координатор может упростить работу с A/B тестами. Я добавлю экран с предложением совершить покупку в приложении и буду показывать его некоторым пользователям.

class NewsFlowCoordinator (
  val navigator : Navigator,
  val abTest : AbTest
) {

  fun start(){
    navigator. showNewsList()
  } 

  fun readNewsArticle(id : Int){
    navigator.showNewsArticle(id)
  }

  fun closeNews(){
    if (abTest.isB){
      navigator.showInAppPurchases()
    } else {
      navigator.closeNews()
    }
  }
}

И снова мы не добавили никакой логики в представление или его модель. Решили добавить InAppPurchaseFragment в онбординг? Для этого понадобится изменить только координатор онбординга, поскольку фрагмент покупок и его viewmodel полностью независим от других фрагментов и мы свободно можем его повторно использовать в других сценариях. Координатор также поможет реализоваnь А/В тест, который сравнивает два сценария онбординга.

Полные исходники можно найти на гитхабе, а для ленивых я подготовил видеодемонстрацию

Полезный совет: используя котлин можно создать удобный dsl для описания координаторов в виде графа навигации.

newsFlowCoordinator(navigator, abTest) {

  start {
    navigator.showNewsList()
  } 

  readNewsArticle { id ->
    navigator. showNewsArticle(id)
  }

  closeNews {
    if (abTest.isB){
      navigator.showInAppPurchases()
    } else {
      navigator.closeNews()
    }
  }
}

Итоги:

Координатор поможет вынести логику навигации в тестируемый слабосвязанный компонент. На данный момент нет production-ready библиотеки, я описал лишь концепцию решения проблемы. Применим ли координатор к вашему приложению? Не знаю, это зависит от ваших потребностей и насколько легко будет интегрировать его в существующую архитектуру. Возможно, будет полезно написать небольшое приложение с использованием координатора.

ЧаВо:

В статье не упоминается использование координатора с шаблоном MVI. Возможно ли использовать координатор с этой архитектурой?

Да, у меня есть

отдельная статья

.

Гугл недавно представил Navigation Controller как часть Android Jetpack. Как координатор соотносится с навигацией от гугла? Вы можете использовать новый Navigation Controller вместо навигатора в координаторах или непосредственно в навигаторе вместо ручного создания транзакций фрагментов.

А если я не хочу использовать фрагменты/активити и хочу написать свой бекстек для управления вьюхами — получится ли использовать координатор в моем случае? Я тоже задумался об этом и работаю над прототипом. Я напишу об этом в своем блоге. Мне кажется, что конечный автомат здорово упростит задачу.

Привязан ли координатор к single-activity-application подходу? Нет, вы можете использовать его в различных сценариях. Реализация перехода между экранами скрыта в навигаторе.

При описанном подходе получится огромный навигатор. Мы же вроде пытались уйти от God-Object’a? Мы не обязаны описывать навигатор в одном классе. Создайте несколько небольших поддерживаемых навигатора, например, отдельный навигатор для каждого пользовательского сценария.

Как работать с анимациями непрерывных переходов? Описывайте анимации переходов в навигаторе, тогда активити/фрагмент не будет ничего знать о предыдущем/следующем экране. Как навигатор узнает когда запускать анимацию? Допустим, мы хотим показать анимацию перехода между фрагментами А и Б. Мы можем подписаться на событие onFragmentViewCreated(v: View) с помощью FragmentLifecycleCallback и при наступлении этого события мы можем работать с анимациями так же, как мы это делали непосредственно в фрагменте: добавить OnPreDrawListener чтобы дождаться готовности и вызвать startPostponedEnterTransition(). Примерно так же можно реализовать анимированный переход между активити с помощью ActivityLifecycleCallbacks или между ViewGroup с помощью OnHierarchyChangeListener. Не забудьте потом отписаться от событий чтобы избежать утечек памяти.

Подборка приложений на Android для навигации — Наш Урал

Тут представлены как и специализированные приложения, так и универсальные навигаторы. Все приложения есть на google play, и просто легки в поиске в интернете.
1. МАРS.МЕ
Карты только векторные. Карты быстрые, можно включить линии высот. Обозначены отели от Booking. Есть оффлайн-автомаршрутизация. Категории POI городские. Родники и турстоянки находятся поиском по названию. Записи трека нет. На карте показывается линия последних перемещений за указанное время (от последнего часа до последних суток), но скачать оттуда трек нельзя. Можно отмечать и экспортировать точки, импортировать точки и треки. Нет навигации по импортированным трекам. Есть очень удобное ведение к точке (крупная стрелка показывает направление, указаны расстояние до точки и её название).
Резюме: подойдёт тем, кому нужно простое приложение с минимумом функций. Наличие только одного типа карт компенсируется возможностью заранее подготовиться, с помощью компьютера отметить точки и проложить маршруты, а затем импортировать в приложение. Функция ведения к точке по прямой (очень полезная в дикой природе) реализована одним из самых лучших способов среди подобных приложений.
2. Мару.сz
Векторные карты: быстрые, есть линии высот, оффлайн-автомаршрутизация. Есть родники, но нет стоянок. Категории POI городские. Поиск по названию находит родники, но не находит стоянки. Карты обновляются примерно раз в полгода (у конкурентов – каждые 1-2 месяца). Спутниковые снимки от Bing, кэшируются при просмотре, но закачать заранее нельзя. Погода в любой точке, медицинский справочник + поиск ближайших медучреждений. Многие функции, связанные с треками и точками, доступны только после регистрации. Ряд функций доступны только через веб-интерфейс: экспорт-импорт треков, рисование трека вручную (показывается высотный профиль). Импортировать и экспортировать точки нельзя (только скопировать координаты или поделиться ссылкой на конкретную точку). Нет навигации по импортированным трекам и ведения к точке. Точка показывается на карте только если открыть её в меню. Во время записи трека появляется панель со скоростью, пройденным расстоянием и временем. Других панелей с данными нет. Можно добавлять фотографии, смотреть чужие фотографии.
Резюме: бесплатность и симпатичная с виду карта привлекают. Но приложение подойдёт только тем, кому нужен только просмотр карты и больше почти ничего. К тому же, ввиду отсутствия на карте стоянок, приложение, очевидно, рассчитано только на однодневные походы.
3. Guru Марs
Растровые, векторные и онлайн-карты. Карты быстрые, есть линии высот. Тропинки тонкие, грунтовые дороги – белый пунктир. Оффлайн-поиск по названию, категориям и адресу. Запись трека, работа с точками, направление на точку и расстояние до неё. Оффлайн-автомаршрутизация. Ручная прокладка маршрута в виде ломаной линии. Навигация по трекам. Коллекции – папки точек и треков. Экспорт-импорт. Панель приборов (скорость, высота, пройденное расстояние и время в пути).
Резюме: приложение довольно удобное, имеет «среднее» количество функций (не слишком много, не слишком мало), и это нравится многим. Основной минус – цена, которая очень сильно завышена.
4. ОsmАnd
Растровые, векторные и онлайн-карты. Накладывание слоёв. На слабых смартфонах векторные карты подтормаживают. Внешний вид векторной карты настраивается, есть контрастный хорошо читаемый стиль. Можно добавить линии высот (плагин за 3 доллара или бесплатно скачать файл с высотами здесь). Оффлайн-поиск по названию, категориям, координатам и адресу. Запись трека, работа с точками, направление на точку и расстояние до неё (в том числе на две точки одновременно). Оффлайн-автомаршрутизация. Ручная прокладка маршрута. Навигация по трекам. Папки точек и треков. Экспорт-импорт. Геопривязанные фотографии от Mapillary. Оффлайн-Википедия. Настраиваемые правая панель и кнопка быстрого действия. Зуммирование кнопками громкости и разблокировка без свайпа. Нет ведения по маршруту из точек. Интерфейс не везде интуитивно понятный, местами перегруженный (например, раздел меню с маркерами). Мало общих настроек, много настроек сосредоточены в профилях. Наличие дополнительных плагинов (морские карты, лыжные карты и т.д.).
Резюме: лучшее приложение из категории «приложений для широких масс». Множество функций, разумная цена, регулярные скидки, возможность полноценно пользоваться бесплатной версией. Основной минус – интерфейс местами не очень удобен.
5. OziExplorer
Только растровые карты. Нет онлайн-карт. Работа с точками, треками и маршрутами. Нет автомаршрутизации. Панели приборов (пользовательские экраны). Есть программа для создания пользовательских экранов (довольно сложная). Неудобный интерфейс. Единственный плюс – удобное переключение между менее подробными и более подробными картами.
Резюме: приложение морально устарело и ощутимо уступает другим подобным приложениям. При этом имеет неоправданно высокую цену.
6. Советские военные карты
Онлайн-карты: Генштаб СССР (не подробнее километровки), OSM, спутник. Растровые оффлайн-карты. Векторные карты (загрузка из меню приложения) без линий высот, без ряда объектов, с не очень удачными темами. Работа с точками, треками, маршрутами. Создание папок. Экспорт-импорт. Запись треков. Ручная прокладка маршрутов. Ведение по маршрутам. Ведение к точке. Удобный частично настраиваемый интерфейс. Удобный компас (но подтормаживает). Панель приборов (настраиваемая).
Резюме: довольно удобное приложение, не перегруженное функциями, но имеющее всё необходимое для программы-навигатора по дикой природе. Минусы – неудачное отображение векторных карт и немного завышенная цена.
7. AlpineQuest
Растровые онлайн- и оффлайн-карты. Очень много функций работы с растровыми картами (наложение нескольких слоёв, прозрачность, яркость, контрастность, насыщенность, наборы слоёв). Онлайн-поиск. Запись трека, работа с точками, расстояние до точки и направление на неё. Ручная прокладка маршрутов и треков. Автопрокладка маршрута онлайн (без навигации). Папки меток. Экспорт-импорт. Зуммирование кнопками громкости. Интерфейс специфический, требуется время на его освоение и привыкание. На слабых смартфонах работает хорошо. Панели с данными и путевой компьютер (не очень удобные). Ориентация на истинный север с учётом магнитного склонения. Удобный компас (показывает направление на выбранную точку).
Резюме: приложение «на любителя». На мой взгляд, и интерфейс специфический, и функции: каких-то чересчур много, а каких-то не хватает. Но ряд пользователей считает иначе. Они находят интерфейс удобным, а тот набор функций, который имеется в приложении, их практически полностью устраивает.
8. OruxMaps
Много различных функций по работе с картами, точками, треками, маршрутами. Нет возможности скачать векторные карты прямо из приложения. Векторная карта с сайта OpenAndroMaps в OruxMaps отображается без линий высот (для появления линий высот нужно дополнительно скачать темы). Векторная карта ощутимо тормозит. Настраиваемый (например, два размера кнопок на правой и левой панелях), но неудобный интерфейс. Русифицирован только наполовину (у старых версий – полностью). Неудобный компас.
Резюме: большое количество функций и бесплатная версия, почти не уступающая платной. Но при этом – очень неудобный интерфейс, к тому же более чем наполовину – англоязычный. И именно интерфейс убивает всякое желание осваивать это приложение.
9. Locus Map
Растровые, векторные и онлайн-карты. Внешний вид векторной карты настраивается. Линии высот присутствуют. Встроенный магазин карт (три карты бесплатно, рождественские скидки) + сторонние карты. Оффлайн-поиск по категориям, координатам и адресу. Запись трека, работа с точками, направление на точку и расстояние до неё (уведомление о прибытии). Добавление высот к точкам и трекам (маршрутам). Оффлайн-автомаршрутизация при подключении BRouter (без него – только онлайн). Ручная прокладка маршрута. Навигация по трекам. Ведение по маршруту из точек. Папки точек и треков. Экспорт-импорт. Зуммирование кнопками громкости и разблокировка без свайпа. Интерфейс удобный, настраиваемый. На слабых смартфонах работает хорошо. Пользовательские экраны и маршрутные компьютеры. Магнитное склонение, ориентация на истинный север. Большой удобный компас. Наличие плагинов (дополненная реальность и т.д.). Отображение на карте геопривязанных фотографий, хранящихся на смартфоне.
Резюме: лучшее приложение из категории «приложений для дикой природы». Множество функций, невысокая цена, возможность полноценно пользоваться бесплатной версией, удобный интерфейс.

Автор: Владимир Пузырев

исходный текст: https://www.facebook.com/groups/puzyrev/posts/4042094292519169/

иллюстрация из поста

Интересно? Расскажи друзьям!

Штатная android мультимедиа навигация ауди карты установка обновление — KIBERCAR

AirTouch Performance это самый быстрый в мире бортовой компьютер на платформе Android, созданный для использования в связке с оригинальным монитором автомобиля. Он в разы быстрее аналогичных устройств других производителей.

Операционная система Android 10.0

Процессор Мощный 10-и ядерный процессор ARM Cortex-A72 + [email protected] 0GHz Hexa core + ARM Mali-T860 Tetra core

HDMI выход Поддержка 4K Video

Объем внутренней памяти 32Gb eMMC

Память 4Gb DDR3

Слот под micro SD Поддержка до 128Gb

USB USB2. 0 High Speed Port x 2

USB 3.0 3.0 USB3.0 5.0Gbps Port x 1

Беспроводная связь 2.4GHz/5GHz Dual-Band Wi-Fi, Support 802.11a/b/g/n/ac, Bluetooth 4.1

GPS Ublox8 (GPS/GLONASS/BEIDOU/GALILEO/ QZSS/SBAS)

Тачскрин управление Емкостной, резистивный, UART

Внешний интерфейс Digital LVDS выход: 1280×720\ 1540х720\ 800х480\ 1024х768\ 1440х540

HDMI HDMI 2. 0, Support maximum [email protected] display

Динамики 2 Вт

Входы / выходы Выход Stereo Audio, микрофон (распознавание голоса), FMT, выход Mute

Питание 8-24 В DC

Температурный режим Хранение: от -20 до +80 °С / Эксплуатация: от -15 до +70°С

Построить график программно с помощью Kotlin DSL

Компонент «Навигация» предоставляет предметно-ориентированный язык на основе Kotlin или DSL, основанный на Kotlin’s типобезопасные строители. Этот API позволяет вам декларативно составить график в вашем коде Kotlin, а не внутри ресурса XML. Это может быть полезно, если вы хотите построить динамическая навигация вашего приложения. Например, ваше приложение может скачать и кэшировать конфигурацию навигации из внешнего веб-сервиса, а затем использовать эта конфигурация для динамического построения навигационного графика в вашей деятельности onCreate () функция.

Зависимости

Чтобы использовать Kotlin DSL, добавьте следующую зависимость к вашему приложению build.gradle файл:

Заводной

dependencies {
    def nav_version = "2.3.5"

    api "androidx.navigation: navigation-fragment-ktx: $ nav_version"
}
 

Котлин

dependencies {
    val nav_version = "2. 3,5 дюйма

    api ("androidx.navigation: навигация-фрагмент-ktx: $ nav_version")
}
 

Построение графика

Начнем с базового примера, основанного на Подсолнечник приложение. Для этого Например, у нас есть два пункта назначения: home и plant_detail . дом пункт назначения присутствует, когда пользователь впервые запускает приложение. Это место назначения отображает список растений из сада пользователя. Когда пользователь выбирает один из растения, приложение переходит к пункту назначения plant_detail .

На рисунке 1 показаны эти места назначения вместе с аргументами, необходимыми для plant_detail destination и действие to_plant_detail , которое использует приложение. для перехода от home к plant_detail .

Рисунок 1. Приложение Sunflower имеет два пункта назначения, home и plant_detail , а также действие, которое связывает их.

Хостинг Kotlin DSL Nav Graph

Прежде чем вы сможете построить граф навигации своего приложения, вам нужно место для размещения график.В этом примере используются фрагменты, поэтому график размещается в NavHostFragment внутри FragmentContainerView :

  

    android: layout_width = "match_parent"
    android: layout_height = "match_parent">

    


  

Обратите внимание, что атрибут app: navGraph не установлен в этом примере. График не определяется как ресурс в res / navigation , поэтому ее необходимо установить как часть onCreate () процесс в деятельности.

В XML действие связывает идентификатор пункта назначения с одним или несколькими аргументами.Однако при использовании DSL навигации маршрут может содержать аргументы как часть маршрута. Это означает отсутствие концепции действий при использовании DSL.

Следующим шагом является определение некоторых констант, которые вы будете использовать при определении ваш график.

Создайте константы для вашего графика

навигационных графов на основе XML анализируются как часть процесса сборки Android. Числовая константа создана для каждого атрибута id , определенного на графике. Это время сборки генерировало статические Идентификаторы недоступны при построении навигационного графика во время выполнения, поэтому Навигационный DSL использует строки маршрута вместо идентификаторов.Каждый маршрут представлен уникальная строка, и рекомендуется определять их как константы, чтобы уменьшить риск ошибок, связанных с опечатками.

При работе с аргументами это встроен в строку маршрута. Встраивание этой логики в маршрут может, опять же, снизить риск появляются ошибки, связанные с опечатками.

  объект nav_routes {
    const val home = "дом"
    const val plant_detail = "plant_detail"
}

object nav_arguments {
    const val plant_id = "plant_id"
    const val plant_name = "plant_name"
}
  

Построение графика с помощью NavGraphBuilder DSL

После того, как вы определили свои константы, вы можете построить навигацию график.

  val navController = findNavController (R.id.nav_host_fragment)
navController.graph = navController.createGraph (
    startDestination = mav_routes.home
) {
    фрагмент  (nav_routes.home) {
        label = resources.getString (R.string.home_title)
    }

    фрагмент  ($ {nav_routes.plant_detail} / $ {nav_arguments.plant_id}) {
        label = resources.getString (R.string.plant_detail_title)
        аргумент (nav_arguments.plant_id) {
            type = NavType.StringType
        }
    }
}
  

В этом примере конечная лямбда определяет два адресата фрагмента с помощью фрагмент () Функция построения DSL. Эта функция требует строки маршрута для пункта назначения. которое получается из констант. Функция также принимает необязательный лямбда для дополнительной конфигурации, такой как метка назначения, а также встроенные функции построения для аргументов и глубоких ссылок.

Фрагмент класс, который управляет пользовательским интерфейсом каждого пункта назначения, передается как параметризованный тип внутри угловые скобки ( <> ).Это имеет тот же эффект, что и установка android: name атрибут для мест назначения фрагментов, определенных с помощью XML.

Навигация с помощью графа Kotlin DSL

Наконец, вы можете перейти от home к plant_detail , используя стандартную NavController.navigate () звонки:

  частное развлечение navigateToPlant (plantId: String) {
   findNavController (). navigate ("$ {nav_routes.plant_detail} / $ plantId")
}
  
Примечание: Плагин Safe Args несовместим с Kotlin DSL.Для большего информацию см. Ограничения.

В PlantDetailFragment можно получить значение аргумента, как показано в следующем примере:

  val plantId: Строка? = аргументы? .getString (nav_arguments.plant_id)
  

Подробную информацию о том, как предоставить аргументы при навигации, можно найти в предоставление раздела аргументов назначения.

Остальная часть этого руководства описывает общие элементы навигационного графа, пункты назначения, и как использовать их при построении графика.

Направления

Kotlin DSL обеспечивает встроенную поддержку трех типов адресатов: Fragment , Activity и NavGraph назначения, каждое из которых имеет свое собственное встроенная функция расширения доступна для создания и настройки место назначения.

Назначения фрагментов

фрагмент () Функция DSL может быть параметризована для класса реализующего фрагмента и принимает уникальная строка маршрута для назначения этому пункту назначения, за которой следует лямбда, где вы можете предоставить дополнительную конфигурацию, как описано в Навигация с помощью графа Kotlin DSL раздел.

  фрагмент  (nav_routes.route_name) {
   метка = getString (R.string.fragment_title)
   // аргументы, deepLinks
}
  

Направление деятельности

Действия () Функция DSL принимает уникальную строку маршрута для назначения этому пункту назначения, но не параметризован для какого-либо реализующего класса деятельности. Вместо этого вы устанавливаете необязательный activityClass в завершающей лямбде. Эта гибкость позволяет определить назначение действия для действия, которое должно быть запущено с помощью неявное намерение, где явный класс активности не имеет смысла.Как и в случае назначения фрагментов, вы также можете настроить метку, аргументы и глубокие ссылки.

  активность (nav_routes.route_name) {
   метка = getString (R.string.activity_title)
   // аргументы, глубокие ссылки ...

   activityClass = ActivityDestination :: класс
}
  

Назначение графика навигации

Навигация () Функция DSL может использоваться для создания вложенный навигационный граф. Эта функция принимает три аргумента: путь к назначить графу маршрут начального пункта назначения графа и лямбда для дальнейшей настройки графика.Допустимые элементы включают другие направления, аргументы, глубокие ссылки и описательная этикетка для пункта назначения. Эта метка может быть полезна для привязки графа навигации к пользовательскому интерфейсу. компоненты, использующие НавигацияUI

  навигация ("route_to_this_graph", nav_routes.home) {
   // метка, другие направления, ссылки на контент
}
  

Поддержка настраиваемых направлений

Если вы используете новый тип назначения, который не напрямую поддерживают Kotlin DSL, вы можете добавить эти направления в свой Kotlin DSL с использованием addDestination () :

  // NavigatorProvider извлекается из NavController
val customDestination = navigatorProvider [CustomNavigator :: класс].createDestination (). apply {
    route = Graph.CustomDestination.route
}
addDestination (customDestination)
  

В качестве альтернативы вы также можете использовать унарный оператор плюса для добавления нового построенный пункт назначения прямо на график:

  // NavigatorProvider извлекается из NavController
+ navigatorProvider [CustomNavigator :: class] .createDestination (). apply {
    route = Graph.CustomDestination.route
}
  

Предоставление аргументов пункта назначения

Любой пункт назначения может определять необязательные или обязательные аргументы.Действия можно определить с помощью аргумент () функция на NavDestinationBuilder , который является базовым классом для всех типы строителей назначения. Эта функция принимает имя аргумента в виде строки и лямбда, которая используется для создания и настройки Аргумент .

Внутри лямбды вы можете указать тип данных аргумента, значение по умолчанию, если применимо, и может ли он иметь значение NULL.

  фрагмент  ($ {nav_routes.plant_detail} / $ {nav_arguments.plant_id}) {
    метка = getString (R.string.plant_details_title)
    аргумент (nav_arguments.plant_id) {
        type = NavType.StringType
        defaultValue = getString (R.string.default_plant_id)
        nullable = true // по умолчанию false
    }
}
  

Если задано значение defaultValue , можно вывести тип. Если оба значения defaultValue и типа , типы должны совпадать. Увидеть Справочная документация NavType для полный список доступных типов аргументов.

Предоставление нестандартных типов

Определенные типы, такие как ParcelableType а также SerializableType , не поддерживают синтаксический анализ значений из строк, используемых маршрутами или глубокими ссылками. Это потому, что они не полагаются на отражение во время выполнения. Предоставляя индивидуальный NavType , вы можете точно контролировать, как ваш тип анализируется из маршрута или глубокая ссылка. Это позволяет использовать Kotlin Serialization или другое библиотеки для обеспечения безотражательного кодирования и декодирования вашего пользовательского типа.

Например, класс данных, представляющий параметры поиска, передаваемые вашему экран поиска может реализовывать как Serializable (для обеспечения поддержка кодирования / декодирования) и Parcelize (для поддержки сохранения и восстановления из Пачка ):

  @Serializable
@Parcelize
класс данных SearchParameters (
  val searchQuery: String,
  фильтры val: Список 
)
  

Пользовательский NavType может быть записан как:

  класс SearchParametersType: NavType  (
  isNullableAllowed = false
) {
  переопределить fun put (bundle: Bundle, key: String, value: SearchParameters) {
    пучок.putParcelable (ключ, значение)
  }
  переопределить удовольствие get (bundle: Bundle, key: String): SearchParameters {
    вернуть bundle.getParcelable (ключ) как SearchParameters
  }

  переопределить веселье parseValue (значение: String): SearchParameters {
    return Json.decodeFromString  (значение)
  }

  // Требуется только при использовании Navigation 2.4.0-alpha07 и ниже
  переопределить val name = "SearchParameters"
}
  

Затем его можно использовать в Kotlin DSL, как и любой другой тип:

  фрагмент  (nav_routes.plant_search) {
    label = getString (R.string.plant_search_title)
    аргумент (nav_arguments.search_parameters) {
        type = SearchParametersType
        defaultValue = SearchParameters ("кактус", emptyList ())
    }
}
  

В этом примере сериализация Kotlin используется для анализа значения из строки, которая означает, что сериализация Kotlin также должна использоваться при переходе к пункт назначения для обеспечения соответствия форматов:

  val params = SearchParameters ("роза", listOf ("доступно"))
val searchArgument = Uri.кодировать (Json.encodeToString (параметры))
navController.navigate ("$ {nav_routes.plant_search} / $ searchArgument")
  

Параметр можно получить из аргументов в пункте назначения:

  val params: Параметры поиска? = аргументы? .getParcelable (nav_arguments.search_parameters)
  

Глубокие ссылки

Глубинные ссылки могут быть добавлены в любое место назначения, так же, как они могут быть с управляемыми XML график навигации. Все те же процедуры, определенные в Создание глубинной ссылки для пункта назначения применить к процессу создания явная глубокая ссылка с использованием Котлин DSL.

При создании неявной ссылки на контент однако у вас нет ресурса навигации XML, который можно было бы проанализировать на предмет элемента. Следовательно, вы не можете рассчитывать на размещение в вашем файле AndroidManifest.xml и вместо этого должен добавить намерение фильтрует ваши действия вручную. Предоставленный вами фильтр намерений должен соответствовать базовому шаблону URL, действию и mimetype глубоких ссылок вашего приложения.

Вы можете предоставить более конкретную ссылку deeplink для каждой отдельной глубинной ссылки пункт назначения с использованием deepLink () Функция DSL.Эта функция принимает NavDeepLink , который содержит String представляющий шаблон URI, String , представляющий действия намерения, и Строка , представляющая mimeType.

Например:

  deepLink {
    uriPattern = "http://www.example.com/plants/"
    действие = "android.intent.action.MY_ACTION"
    mimeType = "изображение / *"
}
  

Нет ограничений на количество добавляемых ссылок на контент. Каждый раз, когда ты звонишь deepLink () новая глубокая ссылка добавляется к списку, который ведется для этого места назначения.

Более сложный сценарий неявной глубинной ссылки, который также определяет путь и параметры на основе запроса показаны ниже:

  val baseUri = "http://www.example.com/plants"

фрагмент  (nav_routes.plant_detail) {
   метка = getString (R.string.plant_details_title)
   deepLink (navDeepLink {
    uriPattern = "$ {baseUri} / {id}"
   })
   deepLink (navDeepLink {
    uriPattern = "$ {baseUri} / {id}? name = {plant_name}"
   })
}
  

Вы можете использовать строковая интерполяция для упрощения определения.

Ограничения

Плагин Safe Args несовместим с Kotlin DSL, поскольку плагин ищет файлы ресурсов XML для сгенерировать классы Directions и Arguments .

Голосовая навигация на Android-устройстве Delivery Route Planner

Приложение Route4Me для Android Driver Route Planner поможет вам создавать, оптимизировать, управлять и перемещаться по сложным маршрутам на вашем устройстве Android. Встроенная голосовая навигация Route4Me для Android теперь полностью интегрирована в приложение для безопасности и комфорта ваших водителей.

В отличие от постоянного наблюдения за экраном смартфона, голосовая навигация позволяет водителям, работающим на местах, торговым представителям, техническим специалистам по обслуживанию и т. Д. Сосредоточиться только на дороге, что делает их гораздо безопаснее. Кроме того, встроенная GPS-навигация Route4Me избавляет от необходимости переключаться между приложением для навигации и приложением для планирования маршрута. Таким образом, вы можете минимизировать риски несчастных случаев и ответственность, повысить уровень производительности водителей и снизить утомляемость водителя.

Используя встроенную GPS-навигацию Route4Me, вы можете избежать расхождений или конфликтов между алгоритмами приложений Route4Me Planner для Android или iOS и сторонними приложениями GPS-навигации, такими как Google Maps, Apple Maps, Waze и т. Д.Вам больше не нужно делиться навигационными маршрутами между приложениями.

Для создания наиболее точных направлений навигации вы можете перемещаться по адресам или координатам пунктов назначения. Координаты GPS особенно полезны, когда вам нужно перейти к определенной точке на карте или к остановке с неполным адресом.

Вы можете взаимодействовать с картой с помощью жестов. Вы также можете изменить перспективу карты на 3D-режим, который добавляет к карте дополнительное измерение и позволяет видеть 3D-здания, улицы и т. Д.

Android Навигация с голосовыми подсказками в приложении

Чтобы начать навигацию по оптимизированному маршруту, откройте этот маршрут из Мои маршруты в меню навигации и нажмите кнопку Start Route , чтобы начать открытый маршрут. Затем нажмите на значок навигации рядом с адресом маршрута, к которому вы хотите перейти из вашего текущего местоположения.

После этого выберите Route4Me In-App Navigation из списка всех доступных вариантов навигации.После запуска навигации по маршруту переходите к навигации по оптимизированному маршруту почти в реальном времени с пошаговыми голосовыми указаниями.

В верхней части навигационной карты вы можете увидеть направления поворота для следующего маневра. Каждый следующий ход автоматически озвучивается приложением. Внизу навигационной карты вы можете увидеть расчетное время прибытия в последний пункт назначения маршрута и расчетное оставшееся расстояние навигации.

Поскольку встроенная навигация Route4Me для Android влияет на трафик и другие условия, близкие к реальному времени, расчетное время прибытия может соответственно меняться во время навигации по маршруту.По мере прохождения маршрута время, оставшееся до прибытия водителя на последнюю остановку маршрута, автоматически обновляется почти в реальном времени.

Для максимального удобства, безопасности и производительности вы можете настроить навигационную карту, используя следующие жесты:

  • Сведение пальцев для увеличения: увеличение и уменьшение любого места на навигационной карте. Увеличивая масштаб, вы можете подробно рассмотреть адреса улиц, углы зданий, формы зданий, названия объектов и т. Д.
  • Перетаскивание двумя пальцами Вверх: включить перспективу трехмерной навигационной карты.
  • Перетаскивание двумя пальцами Вниз: включить перспективу 2D-карты навигации.
  • Вращение двумя пальцами: поверните навигационную карту, чтобы посмотреть на свое текущее местоположение, остановки маршрута и навигационные линии движения под разными углами.
  • Перетаскивание одним пальцем: перемещение по навигационной карте.

Чтобы настроить параметры навигации, коснитесь значка меню из трех точек в правом нижнем углу приложения.Вы можете настроить параметры голосовых указаний и язык голосовой навигации. Чтобы загрузить определенный язык навигации, нажмите кнопку Загрузить голосовые пакеты , а затем загрузите предпочтительный языковой пакет.

Для большего удобства вы можете переключаться между режимами непрерывной навигации и навигации с одной остановкой. Для этого перейдите к Настройки из меню навигации, прокрутите до раздела In-App Navigation Mode , а затем нажмите, чтобы выбрать предпочтительный режим навигации.

Непрерывный маршрут Navigatio n предоставляет указания для всего маршрута, от первой остановки до последней, с указанием примерного времени и расстояния для всего маршрута.

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

iPhone Планировщик маршрутов Навигация с голосовыми подсказками в приложении

В дополнение к возможности использовать различные сторонние навигационные приложения, такие как приложение для навигации Google Maps для iPhone, приложение для навигации Google Maps для iPad, приложение для навигации Apple Maps и т. Д. .Route4Me также имеет интегрированный планировщик маршрутов с голосовой навигацией.

Благодаря встроенной навигации Route4Me вы получите наиболее оптимальные пешеходные и велосипедные маршруты, а также голосовые подсказки GPS прямо в планировщике маршрутов.

Route4Me: голосовая навигационная карта приложения маршрутов движения чрезвычайно детализирована и настраивается, обеспечивая такой же высокий уровень детализации, как и лучшие в бизнесе, например, приложение Google Navigation для iPhone или приложение Apple Maps для iPhone.

Для вашего удобства вы по-прежнему можете использовать пошаговые инструкции из приложения Apple Maps, Waze Navigation & Live Traffic, TomTom Go Navigation, CoPilot GPS Sat-Nav & Traffic и других приложений. Вы можете отправить оптимизированный маршрут Route4Me в приложение маршрутов движения Apple Maps или даже в приложение для совместного использования поездок Uber одним нажатием кнопки. Route4Me может обнаруживать любое стороннее приложение на вашем iPhone или iPad, а Apple Maps отправляет информацию о местоположении из планировщика маршрута в любое предпочтительное навигационное приложение.

Посетите рынок Route4Me, чтобы проверить связанные модули:

Компонент навигации — полное руководство | Мухамед Рияс M

После того, как плагины настроены, мы можем начать навигацию !. Осознав всю мощь «Компонента навигации», я очень рад создать все свое приложение с одним действием и парой фрагментов.

Ниже приведены основные компоненты:

  1. Ваш класс MainActivity
  2. Пара фрагментов
  3. График навигации
  4. Действие
  5. Назначения
  6. Всплывающее окно до
  7. Аргументы
  8. Контроллер навигации по глубокой ссылке
  9. Контроллер навигации по глубинной ссылке

Первые два компонента будут использоваться в ваших прошлых / текущих приложениях, и я не собираюсь их описывать. Я хотел бы предложить подготовить фрагменты перед созданием навигационного графика, который поможет вам связать вещи с тем, что вы знаете, и позволит избежать каких-либо недоразумений.

Итак, я снова цитирую определение сайта разработчика

График навигации — это файл ресурсов, который содержит все ваши назначения и действия. На графике представлены все пути навигации вашего приложения.

На следующем рисунке показано визуальное представление графа навигации для примера приложения, содержащего шесть пунктов назначения, связанных пятью действиями.Каждый пункт назначения представлен миниатюрой предварительного просмотра, а действия по подключению представлены стрелками, которые показывают, как пользователи могут перемещаться от одного пункта назначения к другому.

  1. Назначения — это различные области содержимого в вашем приложении.
  2. Действия — это логические соединения между пунктами назначения, которые представляют пути, по которым могут идти пользователи.

Как создать навигационный график?

  1. Создайте новый каталог ресурсов с именем « navigation »
Создайте граф навигации

2.Создайте файл ресурсов навигации «app_navigation.xml», имя должно соответствовать правилам имен файлов ресурсов.

Поскольку меня больше интересует дизайн с помощью XML-кодирования, я объясню это с помощью кодов. Итак, после создания «app_navigation.xml» ваш код будет выглядеть так:

 

xmlns: app =" http://schemas.android.com/apk/res-auto "
xmlns: tools =" http: // schemas.android.com/tools "
android: id =” @ + id / app_navigation ”
>

Следующими шагами должно быть определение первого представления навигации, то есть, откуда навигация должна начинаться и куда она Эти детали передаются через тег под названием «пункт назначения»

Я использовал следующие 3 фрагмента, чтобы объяснить концепции пункта назначения, аргументов, действия.

  1. MyHomeFragment
  2. MySecondFragment
  3. MyThirdFragment

Добавить все фрагменты как дочерние элементы в родительском элементе навигации, убедитесь, что вам назначен уникальный идентификатор для ваших фрагментов.

  
xmlns: app = "http : //schemas.android.com/apk/res-auto "
xmlns: tools =" http://schemas.android.com/tools "
android: id =" @ + id / app_navigation ">
<фрагмент
android: id = " @ + id / myHomeFragment"
android: name = "com.navigation.component.sample.ui.fragments.MyHomeFragment"
android: label = "fragment_my_home"
tools: layout = "@ layout / fragment_my_home ">

android: id =" @ + id / mySecondFragment "
android: name =" com.navigation.component.sample.ui.fragments.MySecondFragment "
android: label =" fragment_my_second "
tools: layout =" @ layout / fragment_my_second ">

android: id =" @ + id / myThirdFragment "
android: name =" com.navigation.component.sample.ui.fragments.MyThirdFragment "
android: label =" fragment_my_third "
tools: layout =" @ layout / fragment_my_third ">


Используется 4 параметра

  1. android: id: уникальный идентификатор для фрагмента, точно так же, как мы назначаем идентификатор любым другим виджетам в макете xml
  2. android: name: Это полное имя вашего класса фрагмента в kotlin / java
  3. android: label: Строка для идентификации фрагмента
  4. tools: layout: Идентификатор файла ресурсов макета из res / layout

To определите начальный вид, который мы используем startDestination в корневом теге навигации и укажите идентификатор фрагмента

  
xmlns: android =" http://schemas.android.com/apk/res/android "
xmlns: app =" http://schemas.android. com / apk / res-auto "
xmlns: tools =" http://schemas.android.com/tools "
android: id =" @ + id / app_navigation "
app: startDestination =" @ id / myHomeFragment " >
android: name = "com.navigation.component.sample.ui.fragments.MyHomeFragment"
android: label = "fragment_my_home"
tools: layout = " @ layout / fragment_my_home ">

android: name =" com.navigation.component.sample.ui.fragments.MySecondFragment "
android: label =" fragment_my_second "
tools: layout =" @ layout / fragment_my_second ">

android: name =" com.navigation.component.sample.ui.fragments.MyThirdFragment "
android: label =" fragment_my_third "
tools: layout =" @ layout / fragment_my_third ">


Действия

Система навигации также позволяет перемещаться с помощью действий .Как показано на рисунке, линии, показанные на навигационном графике, представляют собой визуальные представления действий. Конец каждой стрелки называется пунктов назначения.

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

  
xmlns: app = "http : //schemas.android.com / apk / res-auto "
xmlns: tools =" http://schemas.android.com/tools "android: id =" @ + id / app_navigation "
app: startDestination =" @ id / myHomeFragment ">
<фрагмент android: id = "@ + id / myHomeFragment"
android: name = "com.navigation.component.sample.ui.fragments.MyHomeFragment"
android: label = "fragment_my_home"
tools: layout = "@ layout / fragment_my_home ">
app: destination =" @ id / mySecondFragment "
app: enterAnim =" @ anim / slide_in_right "
app: exitAnim_out_" @ slide / slide "
app: popEnterAnim =" @ anim / slide_in_left "
app: popExitAnim =" @ anim / slide_out_right "/>


android: name = "com.navigation.component.sample.ui.fragments.MySecondFragment "
android: label =" fragment_my_second "
tools: layout =" @ layout / fragment_my_second ">

app destination = "@ id / myThirdFragment"
app: enterAnim = "@ anim / slide_in_right"
app: exitAnim = "@ anim / slide_out_left"
app: popEnterAnim = "@ anim / slide_in_left"
app: popExitAnim = "@ anim / slide_out_right "/>


android: name =" com.navigation.component.sample.ui.fragments.MyThirdFragment "
android: label =" fragment_my_third "
tools: layout =" @ layout / fragment_my_third ">
popUpTo = "@ id / myHomeFragment"

/>
app: popUpTo = "@ id / mySecondFragment" />

Давайте обсудим параметры, используемые внутри

  1. android: id : уникальный идентификатор для действия, точно так же, как нам присваивается идентификатор фрагментам
  2. app: destination : уникальный идентификатор целевой фрагмент, означает, что это действие переместит текущее представление в целевой фрагмент.Если вы хотите перейти от фрагмента A к фрагменту C, вы можете использовать это значение параметра в качестве фрагмента идентификатора A. Управление обратным стеком и жизненный цикл будут осуществляться компонентом навигации.
  3. Кроме того, мы можем определить анимацию для транзакции фрагмента, как указано, вы должны создать файл анимации xml внутри папки res / anim.

SDK для навигации | Android | Mapbox

Navigation SDK для Android позволяет вам создать полноценную навигацию с помощью API Mapbox Directions.Вы можете создать полный пользовательский интерфейс пошаговой навигации внутри своего приложения, используя наши готовые компоненты, или напрямую использовать основную логику для создания чего-то действительно индивидуального.

Navigation SDK предоставляет набор функций, которые имеют решающее значение при создании проектов навигации, в том числе:

  • Маршруты навигации
  • Точное обновление местоположения устройства
  • Объявления голосовых инструкций
  • Прогресс пользователя к месту назначения в реальном времени
  • Выкл. определение маршрута и изменение маршрута
  • Динамическая настройка камеры во время пошаговой навигации
  • Встроенные компоненты пользовательского интерфейса для отображения изменяющейся навигационной информации
  • Поддержка навигации с ограниченным сетевым подключением или без него

Navigation SDK предлагает два типа навигации : пошаговая навигация и режим свободного вождения.

Пошаговая навигация

Пошаговая навигация, также называемая активным руководством, вероятно, то, что приходит на ум, когда вы думаете о типичной пошаговой навигации: пользователь получает пошаговую инструкцию. поворачивайте инструкции по мере их продвижения по маршруту. Подробнее читайте в пошаговых руководствах по навигации.

Free-drive

Free-drive навигация, также называемая пассивной навигацией, представляет собой уникальную функцию Mapbox Navigation SDK, которая позволяет водителям использовать преимущества некоторых функций навигации, не выбирая маршрут и не следуя пошаговым инструкциям на установить пункт назначения.Подробнее читайте в руководстве по бесплатному вождению.

SDK Mapbox Navigation для Android совместим с приложениями, которые:

  • созданы с использованием Android SDK 21 или выше.
  • Используйте Java 8 для sourceCompatibility и targetCompatibility , как показано в руководстве по установке.

SDK Mapbox Navigation для Android построен на Kotlin, официальном языке, рекомендованном Google для разработки под Android. Kotlin на 100% совместим с Java.

Приложения с базой кода Java могут правильно взаимодействовать с общедоступными API, предоставляемыми Mapbox SDK для Android. Если у вас возникнут проблемы с использованием SDK Mapbox Navigation SDK для Android с Java, свяжитесь с нами.

SDK Mapbox Navigation для Android разработан для использования с несколькими другими продуктами Mapbox.

Directions API

Navigation SDK поставляется с доступом к Mapbox Directions API для создания маршрутов между двумя или более координатами. API Directions имеет множество параметров маршрута, таких как настройка профиля (например, вождение, движение с пробками или ходьба), с азимутом (чтобы повлиять на направление, в котором начнется маршрут) и исключить (например, избегая дорожных сборов).Дополнительные сведения об API Directions см. В документации по API.

Maps SDK для Android

По умолчанию Navigation SDK поставляется с доступом к Mapbox Maps SDK для Android. SDK для навигации использует SDK для карт для отображения маршрутов на карте и отображения местоположения пользователя на карте на протяжении всей поездки, чтобы предоставить как контекст, связанный с навигацией, так и близлежащие места, которые могут быть интересны водителю. SDK для навигации использует SDK для карт. Подробнее читайте в документации Maps SDK.

Атрибуция

Если вы используете карту Mapbox в своем приложении, вы должны предоставить атрибуцию в соответствии с документацией Mapbox Maps SDK.

Условия

SDK для навигации Mapbox распространяется в соответствии с Условиями обслуживания Mapbox.

Цены

Дополнительные сведения о ценах на Navigation SDK см. В руководстве по ценам.

Ищете старую версию Navigation SDK? См. Документацию Navigation SDK v1.

Навигация с переключением назад и вверх

Документы разработчика

Реализация эффективной навигации

Последовательная навигация — важный компонент общего взаимодействия с пользователем.Мало что расстраивает пользователям больше, чем простая навигация, которая ведет себя непоследовательно и неожиданно. Android 3.0 внесены существенные изменения в поведение глобальной навигации. Вдумчиво следуя Рекомендации для Back and Up сделают навигацию вашего приложения предсказуемой и надежной для ваших пользователей.

Android 2.3 и более ранние версии полагались на системную кнопку Назад для поддержки навигации в пределах приложение. С появлением панелей действий в Android 3.0 появился второй механизм навигации: кнопка Вверх , состоящая из значка приложения и курсора влево.

вверх против спины

Кнопка «Вверх» используется для навигации в приложении на основе иерархических отношений. между экранами. Например, если на экране A отображается список элементов, а выбор элемента приводит к экран B (который представляет этот элемент более подробно), затем экран B должен предлагать кнопку «Вверх», которая возвращается к экрану A.

Если экран является самым верхним в приложении (то есть, домашний экран приложения), он не должен отображать сообщение «Вверх». кнопка.

Системная кнопка Назад используется для навигации в обратном хронологическом порядке по истории. экранов, с которыми пользователь недавно работал.Обычно он основан на временных отношениях между экранами, а не в иерархии приложения.

Если ранее просматриваемый экран также является иерархическим родительским элементом текущего экрана, нажатие кнопка «Назад» дает тот же результат, что и нажатие кнопки «Вверх» — это обычная вхождение. Однако, в отличие от кнопки «Вверх», которая гарантирует, что пользователь останется в вашем приложении, кнопка «Назад» Кнопка может вернуть пользователя на главный экран или даже в другое приложение.

Кнопка «Назад» также поддерживает несколько вариантов поведения, не связанных напрямую с экранной навигацией:

  • Отключает плавающие окна (диалоговые окна, всплывающие окна)
  • Отключает контекстные панели действий и убирает выделение с выбранных элементов
  • Скрывает экранную клавиатуру (IME)

Навигация в вашем приложении

Переход к экранам с несколькими точками входа

Иногда экран не занимает строгое положение в иерархии приложения и может быть доступен из нескольких точек входа — например, экрана настроек, который можно открыть с любого другого экрана. в вашем приложении.В этом случае кнопка «Вверх» должна выбрать возврат к соответствующему экрану, действуя идентично Back.

Изменение вида на экране

Изменение параметров просмотра экрана не меняет поведения кнопок «Вверх» или «Назад»: экран все еще остается в том же месте в иерархии приложения, и новая история навигации не создается.

Примеры таких изменений представления:

  • Переключение представлений с помощью вкладок и / или свайпов влево и вправо
  • Переключение представлений с помощью раскрывающегося списка (также известного как свернутые вкладки)
  • Фильтрация списка
  • Сортировка списка
  • Изменение характеристик дисплея (например, масштабирование)
Переход между одноуровневыми экранами

Если ваше приложение поддерживает переход от списка элементов к подробному представлению одного из этих элементов, оно часто желательно для поддержки навигации по направлению от этого элемента к другому, который предшествует или следует за ним в списке.Например, в Gmail можно легко провести пальцем влево или вправо от разговора. чтобы просмотреть более новую или старую в той же папке «Входящие». Так же, как при изменении вида на экране, такие навигация не меняет поведение кнопок «Вверх» или «Назад».

Однако заметное исключение из этого возникает при просмотре между связанными подробными представлениями, не связанными вместе со списком источников — например, при просмотре в Play Store между приложениями из того же разработчика или альбомы одного исполнителя. В этих случаях переход по каждой ссылке создает история, в результате чего кнопка «Назад» перемещается по каждому ранее просмотренному экрану.Вверх должен продолжаться чтобы обойти эти связанные экраны и перейти к последнему просмотренному экрану контейнера.

У вас есть возможность сделать поведение Up еще более умным, основываясь на ваших знаниях деталей. Посмотреть. Расширяя пример Play Store сверху, представьте, что пользователь перешел с последнего Книга просмотрена в деталях для адаптации фильма. В этом случае Up может вернуться в контейнер. (Фильмы), которые пользователь ранее не просматривал.

Навигация в ваше приложение с помощью виджетов и уведомлений на главном экране

Вы можете использовать виджеты или уведомления на главном экране, чтобы помочь пользователям переходить прямо на экраны. глубоко в иерархии вашего приложения.Например, виджет «Входящие» Gmail и уведомление о новом сообщении могут оба обходят экран «Входящие», позволяя пользователю перейти непосредственно к просмотру беседы.

В обоих случаях используйте кнопку «Вверх» следующим образом:

  • Если целевой экран обычно открывается с одного определенного экрана в пределах вашего app , Up должен перейти на этот экран.
  • В противном случае , Up должен перейти на самый верхний («Домашний») экран вашего приложения.

В случае кнопки «Назад» вы должны сделать навигацию более предсказуемой, вставив ее в задняя часть задачи складывает полный путь навигации вверх к самому верхнему экрану приложения.Это позволяет пользователям кто забыл, как они вошли в ваше приложение, чтобы перейти на самый верхний экран приложения раньше выход.

Например, в виджете главного экрана Gmail есть кнопка для перехода непосредственно к его созданию. экран. Вверх или назад на экране создания сообщения пользователь попадет в папку «Входящие», а оттуда Кнопка «Назад» продолжает переход на «Домой».

Косвенные уведомления

Когда вашему приложению необходимо представить информацию о нескольких событиях одновременно, оно может использовать одно уведомление, которое направляет пользователя на межстраничный экран.Этот экран суммирует эти события и предоставляет пользователю возможность глубоко погрузиться в приложение. Уведомления этого стиля вызвал косвенных уведомлений .

В отличие от стандартных (прямых) уведомлений, нажатие Back из косвенного уведомления межстраничный экран возвращает пользователя к точке, откуда было инициировано уведомление — нет дополнительные экраны вставляются в задний стек. Как только пользователь переходит в приложение из его межстраничный экран, Up и Back ведут себя так же, как и для стандартных уведомлений, как описано выше: перемещаться по приложению, а не возвращаться к межстраничному объявлению.

Например, предположим, что пользователь Gmail получает косвенное уведомление от Календаря. Трогательно это уведомление открывает межстраничный экран, на котором отображаются напоминания для нескольких разных События. При нажатии кнопки «Назад» с межстраничного объявления пользователь возвращается в Gmail. Касаясь конкретного событие переводит пользователя с межстраничного объявления в полное приложение «Календарь», чтобы отобразить подробные сведения о событие. Из сведений о мероприятии нажмите «Вверх» и «Назад», чтобы перейти к просмотру календаря верхнего уровня.

Всплывающие уведомления

Всплывающие уведомления обходят панель уведомлений, а отображаются непосредственно в перед пользователем.Они редко используются, и следует зарезервировать для случаев, когда своевременное требуется ответ и необходимо прерывание контекста пользователя . Например, Talk использует этот стиль, чтобы предупредить пользователя о приглашении от друга присоединиться к видеочату, так как это приглашение автоматически истечет через несколько секунд.

С точки зрения поведения навигации всплывающие уведомления во многом повторяют поведение косвенных межстраничный экран уведомления. Назад закрывает всплывающее уведомление.Если пользователь переходит из всплывающего окна в приложение для уведомлений, Вверх и Назад следуют правилам для стандартных уведомлений, навигация в приложении.

Навигация между приложениями

Одной из основных сильных сторон системы Android является способность приложений активировать каждый другое, давая пользователю возможность переходить непосредственно из одного приложения в другое. Например, приложение, которому необходимо сделать снимок, может активировать приложение камеры, которое вернет фотографию в ссылающееся приложение.Это огромное преимущество как для разработчиков, так и для разработчиков, которые могут легко использовать код из других приложений, а также пользователь, который пользуется единообразием для часто выполняемых действия.

Чтобы понять навигацию от приложения к приложению, важно понимать поведение платформы Android. обсуждается ниже.

Действия, задачи и намерения

В Android действие — это компонент приложения, определяющий экран информация и все связанные с ней действия, которые может выполнять пользователь.Ваше приложение представляет собой набор действия, состоящие как из действий, которые вы создаете, так и из тех, которые вы повторно используете из других приложений.

Задача — это последовательность действий, которые пользователь выполняет для достижения цели. А одна задача может использовать действия только из одного приложения или может использовать действия из нескольких различных приложений.

Намерение — это механизм, с помощью которого одно приложение сигнализирует о том, что ему нужно другое помощь приложения в выполнении действия. Действия приложения могут указывать, какие намерения они могут ответить.Для обычных целей, таких как «Поделиться», у пользователя может быть установлено множество приложений. который может выполнить этот запрос.

Пример: переход между приложениями для поддержки совместного использования

Чтобы понять, как действия, задачи и намерения работают вместе, подумайте, как одно приложение позволяет пользователям для обмена контентом с помощью другого приложения. Например, запуск приложения Play Store из дома начинается. новая задача A (см. рисунок ниже). После навигации по Play Store и прикосновения к рекламируемой книге чтобы увидеть его детали, пользователь остается в той же задаче, расширяя ее, добавляя действия.Срабатывание действие «Поделиться» предлагает пользователю диалоговое окно, в котором перечислены все действия (из разных приложений). которые зарегистрировались для обработки намерения Акции.

Когда пользователь решает поделиться через Gmail, действие создания сообщения Gmail добавляется как продолжение Задача A — новых задач не создается. Если бы у Gmail была собственная задача, выполнявшаяся в фоновом режиме, она бы быть незатронутым.

В процессе создания сообщения отправка сообщения или нажатие кнопки «Назад» возвращает пользователя к в книге подробно рассказывается о деятельности.Последующие прикосновения к кнопке «Назад» продолжают возвращаться назад по воспроизведению. Магазин, в конечном итоге придя домой.

Однако, прикоснувшись к Вверх в процессе создания сообщения, пользователь показывает, что хочет остаться в пределах Gmail. Появляется активность в списке бесед Gmail, и для нее создается новая задача B. Новые задачи есть всегда привязан к Home, поэтому нажатие Back из списка разговоров вернется туда.

Задача A остается в фоновом режиме, и пользователь может вернуться к ней позже (например, через Экран недавних сообщений).Если бы у Gmail уже была собственная задача, работающая в фоновом режиме, она была бы заменена с Задачей B — предыдущий контекст отбрасывается в пользу новой цели пользователя.

Когда ваше приложение регистрируется для обработки намерений с действием глубоко в иерархии приложения, см. «Навигация в ваше приложение с помощью виджетов на главном экране» и Уведомления для руководства по настройке навигации вверх.

Начало работы с навигацией с помощью жестов

Android 11 вносит многочисленные изменения в ОС, включая некоторые настройки системной навигации.Начиная с Android 11, почти все устройства по умолчанию будут использовать новую навигацию Google с помощью жестов, что может потребовать небольшой корректировки с вашей стороны. Есть несколько способов сделать навигацию на Android 11 более удобной всего за несколько нажатий.

Жест быстрого переключения

Райан Уитвам / IDG Жест быстрого переключения

Android 11 позволяет быстро переключаться между приложениями, не переходя на экран обзора.

На некоторых телефонах есть учебные пособия, которые научат вас использовать новую систему навигации с помощью жестов, но ни в одном из них не дается объяснение жестов быстрого переключения.Это одна из самых полезных частей жестовой навигации Android, позволяющая мгновенно переключаться между приложениями.

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

Хотите вернуться? Проведите в другом направлении. Вы можете проводить пальцем в любом направлении, чтобы просмотреть последние приложения в хронологическом порядке, не вдаваясь в обзор.

Жест возврата

Райан Уитвам / IDG

В Android 11 всегда можно вернуться назад.

Большая часть жестов навигации Google является точной копией iPhone, но у Apple нет жеста назад. На Android вы можете вернуться, проведя пальцем от левого или правого края экрана. Этот жест может иногда мешать смахиванию в приложениях, но вы можете внести некоторые коррективы.

В соответствии с настройками жестов (расположение которых зависит от устройства) Android предлагает настройки чувствительности для жеста назад.Если вы слишком часто случайно нажимаете кнопку «назад», вы можете перетащить ползунок чувствительности в сторону «Низкая». На некоторых устройствах, таких как Google Pixels, вы получаете отдельные ползунки для левого и правого края, что может быть полезно, если вам нужен более легкий доступ к выдвигающимся навигационным меню на одной стороне экрана.

Забудьте о жестах, вернитесь к кнопкам

Райан Уитвам / IDG

Вы можете вернуть кнопки в Android 11, просто зайдите в настройки, чтобы воскресить их.

Навигация с помощью жестов не для всех, и это нормально.Вы все еще можете вернуться к классической парадигме трехкнопочной навигации. Расположение этого параметра зависит от устройства, но в стандартной версии Android он находится в разделе Настройки > Система > Жесты > Системная навигация . На телефонах Samsung он находится в нижней части меню дисплея. Помните, что при возврате к кнопочной навигации потребуется больше места на экране, а новый интерфейс многозадачности Google не так хорошо сочетается с кнопками.

NavStar для телефонов Samsung

Райан Уитвам / IDG

Приложение Samsung Navstar предлагает еще больше возможностей для настройки оболочки Android 11.

Samsung постоянно продает больше телефонов, чем другие производители Android, и его последние устройства поставляются с Android 11. Samsung также обновила свой пакет настройки GoodLock для Android 11, и один из модулей в этом популярном приложении называется Navstar. Если у вас телефон Samsung, это лучший способ настроить навигацию по системе.

GoodLock доступен в магазине Galaxy Store и будет связывать вас со всеми отдельными модулями, включая NavStar. Внутри NavStar вы можете изменить размер, расположение и цвет маркера навигации с помощью жестов.Здесь также есть полные настройки чувствительности к левому и правому жесту, но вы получаете только один ползунок в основных настройках на телефонах Samsung. Если вы решили вернуться к кнопочной навигации, в NavStar также есть параметры для настраиваемых кнопок, действий и значков.

Приложения для специальных возможностей

Райан Уитвам / IDG

Различные приложения для специальных возможностей, доступные в Android Store, позволяют еще больше настраивать навигацию.

Если вас не устраивает ни одна из опций навигации в Android 11, вы можете пойти совершенно другим путем с приложениями для специальных возможностей.В Play Store есть множество приложений, которые могут полностью заменить вашу системную навигацию. Такие приложения, как Assistive Touch и Simple Control, скачали миллионы.

Assistive Touch, самое популярное приложение в этой категории, позволяет управлять всей навигацией по системе с помощью одной плавающей кнопки. Простое управление собрало миллион установок, позволив людям настраивать кнопки навигации с помощью ярлыков и различных вариантов местоположения. Для этих приложений требуется активация специальных возможностей в Android 11, но приложения должны проводить вас через процесс установки.

Некоторые из этих советов, например приложения для специальных возможностей, могут сосуществовать. Например, вы можете настроить свою системную навигацию по своему усмотрению, а затем добавить приложение для специальных возможностей, такое как Assistive Touch, только для использования одной рукой. Вы мгновенно облетите Android.

Введение в основные концепции Android Navigation

Codemagic создает и тестирует ваше приложение после каждой фиксации, уведомляет выбранных членов команды и выпускает конечного пользователя. Автоматически.Начать

Автор Сувик Бисвас

Навигация — одна из основных концепций, которые нужно освоить, если вы работаете над любым приложением Android, имеющим сложную систему навигации.Правильно управляемая навигация также помогает уменьшить любые недостатки безопасности в вашем приложении за счет реализации таких функций, как аутентификация пользователя перед переходом к любому конфиденциальному контенту в приложении или предотвращение передачи любой конфиденциальной информации другим приложениям на устройстве.

За последний год навигационная система Android постоянно улучшалась, что привело к появлению множества новых концепций.

В этой статье я расскажу о некоторых важных концепциях навигации Android, которые входят в состав компонента навигации Android Jetpack.

Что такое компонент Jetpack Navigation?

Компонент Android Jetpack Navigation представляет собой набор из библиотек , инструментов и руководств , которые обеспечивают надежную структуру навигации для навигации в приложении .

Компонент навигации также предоставляет некоторые другие преимущества, например:

  • Обработка транзакций фрагментов
  • Правильная обработка действий Up и Back по умолчанию
  • Реализация глубинных ссылок
  • Шаблоны пользовательского интерфейса навигации, такие как панель навигации, нижняя навигация и т. Д.
  • Поддержка Safe Args
  • ViewModel support
  • Передача данных с помощью Android Bundle
  • Прослушивание изменений навигации
  • Анимированная навигация
  • Тестирование навигации

Компонент навигации работает как с Activity6, , так и с фрагментами . В примере приложения мы в основном будем работать с фрагментами, поскольку они также обеспечивают хорошую интеграцию с основным жизненным циклом Android.

Когда вы переходите к различным действиям, приложение поддерживает стек, известный как задний стек .Стек назад помогает управлять поведением кнопок «Вверх» и «Назад» внутри приложения. Фрагменты также поддерживают задний стек, но в этом случае весь задний стек фрагментов содержится в Activity.

Компонент «Навигация» соответствует установленному набору принципов навигации Android . Давайте посмотрим на них.

Принципы навигации в Android

Чтобы предоставить пользователям единообразный и интуитивно понятный интерфейс для самых разных приложений Android, существует несколько основных принципов, которым следует навигация.Компонент Navigation разработан для реализации этих принципов по умолчанию.

  • Всегда есть место старта: Каждое приложение Android должно иметь фиксированное место старта. Это экран, который пользователь видит каждый раз, когда открывает приложение. Это также последний экран, который они видят, когда возвращаются с других экранов в приложении с помощью кнопки «Вверх».

  • Задний стек всегда поддерживается: Когда пользователь переходит к различным действиям или фрагментам внутри приложения, всегда поддерживается задний стек .Задний стек помогает в навигации пользователя обратно к правильному месту назначения, откуда они пришли, когда они идут вверх или назад. Он следует структуре Last-In-First-Out (LIFO) .

    • Начальное назначение присутствует ниже в стеке
    • Текущее назначение присутствует наверху стека
    • Новые места назначения помещаются в верхнюю часть стека
    • При возврате текущее значение пункт назначения извлекается из стека
  • Вверх и назад: Обе кнопки «Вверх» и «Назад» действуют одинаково.Разница в том, что кнопка «Вверх» используется только для навигации внутри приложения — она ​​никогда не выведет вас из приложения. Таким образом, кнопка «Вверх» никогда не должна отображаться на первом экране приложения. Однако кнопка «Назад» может вывести вас за пределы приложения на экран, который находится на следующем уровне иерархии навигации.

  • Глубокие ссылки имитируют ручную навигацию: Независимо от того, используете ли вы глубокие ссылки или вручную переходите к определенному экрану внутри приложения, задний стек заполняется одними и теми же экранами.Итак, если вы перешли на определенную страницу с помощью глубинных ссылок, когда вы вернетесь назад, будет использоваться тот же задний стек, что и при переходе на этот экран вручную.

Ключевые части компонента навигации

Компонент навигации состоит из трех основных частей:

  • График навигации: Управляет навигацией вашего приложения. Это файл ресурсов, который состоит из пунктов назначения вместе с действиями , которые используются для перехода к другому пункту назначения от текущего.

  • NavHost : пустой контейнер, в котором отображаются пункты назначения из вашего навигационного графика.

  • NavController : это помогает в управлении навигацией приложений в пределах NavHost . Он управляет заменой целевого контента в NavHost по мере того, как пользователи перемещаются по вашему приложению.

Редактор навигации помогает визуализировать и редактировать всю систему навигации, используемую в вашем приложении, которая состоит из графика навигации , аргументов , анимации перехода и глубоких ссылок .

Наша цель

Мы будем создавать приложение под названием Quotes Trivia , в котором пользователь должен угадать правильного человека, который сказал отображаемую памятную цитату.

Поскольку основное внимание в этой статье уделяется Navigation , мы будем в основном рассматривать концепции, связанные с этим. Но если вы хотите поближе познакомиться с пользовательским интерфейсом и логикой приложения, вы можете перейти к репозиторию GitHub образца приложения, ссылка на который приведена в конце этой статьи.

Настройте компонент навигации

Мы будем использовать версию зависимостей Android KTX, так как в нашем проекте мы используем язык Kotlin .Но если вы используете Java , также доступны версии тех же зависимостей, отличные от ktx.

Чтобы использовать компонент Navigation , добавьте следующие зависимости в файл build.gradle (app) :

  dependencies {
    def nav_version = "2.3.0"

    реализация "androidx.navigation: navigation-fragment-ktx: $ nav_version"
    реализация "androidx.navigation: navigation-ui-ktx: $ nav_version"
}
  

Добавьте граф навигации

Создайте новый файл XML , щелкнув правой кнопкой мыши папку res и выбрав New > Android Resource File .Выберите тип ресурса Navigation и используйте имя файла navigation .

Свяжите файл ресурсов навигации

Вы должны связать файл navigation.xml в файле activity_main.xml , добавив NavHostFragment , чтобы использовать его для навигации по различным фрагментам вашего приложения.

  



    

        
        

    


  

Добавить фрагмент к графику

Перейдите в редактор навигации навигационной системы .xml файл. Нажмите кнопку New Destination и выберите экран, который вы хотите добавить к навигационному графику.

Перейти к другому пункту назначения

Для навигации от текущего пункта назначения к любому другому вам сначала нужно создать действие в графе навигации.

Вы должны написать код Kotlin явно для запуска действия, которое вы определили в навигационном графе.

  binding.startButton.setOnClickListener {view: View ->
    view.findNavController (). navigate (R.id.action_welcomeFragment_to_triviaFragment)
}
  

Условная навигация

Мы будем использовать условную навигацию для принятия решения о переходе пользователя к WonFragment или LostFragment . В нашей игре-викторине пользователь, которому удастся правильно ответить на примерно на 80% вопросов, будет считаться победителем.

Настройте действия из TriviaFragment на два фрагмента, к которым возможна навигация.

Запуск действий из кода Kotlin:

  if (rightAnswers  

Управление задним стеком

Если вы попытаетесь вернуться с WonFragment или LostFragment , приложение перенесет вас на TriviaFragment .Но это не должно быть действием по умолчанию, так как пользователь может захотеть вернуться прямо на главный экран. Кроме того, есть кнопки СЛЕДУЮЩИЙ МАТЧ и ИГРАТЬ СНОВА , если кто-то хочет снова сыграть в игру.

Итак, чтобы перенаправить пользователя непосредственно с WonFragment или LostFragment на WelcomeFragment , мы должны манипулировать задним стеком. Это можно легко сделать, установив Pop Behavior для любого действия из Navigation Editor .

Мы установим поведение всплывающего окна action_triviaFragment_to_wonFragment и action_triviaFragment_to_lostFragment до popUpTo TriviaFragment (включительно).

Использование Safe Args

Safe Args - это подключаемый модуль Gradle, который генерирует простые классы объектов и построителей для типобезопасной навигации, а также упрощает передачу аргументов.

Добавьте следующий путь к классам в сборку верхнего уровня вашего проекта.gradle file:

  dependencies {
    def nav_version = "2.3.0"
    classpath "androidx.navigation: navigation-safe-args-gradle-plugin: $ nav_version"
}
  

Примените плагин на уровне приложения build.gradle файл:

  примените плагин: "androidx.navigation.safeargs.kotlin"
  

Это генерирует код Kotlin, подходящий для модулей только для Kotlin. Если вы используете язык Java или смешанные модули Java и Kotlin, используйте следующее:

  примените плагин: "androidx.navigation.safeargs "
  

Выполните чистую сборку проекта.

Теперь вы можете заменить идентификаторы , используемые для указания действий навигации, сгенерированными классами NavDirections , например:

  binding.startButton.setOnClickListener {view: View ->
    view.findNavController (). navigate (WelcomeFragmentDirections.actionWelcomeFragmentToTriviaFragment ())
}
  

Передача данных между фрагментами

Вы можете добавить аргументы, которые вы хотите передать, непосредственно из Navigation Editor , выбрав Fragment .

Сделайте чистую сборку.

Для передачи аргументов из фрагмента необходимо изменить код Kotlin следующим образом:

  view.findNavController (). Navigate (TriviaFragmentDirections.actionTriviaFragmentToWonFragment (numQuestions, rightAnswers))
  

Android Bundle используется для получения аргументов в месте назначения:

  val args = WonFragmentArgs.fromBundle (requireArguments ())

// Установка значений в TextView (s)
правильноAnswersText.текст = args.numCorrect.toString ()
totalQuestionsText.text = args.numQuestions.toString ()
  

Добавить поддержку кнопки «Вверх»

Интерфейс пользователя NavigationUI может обрабатывать поведение кнопки «Вверх» самостоятельно, так что вам не нужно управлять им явно. Он также автоматически скрывает кнопку «Вверх», когда мы находимся на главном экране приложения.

Внутри MainActivity свяжите NavController с ActionBar :

  val navHostFragment = supportFragmentManager.findFragmentById (R.id.myNavHostFragment) как NavHostFragment
val navController = navHostFragment.navController
NavigationUI.setupActionBarWithNavController (это, navController)
  

Затем переопределите метод onSupportNavigateUp из действия:

  переопределите удовольствие onSupportNavigateUp (): Boolean {
    val navController = this.findNavController (R.id.myNavHostFragment)
    вернуть navController.navigateUp ()
}
  

Это позаботится обо всей навигации между различными фрагментами этого действия.

Давайте добавим дополнительное меню, которое будет перемещать пользователя к AboutFragment . Это будет отображаться только в WelcomeFragment нашего приложения.

Добавьте AboutFragment к графу навигации, но не создавайте для него никаких действий.

Создайте новый ресурс меню с именем overflow_menu , щелкнув правой кнопкой мыши на res и выбрав New > Android Resource File .

Объявите элемент с тем же идентификатором , что и у фрагмента, к которому вы хотите перейти.

  
    <элемент
        android: id = "@ + id / aboutFragment"
        android: title = "@ string / about_title" />

  

Чтобы отображать меню только в WelcomeFragment , добавьте во фрагмент следующее:

  override fun onCreateView (
    надувной: LayoutInflater, контейнер: ViewGroup ?,
    saveInstanceState: пакет?
): Вид? {
    // ...

    // Добавляем эту строку
    setHasOptionsMenu (истина)

    возвратная привязка.корень
}
  

Переопределите onCreateOptionsMenu и увеличьте ресурс меню:

  переопределить удовольствие onCreateOptionsMenu (меню: Меню, надуватель: MenuInflater) {
    super.onCreateOptionsMenu (меню, надувной элемент)
    inflater.inflate (R.menu.overflow_menu, меню)
}
  

Переопределить onOptionsItemSelected , чтобы подключить его к нашему NavigationUI :

  переопределить удовольствие onOptionsItemSelected (item: MenuItem): Boolean {
    вернуть NavigationUI.onNavDestinationSelected (
        элемент,
        requireView (). findNavController ()
    ) || super.onOptionsItemSelected (элемент)
}
  

Добавить панель навигации

Компонент панели навигации является частью библиотеки дизайна материалов Android. Это панель пользовательского интерфейса, которую можно открыть, проведя пальцем от левого края экрана или щелкнув значок меню , присутствующий в панели действий . Обычно он присутствует в приложениях с пятью или более экранами.

Добавьте зависимость Gradle Material Design в сборку уровня приложения.gradle file:

  dependencies {
    def material_version = "1.2.1"

    реализация "com.google.android.material: material: $ material_version"
}
  

Добавьте еще один фрагмент в граф навигации с именем RulesFragment .

Создайте новый ресурс меню с именем navdrawer_menu и добавьте к нему два элемента item .

  
    <элемент
        android: id = "@ + id / rulesFragment"
        android: icon = "@ drawable / ic_rules"
        android: title = "@ string / rules_title" />
    <элемент
        android: id = "@ + id / aboutFragment"
        android: icon = "@ drawable / ic_about"
        android: title = "@ string / about_title" />

  

В activity_main.xml , оберните LinearLayout в DrawerLayout :

  

    

        

            

        

    


  

Добавьте NavigationView внизу DrawerLayout .

  
  

Теперь перейдите к MainActivity :

  • Добавьте две переменные:

      private lateinit var drawerLayout: DrawerLayout
    приватный lateinit var appBarConfiguration: AppBarConfiguration
      
  • Инициализировать DrawerLayout внутри onCreate :

      drawerLayout = binding.drawerLayout
      
  • Измените, чтобы включить ящик:

      NavigationUI.setupActionBarWithNavController (this, navController, drawerLayout)
      
  • Создайте AppBarConfiguration и подключите NavigationUI к представлению навигации:

      appBarConfiguration = AppBarConfiguration (navController.graph, drawerLayout)
    NavigationUI.setupWithNavController (binding.navView, navController)
      
  • В методе onSupportNavigateUp замените следующее:

      return navController.navigateUp ()
      

    с этим:

      return NavigationUI.navigateUp (navController, drawerLayout)
      

    Это помогает заменить кнопку Вверх кнопкой меню , когда мы переходим на первый экран приложения.

Вы можете добавить свойство headerLayout в NavigationView внутри activity_main.xml :

  
  

Файл nav_header.xml выглядит следующим образом:

  

    


  

Прослушивание изменений навигации

Хотя вы не видите кнопку меню на других страницах, кроме первого экрана, вы все равно сможете получить доступ к навигационному ящику , проведя пальцем от левого края экрана на других страницах .

Чтобы решить эту проблему и предотвратить ее открытие на других страницах, мы должны прислушиваться к изменениям навигации и активировать ящик только на первом экране.

В файле MainActivity внутри метода onCreate добавьте следующее:

  navController.addOnDestinationChangedListener {nc: NavController, nd: NavDestination, _: Bundle? ->
    if (nd.id == nc.graph.startDestination) {
        drawerLayout.setDrawerLockMode (DrawerLayout.LOCK_MODE_UNLOCKED)
    } еще {
        drawerLayout.setDrawerLockMode (DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
    }
}
  

Теперь вы не сможете открывать панель навигации с каких-либо страниц, кроме первого экрана.

Добавить кнопку «Поделиться»

Вам всегда захочется поделиться своим выигрышным счетом с друзьями. Итак, давайте добавим в наше приложение кнопку Share с помощью Intent.

Намерения могут быть в основном двух типов:

  • Явное намерение: Для запуска действий в одном приложении
  • Неявное намерение: Это помогает предоставить абстрактное описание действия, которое вы хотите выполнить, который используется для запуска действий других приложений на устройстве

Если на устройстве пользователя присутствует несколько приложений Android, которые могут обрабатывать конкретное неявное намерение, то появляется окно выбора.

Создайте новый файл ресурсов menu с именем share_menu .

Добавьте в него пункт меню:

  

    <элемент
        android: id = "@ + id / share"
        android: enabled = "правда"
        android: icon = "@ drawable / ic_share"
        android: title = "@ строка / share_title"
        android: visible = "true"
        app: showAsAction = "ifRoom" />


  

Мы хотим показать значок share только в WonFragment , поэтому нам нужно будет настроить только этот фрагмент.

Внутри onCreateView add:

Создайте метод для определения Intent :

  private fun getShareIntent (): Intent {
    val args = WonFragmentArgs.fromBundle (requireArguments ())
    val shareIntent = Намерение (Intent.ACTION_SEND)
    shareIntent.setType ("текст / простой")
        .putExtra (
            Intent.EXTRA_TEXT,
            getString (R.string.share_text, args.numCorrect, args.numQuestions)
        )
    return shareIntent
}
  

Метод запуска действия:

  private fun shareSuccess () {
    startActivity (getShareIntent ())
}
  

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

  переопределить развлечение onCreateOptionsMenu (меню: Меню, надуватель: MenuInflater) {
    super.onCreateOptionsMenu (меню, надувной элемент)
    inflater.inflate (R.menu.share_menu, меню)

    if (null == getShareIntent (). resolveActivity (requireActivity (). packageManager)) {
        menu.findItem (R.id.share) ?. isVisible = false
    }
}
  

Переопределить метод onOptionsItemSelected для обработки действия при нажатии кнопки общего доступа.

  переопределить удовольствие onOptionsItemSelected (item: MenuItem): Boolean {
    когда (поз.itemId) {
        R.id.share -> shareSuccess ()
    }

    вернуть super.onOptionsItemSelected (элемент)
}
  

Анимация навигации

Вы можете применять различные типы анимации к Navigation .

Прежде всего, создайте новый файл ресурсов анимации, щелкнув правой кнопкой мыши папку res и выбрав New > Android Resource File .

Давайте определим затухающую анимацию :

  

    <альфа
        android: duration = "@ android: integer / config_mediumAnimTime"
        android: fromAlpha = "1.0"
        android: toAlpha = "0.0" />

  

Анимация скольжения может быть определена следующим образом:

  

    <перевести
        android: duration = "@ android: integer / config_shortAnimTime"
        android: fromXDelta = "- 100%"
        android: fromYDelta = "0%"
        android: toXDelta = "0%"
        android: toYDelta = "0%" />

  

Вы можете использовать Navigation Editor для непосредственного применения анимации.

После применения всех анимаций приложение выглядит следующим образом:

Заключение

Навигационный компонент Android позволяет легко управлять всей навигационной системой приложения.

Ваш комментарий будет первым

Добавить комментарий

Ваш адрес email не будет опубликован.