Конспект лекций по дисциплине «Разработка мобильных приложений»
Уважаемые студенты.
В данной части лекции мы поговорим
о мобильной разработке в целом,
сделаем первые шаги в мир индустрии
программирования приложений.
Что вам понадобится для полноценного
изучения курса?
Для начала это знание любого
объектно-ориентированного языка,
будь то Java, C#, Python, Objective-C,
а также язык разметки XML — по синтаксису
он почти идентичен языку HTML.
Следующим пунктом для быстрого погружения
в мир разработки будет знание
английского языка.
Если вы заметили, то английский язык
является языком международного общения,
и, как правило, все новости, статьи
и материалы выходят именно на этом языке.
Поэтому знать его непременно нужно,
если вы нацелены на дальнейшее развитие
своих навыков.
На курсе мы установим среду
интегрированной разработки под названием
Android Studio, системные требования
которой доступны по следующей ссылке.
Данная программа достаточно мощная,
она собирает код и ресурсы приложения,
давая на выходе уже готовое приложение.
Обратите внимание, что Android Studio —
достаточно тяжеловесная программа.
Нежелательно запускать одновременно с ней
игры, приложения и сторонние программы
во избежание зависания программы.
Будем надеяться, что вскоре разработчики
ускорят работу программы,
ведь с момента первого запуска
скорость работы увеличилась во много раз.
Раньше она имела привычку
запускаться 10 минут.
В настоящее время на запуск программы
уходит не более минуты.
И последним дополнительным существенным
бонусом будет, если у вас уже есть
смартфон или планшет
с операционной системой Android.
Если у вас таковой имеется, то на
следующих занятиях вы сможете запустить
на своем телефоне свое первое приложение,
чтобы показать его друзьям, родным
и знакомым.
Теперь поговорим немного
о системе Android.
Android — сейчас наиболее популярная
операционная система для смартфонов,
планшетов, электронных книг,
цифровых проигрывателей, наручных часов,
фитнес-браслетов, игровых приставок,
ноутбуков, нетбуков, смартбуков,
телевизоров, очков Google Glass,
бытовых роботов и других устройств.
Благодаря этой операционной системе
у нас имеется огромный выбор смартфонов
по цене от $50, что почти в 6 раз дешевле
продуктов от компании Apple.
Мобильные устройства на платформе Android
быстро дешевеют в связи с высокой
конкуренцией между производителями.
По прогнозам компании Google,
к 2019 году цена снизится на 21%.
Что означает
«система с открытым исходным кодом»?
Это значит, что любой разработчик может
бесплатно скачать исходный код Android,
изменить его и опубликовать свою версию.
Многие компании так и делают,
что позволяет им выпускать недорогие
устройства и продавать по всему миру.
В результате все больше людей начинают
пользоваться смартфонами и мобильным
интернетом под эгидой Android'а.
Становиться разработчиком мобильных
приложений под Android весьма выгодно,
потому что аккаунт разработчика стоит
всего $25.
В результате вы получите возможность
показать свои приложения всему миру
через официальный маркет Google Play.
Хочется повторить, что вам потребуется
единоразово приобрести
аккаунт разработчика всего за $25,
в отличие от аккаунта системы iOS,
который требует оплаты $99 ежегодно.
Android является катализатором
экономического роста.
По прогнозам компании Google,
к 2020 году в сфере мобильных технологий
будут работать 15 миллионов человек,
поэтому начинать уже нужно сейчас.
На данном графике мы рассмотрим
процентное соотношение всех версий,
а на следующем графике мы рассмотрим
уже в таблице, сколько процентов
каждая версия сейчас занимает на рынке.
С приходом осени выходит новое обновление
версии Android.
Как правило, весной проводят
анонс новой версии,
а осенью выходит ее стабильная версия,
доступная для скачивания
каждому пользователю.
Данный график был составлен
7 мая 2018 года.
Версии, которые поддерживают
менее 0,1% на рынке,
не отображены на графике.
Версии, которые постепенно выходят
из рынка мобильных устройств, —
это Donut, Eclair, Froyo и Honeycomb.
В таблице и на графике
они не будут отображены.
Каждая версия начинается с буквы
английского алфавита
и означает какую-нибудь сладость,
поэтому можно предположить,
что разработчики Android —
заядлые сладкоежки.
Следует отметить, что на графике-рисунке
самые популярные версии сейчас —
это Marshmallow и Nougat,
что с английского переводится:
«зефир» и «нуга».
На этом наша лекция подходит к концу.
Поздравляю вас со вступлением
в мир зеленых роботов,
где мы познакомились с экосистемой
операционной системы Android,
сравнили его с айфоном,
узнали, что требуется для начала работы,
и вдохновились необычными фактами.
На следующем занятии мы установим
необходимые программы
для запуска своей первой программы.
Установка необходимого программного обеспеченияВ этой части лекции мы поговорим с вами
подробнее о системе Android и установим
необходимое программное обеспечение
для своего первого запуска приложения
на виртуальном эмуляторе
или реальном устройстве.
Как уже отмечалось в прошлой лекции,
система Android представляет собой
разностороннюю платформу приложений,
на основе которой можно создавать
приложения и игры для мобильных устройств
в среде языка Java.
Android — это операционная система,
основанная на ядре Linux.
Android разработан
в Android Open Source Project, и сейчас
данный проект возглавляет Google.
Операционную систему Android можно
разделить на четыре области,
как показано на следующем рисунке.
Разработчик Android обычно работает
с двумя верхними слоями для создания
новых приложений для платформы Android.
Остановимся более подробно на уровнях.
Уровни можно охарактеризовать
по следующим слоям.
1-й уровень — приложения (applications).
Он содержит кастомные приложения,
такие как браузер, камера, галерея,
музыка и телефон.
Следующий уровень — это структура
приложения (application framework),
которая позволяет осуществлять
взаимодействия на высоком уровне
системы Android.
Третий уровень содержит в себе библиотеки
и среду выполнения Runtime.
Библиотеки созданы для работы многих
общих функций фреймворка, таких как
графический рендеринг, хранение данных,
просмотр web-страниц,
а выполняемая среда Runtime — для работы
с приложениями Android.
И последний, четвертый уровень —
ядро Linux.
Это уровень связи для базового
оборудования, а именно запуск камеры,
работа дисплея телефона,
включение Bluetooth и прочее.
Разработка приложения
для Android-платформы начинается
с установки пакета JDK 8
и заканчивается запуском на устройстве
приложения "Hello World!".
Алгоритм установки можно условно
разделить на 3 пункта.
Первый пункт — это установка инструмента
Java Standard Edition Development Kit 8.
Возможно, вы заметите, что на сайте Oracle
вышла уже 10-я версия Java, но не спешите
устанавливать ее, поскольку она все еще
нестабильна в связке с Android Studio
и, по словам многих разработчиков Android,
она может стать причиной ошибок,
поэтому мы устанавливаем стабильную
8-ю версию Java, чтобы у вас все работало
и запускалось.
Если у вас уже установлена Java,
то переходите сразу к установке программы
Android Studio.
Следующим пунктом на пути установки
программного обеспечения является
установка интегрированной среды
разработки Android Studio,
но кроме нее существуют и другие среды,
как NetBeans, Eclipse, Visual Studio,
IntelliJ IDEA.
Поскольку рекомендуемой средой разработки,
согласно документации, является все же
Android Studio,
мы ее и будем использовать.
Прекрасным и вдохновляющим стартом
для вас будет то, что все программное
обеспечение абсолютно бесплатно
и подходит для всех операционных систем,
будь то Windows, Mac или Linux.
Устанавливайте только с официальных
сайтов и смело запускайте у себя
на компьютере.
И последним пунктом является установка
виртуального эмулятора, если у вас нет
реального физического устройства
с операционной системой Android.
После описания всего процесса
можно приступать к установке
программного обеспечения.
Если у вас возникнут сложности,
а они возникают из-за различия версий и,
возможно, из-за ограничения прав доступа,
не забывайте обращаться за помощью
к Google или Stack Overflow.
Перейдем к установке Java.
Установка программной среды
Java SE Development Kit 8.
На данный момент используется
Java 8-й версии,
доступная по ссылке на слайде.
Скачивать пакет JDK 8 можно
с официального сайта компании Oracle.
После принятия лицензионного соглашения
требуется скачать инсталляционный пакет
под свою операционную систему.
Дальнейшая установка будет рассмотрена
на примере операционной системы
Windows 10.
Для того чтобы установить Java 8 на свой
компьютер, запустите скачанный файл,
после чего начнется процесс установки.
В окне приветствия мастера установки
нажмите Next, после чего откроется окно
выбора директории по умолчанию,
где требуется установить
программный пакет.
При желании директорию можно изменить,
нажав на кнопку Change.
Далее нажимаем на Next.
Далее у нас запустится
статус выполнения установки
и в конечном итоге
окно завершения установки,
после чего мастер установки предлагает
перейти к технической документации
и руководству для работы Java.
Нажатием на кнопочку Next Steps откроется
следующая страница с документацией,
являющаяся полезной для изучения.
Следующим этапом у нас будет установка
интегрированной среды разработки
Android Studio.
На данный момент Android Studio является
версией IDE, что с английского означает
«интегрированная среда разработки»,
где включена версия Android SDK.
Про менеджера SDK мы поговорим
чуть позднее.
Сейчас мы видим окно приветствия
Android Studio.
Стоит обратить внимание, что данный
программный продукт занимает значительное
место на диске и требует высокую
производительность от компьютера
или ноутбука.
После нажмите на кнопку Next.
Откроется окно для выбора отдельных
компонентов для установки.
По умолчанию выбираются все, а также
выводится информация о требуемом месте
на диске в размере 2,3 гигабайта.
Требуется указать место для установки
данного программного обеспечения.
Как правило, оно выбирается
автоматически.
Следует обратить внимание на то,
чтобы в директории выбранной папки
не присутствовали символы кириллицы —
в будущем это усложнит сборку проекта.
Все символы должны быть прописаны
на латинице.
В новом окне мастера установки появляется
пункт, где не нужно ставить галочку.
Если ее поставить, то на рабочем столе
не появится ярлык программы
Android Studio.
На данном этапе следует нажать на кнопку
Install для запуска процесса установки.
На данном экране у нас распаковка файлов
из архива и отображение самого процесса
установки на компьютер.
Установка обычно занимает
от 5 до 10 минут.
На этом установка интегрированной среды
разработки Android Studio окончена.
После этого откроется
стартовое окно Android Studio
при нажатии на кнопку Finish.
Если вы устанавливаете
Android Studio впервые,
то никаких пользовательских настроек
вам не нужно —
нажимая на данный пункт,
кликаем на кнопочку Ok.
Далее у нас открывается теперь
окно приветствия.
Кликаем Next.
Выбираем стандартную версию.
Тему выберем IntelliJ — она светлая.
Для продолжительной работы рекомендуется
тема Darcula.
Следом здесь нам потребуется установить
SDK-компоненты, которые мы рассмотрим
на следующей лекции.
И нажимаем на кнопочку Finish.
Здесь у нас скачиваются дополнительные
пакеты, плагины.
Наконец у нас открылось стартовое окно.
В следующей части мы установим все
оставшиеся необходимые компоненты,
а также виртуальный эмулятор.
Правильная установка Android Studio
гарантирует вам ее бесперебойную работу.
Настройка SDK Manager и создание эмулятораВ третьей части нашей лекции мы
рассмотрим SDK Manager, а также настроим
работу виртуального эмулятора
и физического устройства.
В установке полного программного
обеспечения для разработки мобильных
приложений под платформу Android
ничего сложного нет.
Однако если вы устанавливаете его впервые,
вам все же потребуется помощь.
При неправильной установке
велика вероятность ошибки
при запуске программы.
Возможно, вы не установите
один необходимый пакет,
и из-за этого приложение
не будет запускаться на устройстве.
Поэтому мы устанавливаем программу
поэтапно, чтобы никаких конфликтов
в будущем не возникало.
Как правило, всего необходимого
обеспечения для начала работы
изначально в пакете SDK не установлено,
поэтому нам потребуется вручную загрузить
недостающие компоненты.
И для начала нам нужно запустить
менеджер SDK через окно приветствия.
Откройте последовательно пункт Configure
и кликните на SDK Manager.
SDK Manager содержит в себе три вкладки.
Первая вкладка SDK Platforms содержит
весь основной функционал,
используемый при разработке.
На этой вкладке можно выделить
целевые платформы, под которые мы будем
разрабатывать приложение.
Я всегда рекомендую устанавливать
последние версии платформы.
В частности, рекомендуется установить
все пакеты начиная с версии
Android 5.0 Lollipop.
Настроим сейчас Android 5.0 Lollipop
для примера.
Для скачивания и установки
необходимого пакета нажмите
на квадрат напротив выбранного пакета.
В качестве примера установим Android 5.0,
как уже говорилось.
Далее нажмем на кнопку Apply.
Запустится окно подтверждения загрузки
и, соответственно, версии для установки.
Подтвердим действие и будем ожидать
загрузку пакета на наш компьютер.
Далее у нас сейчас откроется окно
загрузки пакета на наш компьютер.
Обратите внимание, что пакеты скачиваются
из сети, и убедитесь в том, что
интернет-соединение позволит скачивать
большие объемы данных.
Нажмем на кнопку Finish.
После этого пакет уже загружен из сети
и установлен.
Таким же способом можно обновлять
существующие версии.
Для удаления пакета процедура схожая.
Уберите галочку.
Слева от названия пакета
при нажатии на галочку появится крестик —
это предупреждение значит, что вы
собираетесь деинсталлировать
данный пакет.
После кликните на кнопку Apply.
Откроется новое окно
с подтверждением удаления
и при нажатии на кнопку начнется
процесс удаления.
Процесс удаления занимает
гораздо меньше времени.
SDK Manager также позволяет загружать
любые версии платформы
для тестирования приложений
и работы с устройством.
Теперь перейдем на вкладку SDK Tools.
Для нас прежде всего важны
следующие пакеты: GPU Debugging tools —
нажмем на галочку,
далее нам потребуется добавить
Google Play Licensing Library,
Google Play Services, Google USB Driver,
а также Google APK Expansion library.
Нажмем на кнопочку Apply.
Подтвердим наше действие,
и начнется установка
всех перечисленных пакетов.
Данные пакеты устанавливают
репозиторий Android
и сервисы Google Play, а пакет
Google USB Driver представляет собой
драйвер для работы с данными телефона.
Благодаря данным пакетам мы сможем
запускать приложение
на настоящем телефоне через USB-кабель.
Если планируется использование эмулятора,
то также следует установить пакет
Android Emulator Intel x86
Emulator Accelerator.
Если в процессе разработки
или тестирования будут возникать проблемы
с какими-нибудь версиями
операционной системы Android,
то вполне вероятно, что проблема
в отсутствии определенных компонентов
для определенных платформ.
Пакеты все скачались и установились.
Нажмем на кнопку Finish.
Также здесь, в данном пакете
Android SDK Build-Tools,
появилось новое обновление.
Мы можем обновить его сейчас.
Нажмем на кнопочку Ok.
Далее мы рассмотрим, как запускать
SDK Manager не из стартового экрана,
а из консоли.
Мы рассмотри это немного позднее.
В следующей части лекции мы запустим наш
первый проект на виртуальном эмуляторе.
Теперь мы нажмем на кнопочку Finish.
На этом третья часть урока
у нас окончена.
Создание проекта и запуск на устройствеВ данной части лекции мы создадим проект,
запустим наше первое приложение
на устройстве
и проведем настройку программы.
На начальном экране Android Studio
выберите пункт
Start a new Android project.
После этого отобразится новое диалоговое
окно — создание нового проекта.
В поле Application name мы введем
название проекта:
в качестве имени укажем Example 1.
В поле Company domain указывается
домен приложения или тот пакет классов,
где будет размещаться
главный класс приложения.
Рекомендуется задавать
осмысленное значение в этом поле,
поскольку при размещении
вашего приложения в маркет Google Play
доменное имя должно быть уникальным.
На данном этапе можно оставить
значение по умолчанию.
Project location — это следующее поле.
В данной локации у нас будет установлена
папка, где проект будет создан.
Не используйте в названии пути кириллицу,
потому что Android Studio
не читает кириллицу.
При обнаружении кириллицы
программа выведет предупреждение
о некорректных символах.
И последние два пункта
с поддержкой языков C++ и Kotlin
нам не требуются.
Далее мы кликаем кнопку Next.
В следующем окне нам предлагается выбрать
минимальную поддерживаемую
версию проекта.
Если по умолчанию у вас не стоит
API 21: Android 5.0 Lollipop,
то установите ее в качестве
целевой версии для разработки.
Далее кликаем кнопку Next.
Далее нам откроется новое окно,
где необходимо выбрать шаблон проекта.
Самыми распространенными являются
Basic Activity и Empty Activity.
Для старта нашего приложения мы выберем
пустой шаблон под названием
Empty Activity.
Кликаем кнопку Next.
При выборе Empty Activity
на следующем шаге нужно задать
ряд настроек проекта, а именно
название нашего проекта
и название разметки.
В Activity Name — это название
главного класса приложения,
в пункте Layout Name —
название файла xml,
в котором будет храниться
определение визуального интерфейса.
Generate Layout File — здесь при галочке
это значит, что генерируется файл xml
с определением визуального интерфейса.
И в отмеченном состоянии
Backwards Compatability (AppCompat)
позволяет установить обратную зависимость
между различными версиями Android.
Оставим все настройки по умолчанию.
Далее — на кнопку Finish.
Через некоторое время Andriod Studio
создаст и откроет проект.
После этих шагов Android Studio
создает папку для проекта на диске
в местоположении, указанном
при создании проекта.
Далее происходит построение проекта.
Это может занять несколько минут.
Android Studio использует Gradle
в качестве системы построения.
Иногда система сборки выдает
сообщение с предупреждением
и открывает окно редактора кода,
отображающее текущий проект.
На запуск проекта обычно уходит
от 1 до 3 минут
в зависимости от мощности
вашего программного обеспечения.
Так как мы запускали проект впервые,
на сборку ушло больше времени,
чем требуется.
Открылось окно, в котором отображаются
подсказки для работы в Android Studio.
Мы можем нажать на Next Tip,
и откроется новая подсказка.
Далее мы можем вернуться
к предыдущей подсказке,
можем отключить вывод этой подсказки
или закрыть.
В данном случае мы закроем.
В Android Studio у нас в нижней части
окна появилось предупреждение о том,
что требуется установить пакет
с версией Android 27.0.3
и синхронизировать проект.
Нажмем на кнопочку для того,
чтобы подгрузить оставшийся пакет.
Нажмем на кнопочку Finish.
И теперь проект снова собирается.
У нас открылись два файла:
activity_main и MainActivity.java.
Прежде чем изучать интерфейс приложения,
мы создадим виртуальный эмулятор
и запустим наше приложение.
Для создания эмулятора Android
нам понадобится Android AVD Manager,
что означает Android virtual device,
моделирующий конфигурацию
определенного типа Android-устройства.
Не беспокойтесь,
ставить больше ничего не потребуется.
Просто нажмите на
Create New Virtual Device.
Во вкладке Tools находится
наш AVD Manager.
Мы нажмем на кнопку
Create Virtual Device.
Далее нам потребуется выбрать устройство.
Мы установим самое первое в списке.
Нажмем на кнопку Next.
Нам потребуется скачать пакет.
Нажмем на кнопку Finish.
Теперь нам доступно данное устройство
для тестирования.
Нажмем на кнопку Next.
Можем дать ему название,
но оставим название по умолчанию
и нажмем на кнопочку Finish.
Мы создали виртуальный эмулятор.
Теперь он находится у нас в созданных.
Мы можем увидеть, что он занимает
101 мегабайт на диске,
имея последнюю версию Android.
Закроем окно.
И теперь пришло время запустить
наш первый проект,
созданный в Android Studio.
Нажмите на кнопку Run App или Shift+F10.
Далее высвечивается наше устройство,
которое мы добавили.
Мы его выбираем.
Здесь также можно установить его
в качестве устройства по умолчанию,
нажав кнопочку.
Нажимаем на галочку
и кликаем на кнопку Ok.
Далее наш проект начинает собираться.
Запускается эмулятор.
Установка приложения на эмулятор
и запуск приложения.
На это уйдет некоторое время.
Чем мощнее ваш компьютер,
тем меньше времени понадобится.
Поскольку эмулятор —
вещь достаточно медлительная
на некоторых устройствах,
поэтому будем ожидать улучшения.
Мы можем перемещать эмулятор,
чтобы он не перекрывал текст.
Также есть несколько рекомендаций
для запуска эмуляторов.
Запускайте их в начале сеанса
перед сборкой приложения
и не закрывайте, пока не будет выполнена
проверка приложения, чтобы не дожидаться
повторной загрузки эмулятора.
Кроме того, не следует одновременно
запускать несколько эмуляторов,
поскольку это существенно нагружает
память компьютера.
Сборка проекта завершилась,
сейчас Android Studio устанавливает
приложение на эмулятор.
Наш эмулятор запустился,
и мы увидели первый "Hello World!"
на экране эмулятора.
Для того чтобы запустить приложение
на реальном Android-устройстве,
нам понадобится устройство на Android
(например, смартфон или планшет)
и кабель USB для подключения
устройства Android к компьютеру.
Для начала нам нужно включить
режим разработчика на устройстве.
Откройте настройки на вашем устройстве
во вкладке «О телефоне».
Должна быть подробная информация
о памяти, прошивке, версии и прочее.
Нажмите вкладку «Версия»
или «Номер сборки» 7 раз,
после чего вам станет доступен
режим разработчика
и появятся новые настройки.
Далее подключите ваш смартфон
к компьютеру с помощью кабеля USB.
Разрешите отладку через USB
в меню настройки для разработчиков
на вашем устройстве.
Теперь запустите этот же проект,
нажав на Run App на панели инструментов
или нажмите на комбинацию клавиш:
Shift + F10.
Откроется окно выбора подключенного
реального устройства или эмулятора.
Выберите ваше устройство и нажмите Ok.
Подробнее, как это сделать, —
по ссылке в описании к видео.
Итак, мы запустили наш первый проект
на виртуальном эмуляторе
и реальном устройстве.
В следующей части мы добавим
пользовательские настройки для удобства
работы с программной средой.
Настройка внешнего вида Android StudioВ прошлой части лекции мы настроили
виртуальный эмулятор,
поэтому закрывать его не рекомендуется,
чтобы не ожидать повторной загрузки
и сборки продолжительное время.
В этой части лекции мы зададим
пользовательские настройки для удобства
работы с программной средой.
В опции меню File откройте вкладку
Settings, то есть настройки.
Либо можно это сделать комбинацией клавиш
Ctrl + Alt + S.
В данном случае нам необходимо перейти
в боковое меню под названием
Appearance & Behavior.
И в пункт меню Appearance.
Здесь можно настроить внешний вид студии.
По желанию, можно сделать в темных тонах.
Для этого нажмите на значение Darcula
и примените его с помощью кнопки Apply.
Как мы видим, тема изменилась,
стала темнее, и она более комфортна
для работы с программной средой
длительное время.
Также существует тема Windows.
И тема IntelliJ.
Мы ее и применим.
Вся разница между IntelliJ и Windows
заключается, как мне кажется, в шрифтах.
В остальном они полностью идентичны.
Мы сменили темную тему на светлую.
В данном случае мы будем пользоваться
IntelliJ.
Следующим шагом будет переход
в меню Editor.
В раскрывающемся списке откройте
пункт меню General.
И кликните на пункт Appearance.
Также снова нам потребуется проверить,
поставлены ли галочки
напротив пункта Show line numbers.
Здесь стоит.
Это показ числовых строк.
И пункт Show method separators —
это показ разделителей методов.
Первая функция будет отображать
номера строк слева от текста,
а вторая будет рисовать разделители
между методами в коде.
Включение данных опций будет полезно,
особенно для новичков.
Нажмем на Ok.
Далее снова откроем окно настроек.
Последний шаг — это настройка
автодополнения.
Для этого,
находясь в этой же вкладке меню,
перейдите в пункт Code Completion.
Напротив Case sensitive completion
выберите значение None.
Опция по умолчанию подразумевает
срабатывание автодополнения,
в данном случае First letter.
Она означает срабатывание
автодополнения только в том случае,
если первая буква набрана
в правильном регистре.
Опция None, которая нам нужна,
будет вызывать автодополнение
независимо от того, в каком регистре
вы начали набирать код.
Нажмем на кнопочку Ok.
И на этом мы подходим к концу
первой «нулевой» лекции.
Мы познакомились с системой Android,
установили все необходимое
программное обеспечение,
запустили первый проект на эмуляторе
и на реальном устройстве,
а также настроили среду
для удобного использования.
Интерфейс Android StudioВ первой лекции мы создали проект
и запустили его на эмуляторе
и на физическом устройстве.
Теперь мы познакомимся с интерфейсом
программы Android Studio.
Вы можете открыть прошлый проект
или создать новый проект,
чтобы рассмотреть детально
все панели и кнопки управления
для работы со средой разработки.
В правом верхнем углу у нас располагается
панель Toolbar, которая предоставляет
быстрый доступ к наиболее часто
используемым командам.
Мы уже использовали одну команду
из данной панели — запуск приложения.
Здесь также есть команда
старта SDK менеджера — вот она,
запускает его из самой программы,
а не из консоли стартового окна.
Если нам потребуется подгрузить
дополнительные компоненты, то мы можем,
не выходя из программы, запустить Manager
либо запустить Manager из вкладки Tools.
Здесь находится наш SDK Manager.
В левой части панели находится
панель навигации — она находится напротив
панели Toolbar.
Она называется Navigation bar
и помогает перемещаться по проекту
и открывать файлы для редактирования,
тем самым обеспечивая более сжатый вид
структуры проектов из окна Project.
Окно редактора позволяет создавать
и редактировать код.
В зависимости от типа открытого файла
вид редактора может измениться.
Например, при просмотре файла макета
activity_main окно редактора отображает
редактор макета.
Здесь у нас код XML,
и мы находимся на вкладке Text.
Также у нас здесь есть Preview
нашего приложения — как оно выглядит.
Также мы можем переместиться
на вкладку Design, чтобы увидеть,
как выглядит наш интерфейс.
На этот макет мы можем перемещать кнопки,
текст, картинки и другие компоненты
из вкладки Palette.
По умолчанию у нас открываются
два экрана устройства:
на одном мы видим сам макет дизайна,
а на втором экране —
макет с отображением привязок.
Он называется Blueprint.
Более детально все возможности настроек
с вкладки Design мы рассмотрим
на следующем занятии.
Второй вид окна редактора отображает
код Java в файле MainActivity.java.
Сбоку у нас располагается панель
Tool buttons, которая содержит кнопки,
позволяющие разворачивать и сворачивать
отдельные окна инструментов.
Сейчас мы находимся в окне Project.
Здесь также есть окно Android —
более сжатый вид,
и для того чтобы раскрыть проект,
чтобы рассмотреть все компоненты детально,
мы можем перейти на вкладку Project.
Пока свернем папки.
В нижней части программы находится
окно инструментов, предоставляющее
доступ к определенным задачам.
Например, управление проектами, поиск,
отображение информации о процессе
запуска приложения и так далее.
Данное окно можно свернуть и развернуть.
Более подробно работу с данным окном
мы рассмотрим на следующем занятии.
И, наконец, Status bar —
это самая нижняя панель программы.
Она отображает состояние проекта
и самой программы, а также различные
сообщения и предупреждения.
В любой момент вы можете выполнить
поиск по командам и элементам,
просто щелкнув на увеличительное стекло
в правом верхнем углу окна Android Studio.
Либо дважды нажать на клавишу Shift.
Чтобы не потеряться в проекте,
мы изучим иерархию файлов.
Сейчас мы находимся в виде Project.
Раскроем список и увидим полную структуру
папок проекта.
Папки проекта выглядят точно так же,
как на диске, где сохранен наш проект.
В данной структуре проекта
много файлов и папок.
Если раскрыть папку app,
мы увидим следующие папки:
папка build, libs и src.
В папке build хранятся файлы, создаваемые
системой в процессе компиляции.
Лучше там ничего не менять.
Папка libs — папка для сторонних
библиотек, подключаемых в проект.
И папка src — это папка для исходного кода
и ресурса.
Внутри src находится папка main.
Это основная рабочая папка,
с которой мы будем всегда работать.
Внутри папки main находятся две подпапки.
Это java и res — соответственно,
папка для кода и папка для ресурсов.
Раскроем папку res.
Данная папка содержит все ресурсы для
нашего приложения, включая изображения,
файлы макетов экранов, строковые ресурсы,
значки, иконки, цвета и стили оформления.
Она включает следующие вложенные папки.
Это drawable — здесь у нас сохраняются
все изображения для нашего приложения.
Вторая папка — drawable-v24 —
сохраняет изображения для версии
Android 24 и выше.
Следом идет папка layout —
она содержит файлы макетов
для activity экранов приложения.
В настоящее время наше приложение
имеет одну activity
с файла макета activity_main.
Открыть файл макета мы можем,
раскрыв папку и дважды нажав
на название файла.
Следом папка mipmap — она содержит
иконки запуска приложений.
Это те иконки, которые отображаются
на Android-устройстве
после установки приложения.
Всего 6 папок под таким названием,
но с разными разрешениями,
куда надо вставлять изображения
под каждое разрешение экрана,
чтобы иконка была высокого качества
на больших дисплеях и не была размытой
на маленьких экранах смартфонов.
И, наконец, папка values содержит ресурсы:
цвета, строки и стили,
используемые в приложении.
Также в окне структуры проекта есть
два файла с именем build.gradle.
Один файл build.gradle
и второй файл build.gradle.
Это файлы сборки для системы Gradle,
которую используют для компиляции,
построения и упаковки
приложений и библиотек.
Файл сборки уровня проекта содержит
настройки для всего проекта.
А файл сборки уровня модуля app
содержит настройки для модуля.
Чаще всего мы будем работать
именно с файлом сборки уровня модуля.
Он содержит такие основные секции,
как android, buildTypes и dependencies.
В android указаны версии
инструментов разработки,
минимальная поддерживаемая версия
(в данном случае у нас 21),
целевая поддерживаемая версия
(в нашем случае 27),
версия приложения для Google Play,
название версии,
инструмент для тестирования
и другие параметры.
Секция dependencies содержит список
библиотек, подключаемых к проекту.
Здесь могут быть подключены как локальные,
помещенные в папку libs,
так и хранящиеся удаленно библиотеки.
Теперь раскроем папку java.
Все файлы кода на языках Kotlin и Java
организованы здесь.
Папка java содержит одну папку
с доменом нашего проекта.
Папка java содержит файлы исходного кода
Kotlin и Java для нашего приложения.
С данной папкой мы будем работать
большую часть времени,
поскольку это главный пакет проекта.
И напоследок нам следует обратить внимание
на файл AndroidManifest в папке main.
Данный файл описывает все компоненты
приложения Android и считывается
системой среды выполнения Android
при запуске приложения.
В этой части лекции мы рассмотрели
интерфейс программы
и в следующей части начнем работу
с интерфейсом приложения.
Редактор макетаВ прошлой части лекции мы познакомились
с интерфейсом программы Android Studio.
Во второй части мы научимся работать
в редакторе макета.
Закроем лишние вкладки.
Откроем файл MainActivity.
Данный класс является activity.
Термин переводится как «активность»
или «деятельность»,
но никто его не называет активностью
или деятельностью.
Используется термин просто activity
без перевода.
MainActivity изначально был создан
средой разработки,
когда мы создавали новый проект.
Каждая activity в приложении для Android
имеет свой макет, который определяет
пользовательский интерфейс.
На 11 строчке присваивает макет
под именем activity_main.
Для того чтобы их различать, запомните:
в activity мы пишем логику приложения —
соответственно, пишем код Java
для работы с компонентами,
а в макете мы настраиваем
пользовательский интерфейс —
соответственно, пишем код XML
или перетаскиваем с панели Palette
кнопки, изображения и так далее.
В Android Studio есть редактор макетов,
в котором можно настраивать
и определять макеты.
Сами макеты описаны на языке разметки XML.
Редактор макета позволяет нам определять
и изменять макет путем написания кода XML
либо работать с компонентами через
интерактивный визуальный редактор.
В прошлой части лекции мы переключались
между вкладками кода и дизайна.
Это вкладка Design.
Это вкладка Text.
Теперь откроем макет
под именем activity_main.
Сейчас мы находимся здесь.
Попробуем его найти в папке ресурсов.
Раскроем папку res.
В папке layout находится наш макет
activity_main.
Два раза щелкнем,
но он у нас уже открыт.
Откроем вкладку Design, чтобы отобразить
визуальный редактор макета.
Макет дизайна слева показывает,
как наше приложение
появляется на устройстве.
Схема чертежа, показанная справа,
представляет собой
схематический вид макета.
Используйте значок компоновки
в левом верхнем углу
панели инструментов дизайна,
чтобы отобразить проектный вид
либо вид чертежа.
Или оба вида вместе.
В выпадающем списке нам также доступны
три варианта отображения.
И последняя функция в данном списке —
это обновление отображения,
если вдруг в макете не отображаются
обновленные данные.
Используйте значок ориентации
для смены ориентации макета.
Существуют два варианта
ориентации экрана —
это вертикальный и горизонтальный вид.
В данном случае мы находимся
в вертикальном виде.
Чтобы переключиться на горизонтальный,
кликнем на пункт Landscape.
Также в выпадающем списке можно настроить
ночной режим и режимы
для разных устройств.
Здесь, в данном случае, для телевизоров,
для часов, для виртуальных очков
и для машин.
Также с помощью данной вкладки
можно создать новый макет
для горизонтального отображения, планшета
или еще дополнительный вид по желанию.
Используйте меню выбора устройств,
чтобы видеть, как макет будет выглядеть
на разных Android-устройствах
с разными версиями Android, разрешением
и плотностью экранов.
Затем у нас следуют две вкладки:
настройка темы и настройка локализации.
Последняя означает добавление
строковых ресурсов
для мультиязычного приложения.
И, наконец, в правом верхнем углу
редактора макетов вы видите
кнопки «плюс» и «минус»
для увеличения и уменьшения масштаба.
Используйте эти кнопки для настройки вида
или нажмите кнопку Zoom to Fit Screen
справа от кнопок масштабирования,
чтобы обе панели соответствовали
нашему экрану.
Теперь настало время построения макетов.
К сожалению, Android Studio по умолчанию
во всех проектах добавляет
родительский макет ConstraintLayout.
Для новичков, которые впервые сталкиваются
с макетами и самим кодом XML,
понять данный макет будет сложно,
поэтому мы заменим ConstraintLayout
на LinearLayout, то есть линейный макет.
Более подробно поведение всех
родительских макетов мы будем
рассматривать чуть позднее.
Чтобы заменить ConstraintLayout
на LinearLayout, выделим и удалим
строку с пакетом ConstraintLayout.
И впишем название нового макета:
LinearLayout.
Обратите внимание, что студия начинает
подсвечивать код, если видит,
что есть ошибки в нашем файле.
В данном случае нам потребуется удалить
лишний код, который принадлежит
ConstraintLayout.
Студия подсветила нам блеклым цветом
строчку на третьей строке.
Ее мы удалим.
Далее, у LinearLayout есть обязательный
атрибут для ориентации
родительского макета.
В данном случае атрибут
называется orientation.
Мы выберем значение «вертикально».
Как вы заметили, кода стало
намного меньше, поэтому начинать работу
по построению интерфейса необходимо
с легких родительских макетов.
Что же представляет собой
компонент View?
Он может содержать картинку, часть текста,
кнопку или элемент, который может
отобразить макет экрана.
Несколько элементов View создают
индивидуальный интерфейс приложения.
Все, с чем вы взаимодействуете
в приложении, называется
пользовательским интерфейсом,
или user interface на английском,
или еще короче — UI.
Мы рассмотрим 3 наиболее часто
используемых элемента View:
это TextView, Button и ImageView.
TextView существует для
отображения текста.
Перейдем на вкладку Design, чтобы увидеть
элемент ImageView.
Также мы поменяем ориентацию устройства.
ImageView у нас для отображения картинок
и Button — для работы с кнопками.
Так как элемент TextView у нас уже
определен в макете, мы добавим ImageView.
Сначала мы добавим элементы — картинки и
кнопки — с помощью визуального редактора.
Затем мы добавим те же самые элементы,
но уже с помощью программного кода.
С панели Palette перенесите на экран
элемент ImageView.
Откроется новое окно Resources,
где нам предлагается выбрать картинку
для нового элемента.
Раскроем список Project и выберем
первую картинку в списке.
Нажмем Ok.
Новый элемент появился у нас на макете.
Теперь перетащим кнопку Button.
Чуть ниже ImageView.
Видим, что кнопка растянулась по ширине
на весь экран.
В правом нижнем углу в окне редактора
макетов у нас есть панель Component Tree.
Данная панель отображает иерархию
элементов в нашем проекте.
Напротив элементов ImageView и Button
появилось предупреждение
о возможных ошибках.
При наведении на элемент появляется
подробное описание возникшей ошибки.
В нашем случае
"Missing 'contentDescription' attribute
on image" означает
отсутствие описания картинки.
Зачем нам нужно прописывать
описание картинки?
В большинстве случаев это не является
обязательным атрибутом, но все же
чаще рекомендуется прописывать описание.
Например, если картинка не подгрузится
вовремя, то описание останется на месте,
где должна быть картинка.
Такая практика пришла из web-индустрии.
При долгой загрузке картинки
сайт в поле, где должна быть картинка,
как правило, выводит текст с описанием,
что должно быть в этом поле.
Второе предупреждение — напротив кнопки
Button — это "Hardcoded string "Button",
should use @string resource".
Оно означает, что имена кнопок и
описания текста не следует прописывать
в самом макете.
Для этого существует файл strings.xml,
где будут храниться все строковые ресурсы
нашего приложения.
В этой части лекции мы научились работать
с визуальным редактором.
В следующей части лекции мы начнем
работу с кодом XML и настройкой
элементов View.
Работа с TextViewВ данной части лекции мы настроим
наш элемент View и узнаем особенности
атрибутов и их значения.
В окне визуального редактора откроем
боковую панель Attributes.
Она сейчас пустая, и при выделении
TextView "Hello World!"
появятся его атрибуты.
С помощью данной панели мы можем
изменять свойства
наших элементов напрямую.
Например, можно изменить стиль текста
у TextView, сделав его больше.
Для этого напротив пункта textAppearance
выберем свойство textAppearance
AppCompat.Display1.
Как мы видим, текст нашего элемента
изменился и стал больше.
Откройте вкладку Text.
Давайте рассмотрим подробнее
синтаксис языка XML.
Что означает синтаксис?
Он означает правила, позволяющие писать
корректный код без ошибок.
Если вы напишете неправильный код,
то, соответственно, ничего
на экране смартфона не отобразится
или приложение «упадет» с ошибкой.
Синтаксис языка разметки XML простой.
Например, элемент TextView
начинается с открытия угловой скобки
и заканчивается тоже угловой скобкой
со слэшем, как и все элементы View.
Для всех элементов в макете есть
два обязательных атрибута:
это ширина и высота.
Объявлять их необходимо всегда.
Даже если вы забудете, редактор кода
вам напомнит подсказками
и автодополнением добавит их
при первом упоминании.
Ширину и высоту элемента можно задать
относительно их фактического объема,
можно растянуть на весь экран
или задать точные границы.
Сменим высоту у элемента TextView
с wrap_content на match_parent.
Теперь перейдем на вкладку Design.
Или мы можем сделать проще —
мы раскроем боковой элемент Preview.
Мы видим, что TextView занимает весь экран
благодаря значению match_parent.
Теперь зададим ему точные границы —
например, 240 dp.
Их еще называют dips.
Как мы видим, TextView теперь занимает
где-то больше половины экрана.
Что означает единица измерения dp?
Это не зависящие от плотности пиксели,
записанные как dp —
density-independent pixels.
Они являются гибкими единицами,
которые масштабируются,
чтобы иметь одинаковый размер
на любом экране устройства.
То есть вне зависимости от плотности
пиксели относятся к равномерному
отображению элементов интерфейса
на экранах с различной плотностью.
Более подробно о единице измерения dp
вы можете прочитать, перейдя по ссылке
в описании видео.
В данном случае данная вкладка сайта
подробнее рассказывает
о независимых пикселях.
Для изменения размеров текста тоже есть
своя единица измерения.
Это sp (scale-independent pixels) —
независимые от масштабирования пиксели,
которые наиболее корректно
отображают шрифты.
Заменим стандартный системный шрифт
на 15 sp и посмотрим, что изменилось
в интерфейсе.
Удалим данную строчку полностью.
И введем новый атрибут: textSize.
Со значением, например, 15 sp.
Как мы видим, текст изменился —
он стал намного меньше.
Его можно увеличить и задать
новое значение — например, 50 sp.
Текст увеличился, и так можно менять
размер текста в зависимости от дизайна.
Более подробно о шрифтах вы можете
почитать в гайдлайне по Material Design.
Ссылки будут в описании к видео.
Следует отметить, что можно применять
и другие единицы измерения, такие как
пиксели, миллиметры, дюймы, пункты,
но их не следует применять для настройки
размеров элементов, потому как они будут
отображаться некорректно на разных
экранах Android-устройств.
Используйте единицу измерения dp
для изменения размеров элементов
и sp для редактирования размера шрифта.
Теперь мы изменим текст "Hello World!"
на "Hello Android!".
Для этого в атрибуте text мы удалим
слово "World".
И впишем слово "Android".
Редактор кода нам подсвечивает, что
строка захардкодена.
Это означает, что такое объявление
нежелательно в самом интерфейсе TextView.
Для того чтобы решить проблему,
нажмите комбинацию клавиш Alt + Enter.
Здесь у нас два пункта:
либо добавить строковый ресурс,
либо игнорировать данное предупреждение.
Мы добавим строковый ресурс,
кликнув на пункт Extract String Resource.
Откроется новое окно, где автоматически
генерируется имя ресурса и его значение.
Кликнем на кнопку Ok.
В результате предупреждение исчезло
и появилась ссылка на строку.
Теперь мы изменить текст не сможем
напрямую через TextView.
Мы сможем это сделать только в файле
strings.xml, который находится
в папке values.
Откроем данный файл.
Раскроем список в папке values.
Откроем файл strings.xml двойным нажатием.
И, как мы видим, наша строчка
переместилась сюда.
В этом же файле хранится название
нашего приложения.
Теперь можно отредактировать название.
Удалим слово "Exemple 1" и впишем
"Hello World", например.
Перейдем в визуальный редактор.
И убедимся, что изменения вступили в силу.
У нас изменилось название
и название TextView.
Таким же способом мы создадим
строковый ресурс для кнопки Button.
Теперь мы изменим положение текста
"Hello World!".
Для начала, для того чтобы увидеть
все изменения, мы можем немного
уменьшить шрифт.
Сейчас, как мы видим, он прижат
к левому верхнему углу нашего приложения.
С помощью атрибута gravity
и layout_gravity со значением центра
мы выровняем текст по центру.
Выделим TextView,
перейдем на вкладку Design.
Далее раскроем все атрибуты.
Для начала нам надо найти атрибут gravity.
Поставим галочку на пункт center.
Как мы видим, надпись уже
сместилась в середину.
И нам требуется найти следующий атрибут —
layout_gravity.
Он находится здесь.
И здесь мы тоже ставим галочку
на пункте center.
Как мы видим, наш TextView выровнялся
по центру относительно границ
нашего приложения.
Данные атрибуты можно применять
ко всем элементам View.
Теперь можно перейти к настраиванию
цвета текста — для этого существует
атрибут textColor.
Так, свернем layout_gravity и gravity.
И найдем атрибут textColor.
Вот он.
Бывают также системные цвета и цвета,
которые можно найти в официальной
документации по Material Design.
Сама концепция Material Design появилась
в 2014 году и была призвана объединить
стили всех сервисов Google,
чтобы на каждом устройстве их сервисы
выглядели одинаково.
В частности, это касалось
и Android-платформы.
Теперь вернемся к настраиванию
цвета текста.
Перейдем на вкладку Text.
В данном случае мы уже добавим ее
через код XML.
Наберем на клавиатуре атрибут textColor.
И можем применить к нему системный цвет —
например, colorPrimary.
Наш текст окрасился в синий
в соответствии с тулбаром.
Теперь можно открыть страницу сайта,
где рассказано все о цвете в Android.
Здесь мы можем выбрать подходящий цвет.
Здесь также рассказано о том, как
сочетать цвета в вашем приложении,
какой делать главным,
а какой — второстепенным.
Нам требуется найти палетку
со всеми цветами.
Она находится в самом низу.
Итак, выберем самый темный красный цвет
под названием A700.
Скопируем его название.
Перейдем в наш проект.
И теперь мы можем удалить системный цвет
и вставить цвет, который мы скопировали.
TextView у нас окрасился в ярко-красный.
Еще можно настроить цвет
внутри фона TextView.
Для этого есть атрибут background.
Добавим его.
И также выберем для него цвет.
Снова откроем вкладку сайта.
И, например, мы можем выбрать
блеклый фиолетовый цвет.
Копируем сам цвет.
И вставляем в двойные кавычки.
В итоге у нас окрасился фон
нашего TextView,
и изменения у нас успешно вступили в силу.
Всех свойств для кнопок, картинок
и других элементов не перечислить.
Не обязательно знать их все наизусть.
Не обязательно знать также все атрибуты
и их значения — для этого есть
документация Android.
Откроем поисковик.
В данном случае у меня стоит Google.
И введем текст "documentation android".
Переходим на эту вкладку.
И первая ссылка нас приведет
к самой документации подробной.
Следом теперь мы можем ввести
документацию элемента,
с которым мы работали.
В данном случае это TextView.
И первая ссылка открывает все атрибуты
и их значения в TextView.
В данном случае вот они все.
Здесь у нас полное описание TextView
и список всех его атрибутов,
которые можно ему присвоить.
Допустим, если вы хотите выделить
текст жирным шрифтом,
воспользуемся поиском по документу.
В строку поиска введем слово bold.
Bold означает жирный шрифт с английского.
И это значение атрибута textStyle.
У данного атрибута есть три значения:
это нормальный, жирный и курсив.
Все это вносится по редактированию текста.
Также можно совместить два атрибута.
Перейдем в Android Studio и попробуем
применить textStyle к нашему проекту.
В данном случае мы попробуем сделать
жирный шрифт для нашего TextView.
И, как видим, изменения успешно
вступили в силу.
Пользоваться документацией легко,
если вы владеете английским языком.
Также следует обратить внимание,
что все атрибуты Android
(в данном случае layout
с шириной, layout с высотой,
с центрированием)
находятся с левой стороны
и определяют значение с правой стороны.
Значения атрибутов всегда должны быть
в двойных кавычках.
В качестве самостоятельного задания
настройте ImageView и кнопку Button:
поменяйте им размеры, цвет, шрифт
и попробуйте применить новые атрибуты
из документации Android.
В следующей части лекции мы поговорим
о родительских макетах и способах
их применения для построения
пользовательского интерфейса.
Родительские макетыМы уже работали с элементом LinearLayout.
Он позволяет группировать
дочерние элементы в одну линию
в автоматическом режиме
по вертикали или по горизонтали
с помощью атрибута orientation.
Откроем страницу документации
LinearLayout.
У разметки LinearLayout есть
интересный атрибут Layout Weight,
назначающий индивидуальный вес
для дочернего элемента.
Данный атрибут определяет важность
элемента и позволяет этому элементу
расширяться или сужаться в зависимости
от выбранного значения, чтобы заполнить
или уменьшить пространство
в родительском представлении.
Посмотрим на примерах в документации код,
который отображает работу атрибута
layout_weight.
Также тут у нас появляется новый
элемент View — EditText.
Вот он.
Данный элемент позволяет вводить текст.
Если TextView у нас только отображает
статичный текст, то EditText позволяет
работать с текстом.
Атрибут hint означает подсказку
для ввода текста.
При набирании текста подсказка исчезает.
Третий элемент EditText с атрибутом
layout_weight со значением "1" заполняет
все свободное пространство в интерфейсе.
В данном случае это у нас EditText
со значением: message.
Как мы видим, он заполнил
все пространство до кнопки Send.
В LinearLayout также есть дополнительные
атрибуты для управления представлением,
доступные по ссылке в конце документации.
Можем ее открыть и посмотреть.
Познакомиться со всеми атрибутами,
со всеми значениями, которые можно
применить к данному родительскому макету.
Существуют также и другие типы
родительских макетов, кроме LinearLayout,
позволяющие располагать элементы
разными способами.
Теперь мы можем познакомиться
с ними поближе.
Для начала стоит отметить,
что родительские макеты позволяют
управлять элементами View,
такими как кнопки, текст, изображения,
задавая им свойства и расположение
относительно друг друга или относительно
самого родительского макета,
который также еще называют компоновкой
и контейнером.
На протяжении курса мы будем использовать
наиболее популярные родительские макеты,
чтобы закрепить их работу и поведение
на практике.
Кроме того, разметку можно создавать
и программным способом, который мы
рассмотрим на следующем занятии.
Если вы будете обращаться к элементам
управления через Java-код, то необходимо
присваивать элементам уникальный
идентификатор.
Посмотрим в Relative Layout.
Здесь должен быть код.
Идентификатор id.
С помощью него вы можете обращаться
к элементу через код при помощи метода
find view by id.
Либо к нему обращаются в самой разметке
xml-файла.
Новая разметка, с которой мы еще
не работали, но уже открыли,
называется RelativeLayout.
RelativeLayout позволяет дочерним
компонентам определять свою позицию
относительно родительского компонента
или относительно соседних дочерних
элементов.
Чтобы задать позицию в данном
родительском макете, обязательно
присваивать идентификатор
каждому элементу, чтобы к нему
можно было обратиться.
Рассмотрим работу RelativeLayout
в примере документации.
Здесь встречается новый элемент View —
Spinner.
Он представляет собой выпадающий
список с данными.
В данной разметке все элементы
выравниваются относительно родителя
RelativeLayout.
Первый выпадающий список выравнивается
с левой стороны с помощью атрибута
layout_alignParentLeft,
значение: "true".
И layout_toLeftOf.
С идентификатором второго спинера.
А второй выпадающий список Spinner —
с помощью атрибута
layout_alignParentRight.
Он выравнивается по правой стороне.
В данном случае здесь у нас
отображение времени,
а с левой стороны — отображение даты.
Также атрибут layout_below означает,
что он находится под EditText'ом.
Потому что здесь значение —
идентификатор первого элемента.
И, наконец, кнопка Button
размещается под списком
с идентификатором times
с правой стороны относительно
родительского макета, с атрибутом
layout_alignParentRight.
У RelativeLayout, как и у LinearLayout,
есть также и дополнительные атрибуты
для управления представлением,
доступные по ссылке
так же в конце документации.
Можно перейти.
Здесь так же, как и в LinerLayout,
существуют дополнительные атрибуты
для более тонкой настройки
и дополнительные методы для работы
в коде Java.
Также давайте обратим внимание,
перейдем на прошлую страницу,
что здесь заметка, где говорится
о построении макета с помощью
ConstraintLayout.
Перейдем по ссылке.
И откроется документация по работе
с данным видом родительского макета.
ConstraintLayout появился
в Android Studio версии 2.2.
Напомню, что сейчас у нас
версия стоит 3.1.3.
Он появился на замену разметке макета
RelativeLayout.
Google советует всем переходить на него
и создал специальный конвертер
для этой задачи, который подключается
автоматически в библиотеке Gradle.
Сейчас мы покажем, где он находится.
В данном случае вот он.
Автоматически подгружает эту библиотеку.
Следующий вид разметки — это Grid.
GridView.
Это табличная сетка.
В ней для любого элемента можно указать
строку и колонку, и в этом месте таблицы
он будет размещен.
Указывать элементы для каждой ячейки
не понадобится — это нужно делать только
для тех ячеек, где действительно
должны быть элементы.
Элементы таблицы могут растягиваться
на несколько ячеек таблицы,
и в одну ячейку можно поместить
несколько элементов.
Существует еще один вид разметки,
но сейчас он не используется.
Исходя из названия понятно,
что данный макет работает
со списковыми представлениями.
Теперь к нему на замену пришел
RecyclerView.
Перейти к нему можно
с помощью этой ссылки.
Он позволяет динамически создавать списки,
намного упрощая работу с ними
и позволяя предупруждеть утечки памяти.
И последний макет в этой части —
это экспериментальный вид разметки
FlexboxLayout
от самих разработчиков Google.
Его преимущество заключается в том, что
он потребляет гораздо меньше памяти,
переиспользуя элементы повторно.
Чтобы его подключить, необходимо
скопировать данную строчку
и включить файл build.gradle.
В следующей части лекции
мы поговорим о классе MainActivity
и научимся создавать внутренние
и внешние отступы.
Класс Activity, внутренние и внешние отступыВ прошлых темах мы рассмотрели
создание простейшего приложения,
также изменили содержимое файла
activity_main.xml
и вывели на экран строку.
Однако мы еще не говорили,
как файл activity_main
связан с графическим интерфейсом.
Поэтому рассмотрим класс activity
и файл ресурсов, который определяет
визуальный интерфейс.
Класс activity является классом, который
по сути представляет отдельный экран
приложения или его визуальный интерфейс.
Отдельные activity, которые уже
непосредственно используются в приложении,
являются наследниками этого класса.
Приложение может иметь одну activity,
а может и несколько.
Каждая отдельная activity задает
отдельное окно для отображения.
Рассмотрим код, который использовался
в прошлой теме.
Код генерируется автоматически
в Android Studio.
Файл кода можно найти в проекте
в папке src, подпапке main
и подпапке java.
Находится здесь MainActivity.
Класс MainActivity представляет собой
обычный класс Java, в начале которого
идут определения пакетов
и импорта внешних пакетов.
По умолчанию он содержит только один
метод onCreate, в котором фактически
и создается весь интерфейс приложения.
В методе onCreate идет обращение
к методу родительского класса
и установка ресурса разметки дизайна.
В данном случае на 11 строчке находится
установка ресурса разметки дизайна.
Впоследствии мы подробнее рассмотрим
все эти выражения, пока достаточно
понимать, для чего они нужны.
В итоге получается примерно следующий
визуальный интерфейс.
Который мы уже неоднократно видели.
Чтобы установить ресурс разметки дизайна,
вызывается метод setContentView, в который
передается идентификатор ресурса.
Обратите внимание на то, как выглядит
идентификатор ресурса под названием
R.layout.activity_main.
Фактически это и есть ссылка на файл
activity_main.xml, который находится
в каталоге res/layout.
Весь интерфейс представлен элементом —
контейнером ConstraintLayout.
В нашем случае он представлен
контейнером LinearLayout.
И он содержит у нас 3 элемента:
TextView, ImageView и Button.
Таким образом, при запуске приложения
сначала запускается класс MainActivity,
который в качестве графического интерфейса
устанавливает разметку
из файла activity_main.
Однако в классе MainActivity мы используем
не файлы, а идентификаторы ресурсов —
R.layout.activity_main.
Все идентификаторы ресурсов определены
в классе R.java, который автоматически
создается утилитой при создании проекта
и находится в файле в каталоге build.
Сейчас мы можем его найти.
В каталоге build.
Далее папка generated.
Переходим в папку source.
Открываем папочку r.
И с названием нашего пакета.
Файл R.java находится здесь.
Здесь определены все
идентификаторы ресурсов.
Класс R содержит идентификаторы для всех
ресурсов, расположенных в каталоге res.
Для каждого типа ресурсов
в классе R создается внутренний класс.
Например, для графических ресурсов
из каталога res/drawable
создается класс R.drawable.
И для каждого ресурса данного типа
присваивается идентификатор.
По этому идентификатору впоследствии
можно извлечь ресурс в файле кода.
Редактировать данный файл
ни в коем случае не нужно.
Иначе это приведет к ошибкам в проекте.
Снова закрываем эту папку.
Переходим к файлу ActivityMain.
Настало время рассмотреть внутренние
и внешние отступы.
Параметры разметки позволяют
задавать отступы
как от внешней границы элемента
до границ контейнера,
так и внутри самого элемента
между его границами и содержимым.
Для установки внутренних отступов
применяется атрибут android:padding.
Он устанавливает отступы контента
от всех четырех сторон контейнера.
Можно установить отступы только
от одной стороны контейнера,
применяя следующие атрибуты:
paddingLeft, paddingRight, paddingTop
и paddingBottom.
Рассмотрим на нашем примере с TextView.
Допустим, мы поднимем текст снизу.
В значениях укажем 20 dp.
Мы видим: наш текст поднялся чуть выше.
С нижней границы.
Мы можем задать чуть больше.
Можно 50 dp.
С центра он поднялся наверх на 50 dp.
Для того чтобы увидеть, как "Hello World!"
переходит от одной границы до другой
с левой и с правой стороны,
мы должны расширить TextView.
Можно это сделать так, а можно
задать точные границы.
Мы расширили, теперь мы можем
передвинуть "Hello World!".
Например, к правой части TextView.
Для этого мы создадим атрибут padding.
Со значением Right.
И добавим значение 10 dp.
Как мы видим, текст сдвинулся.
Но нам будет нужно значение побольше.
50 dp.
В данном случае он у нас сдвигается влево.
Тогда попробуем атрибут Left.
Чтобы он у нас сдвинулся к правому краю.
Как мы видим, он сдвинулся.
Следующим атрибутом для установки
внешних отступов является
атрибут layout_margin.
Данный атрибут имеет модификации,
которые позволяют задать отступ
только от одной стороны
либо от всех сторон.
Применим новый атрибут
снова к элементу TextView.
Сначала мы добавим отступы со всех сторон.
Начнем с небольших значений: 20 dp.
И, как мы видим,
изменения вступили в силу,
и со всех сторон TextView
добавились отступы в 20 dp.
Также мы можем их увеличить или уменьшить.
Мы, например, увеличим на 50 dp
и посмотрим, что получилось.
Теперь он занимает, наш TextView,
большую часть экрана
и сдвинул элементы ImageView и Button
в низ макета.
На этом первая лекция подходит к концу,
и в следующей лекции мы начнем
уже разрабатывать приложение.
Основные элементы управленияСейчас мы находимся буквально в одном шаге
от разработки приложения.
И сейчас мы познакомимся с основным
элементом управления, называемым View.
View-класс представляет собой основной
строительный блок для компонентов
пользовательского интерфейса.
Вид занимает прямоугольную область
на экране и отвечает за рисование
и обработку событий.
Также View — это базовый класс
для элементов, которые используются
для создания компонентов
интерактивного интерфейса, таких как
кнопки, которые мы уже рассмотрели,
TextView, ImageView и так далее.
Также мы сегодня рассмотрим определение
в коде активностей элементов View.
Первый элемент — это надпись (TextView).
Для простого вывода текста на экран
предназначен элемент TextView.
Он просто отображает текст
без возможности его редактирования.
Ему также можно назначить атрибуты
для выравнивания текста внутри блока,
назначить шрифт, направление текста,
цвет текста и много другое.
Следующий элемент — текстовое поле
(EditText) — является подклассом
класса TextView.
Он также представляет текстовое поле,
но теперь уже с возможностью ввода
и редактирования текста.
Таким образом, в EditText мы можем
использовать все те же возможности,
что и в TextView.
Из тех атрибутов, что не рассматривались
в теме про TextView, следует отметить
атрибут android:hint.
Он позволяет задать текст, который
будет отображаться в качестве подсказки,
если элемент EditText пуст.
Кроме того, мы можем использовать
атрибут InputType, который позволяет
задать клавиатуру для ввода.
В частности, среди его значений
можно выделить следующие:
textPassword — клавиатура
для ввода пароля,
phone — клавиатура для ввода номеров,
textAutoCorrect — автоматически
исправляет вводимый текст
и textCapSentences — при вводе первого
введенного символа слова представляет
заглавную букву, а остальные —
строчные, как в предложениях.
Также есть еще и другие значения —
например, выбор даты, ввод пароля и т.д.
Следующий элемент — это кнопка (Button),
с ней мы уже знакомы.
Он является одним из часто используемых
элементов, которые представлены классом
android.widget.Button.
Ключевой особенностью кнопок является
возможность взаимодействия
с пользователем через нажатие
с помощью метода onClick,
который задает обработчик нажатия кнопки.
Следом также для кнопок есть
и вывод изображений.
Чтобы вывести на кнопке текст,
справа от которого находится графическое
изображение, используйте атрибут
android:drawableRight и укажите
нужное изображение, путь к нему.
Или android:drawableLeft — для вывода
изображения слева.
Также можно вывести изображение
над и под текстом.
Следующий элемент — это двухпозиционная
кнопка (ToggleButton).
Компонент ToggleButton по своей
функциональности похож на флажок
CheckBox или переключатель RadioButton,
который мы рассмотрим в следующих слайдах.
ToggleButton — кнопка, которая может
находиться в одном из двух состояний:
активном со значением On
и неактивном со значением Off.
ToggleButton находится в разделе Widgets.
По умолчанию ToggleButton находится
в выключенном состоянии.
Основное событие для ToggleButton —
это изменение состояния кнопки
onToggleClicked.
Схожим элементом, как ToggleButton,
является переключатель (Switch).
Он появился в Android версии 4.0.
Находится в разделе Commands
и в разделе Buttons.
Фактически это замена
немного устаревшего ToggleButton.
В новых проектах лучше использовать
все-таки Switch.
Компонент используется в том случае,
когда нужно переключиться
на противоположное состояние:
да/нет, включить/выключить,
открыть и закрыть.
Момент переключения можно отслеживать
при помощи прослушки событий
onSwitchClicked.
Элемент CheckBox является флажком,
с помощью которого пользователь может
отметить (а точнее поставить галочку)
определенную опцию.
Компонент находится в группе Buttons.
Для управления состоянием флажка
используйте методы setChecked
или isChecked.
Чтобы узнать текущее состояние флажка,
следует вызвать метод isChecked.
Следующий элемент — переключатели,
или RadioButton на английском.
Главная особенность элемента
состоит в том, что он
не используется в одиночестве.
Всегда должно быть два и более
переключателей, и только один из них
может быть выбранным.
Находится RadioButton в разделе Widgets.
Компоненты RadioButton используются
в составе контейнера RadioGroup.
Обратите внимание на два момента.
Первое: в контейнеры RadioGroup
можно включать не только RadioButton,
но и другие элементы —
например, картинки и текст.
Второе: переключатели работают
в своем контейнере, то есть если у вас
два контейнера RadioGroup,
то переключатели из одного контейнера
никак не повлияют на поведение
переключателя из второго контейнера.
Чтобы определить, какой переключатель
будет установлен, используйте метод
getCheckedRadioButtonId.
Раскрывающийся список Spinner из раздела
Widgets похож на выпадающий список
ComboBox, используемый в операционной
системе Windows.
В закрытом состоянии компонент показывает
одну строчку, при раскрытии — выводит
список в виде диалогового окна
с переключателями.
Следующий элемент — это графическое
представление ImageView.
Компонент ImageView предназначен
для отображения изображений.
Он находится в разделе Images.
Для загрузки изображения в xml-файле
используется атрибут android:src.
Здесь также у нас тот самый атрибут
contentDescription, который позволяет
писать описание картинки.
ImageView является базовым
элементом-контейнером
для использования графики.
Можно загружать изображения
из разных источников — например,
из ресурсов программы или из сети.
Следующий элемент — это графическая
кнопка ImageButton.
Он находится в разделе Widgets.
Компонент ImageButton представляет собой
кнопку с изображением вместо текста.
По умолчанию ImageButton похож
на обычную кнопку.
Следующий элемент — это прокручиваемые
представления (ScrollView).
Существует для того, чтобы добавить
вертикальную полосу прокрутки
или заключить существующий макет
в элемент ScrollView,
как и группы RadioButton.
И последний элемент на сегодня —
это уведомления, или тосты.
Для создания простых уведомлений в Android
используется класс Toast.
Фактически Toast представляет всплывающее
окно с некоторым текстом, которое
отображается в течение некоторого времени.
Объект Toast нельзя создать
в коде разметки xml — например, в файле
activity_main.xml.
Toast можно использовать
только в коде Java.
В качестве времени показа окна мы можем
использовать целое численное значение
количества миллисекунд
или встроенные константы,
такие как Toast.LENGTH_LONG
продолжительностью 3,5 секунды.
И Toast.LENGTH_SHORT
продолжительностью в 2 секунды.
На этом все.
В следующей части нашей лекции
мы уже будем разрабатывать
полноценное приложение.
Создание приложения "Тест"В этом уроке мы создадим
тестовое приложение
с вопросом и двумя кнопками:
«да» и «нет».
Мы научимся не только создавать
интерфейс, но и создадим
событие для кнопки, чтобы она выполняла
определенное действие при нажатии.
Еще мы научимся создавать всплывающие
сообщения с разным временем отображения.
В окне Android Studio кликнем на пункт
Start a new Android Studio project.
Заполним поля.
Напротив Application name впишем слово
Test App.
То есть так будет называться
наше приложение.
А в Company domain оставим по умолчанию,
так же, как и локацию.
Кликаем на кнопку Next.
В данном окне у нас стоит версия
разработки API 21: Android Lollipop 5.0.
Далее мы кликаем на Next.
Выбираем пустой шаблон Empty Activity.
И оставляем по умолчанию названия
наших файлов:
MainActivity для работы с кодом Java
и activity_main для работы
с визуальным интерфейсом.
Далее кликаем на кнопку Finish.
Начинается сборка проекта.
Наш проект собрался за 14 секунд.
Сразу откроем нужные нам файлы.
Нам нужен файл activity_main.
Также MainActivity.java.
И нам нужен строковый ресурс.
Откроем его в нашем проекте.
В папочке res
и в подпапочке values.
Все файлы, с которыми мы будем работать,
открыты.
Теперь нам нужно заполнить
activity_main данными.
Мы удалим разметку с ConstraintLayout.
и заменим его на LinearLayout.
С ним мы уже работали.
Как мы знаем, у него есть обязательный
атрибут ориентации.
Назначим ему вертикальную ориентацию.
Добавим атрибут gravity
для того, чтобы он выравнивал
дочерние элементы по центру.
И дадим ему значение: "center".
В TextView мы удалим лишний код.
И, соответственно, этот лишний код,
который остался от ConstraintLayout.
В TextView мы уберем стандартный текст.
Напишем: «Москва — столица России».
И точку.
Далее нам потребуется создать еще один
вложенный LinearLayout.
Создаем мы его с помощью разметки XML,
а не через визуальный интерфейс.
В нем заменим высоту, чтобы он
не занимал всю высоту экрана.
Зададим ему атрибут orientation
с горизонтальной ориентацией.
Далее в нем мы создадим две кнопки Button
со значениями «да» и «нет».
Первой будет у нас кнопка «да».
И вторая у нас будет со значением «нет».
Добавим строковые ресурсы в strings
с помощью комбинации клавиш
Alt + Enter.
Мы уже это делали.
Дадим ему название, например, moscow.
Нажимаем Ok.
Здесь ему присвоим название...
Например, button_yes.
Чтобы нам не спутать две кнопки.
И этому — название button_no.
Нажмем на кнопку Ok.
Мы создали строковые ресурсы.
Проверить их можем в файле strings.
Как мы видим, строковые ресурсы
успешно создались.
Теперь мы перейдем на вкладку Design,
чтобы проверить, все ли у нас
корректно отображается.
Здесь у нас высветилась проблема
с отображением графического интерфейса.
В данном случае это, скорее всего,
возникло из-за того, что у нас сейчас
стоит 28 версия в качестве конечной.
Целевой версии.
Так как она все еще нестабильна,
попробуем поменять на версию ниже.
На версию 27.
В файле build.gradle.
Если у вас разметка в дизайне отображается
корректно, то ничего менять не нужно.
Мы поменяем на версию 27.1.
Либо 0.
Так, обновим файл gradle, синхронизируем.
Синхронизация прошла успешно.
Сейчас мы также поменяем 28 на 27 версию.
Теперь — да, разметка у нас появилась.
Ошибка у нас устранена.
Закроем это окно с предупреждениями.
Все, что мы набрали в коде XML, теперь
отображается в визуальном интерфейсе.
Здесь можно увеличить текст и задать
отступы кнопкам, чтобы они не были
так близко друг к другу.
Вы можете сделать это самостоятельно.
Либо можете сделать так же, как и у меня.
Для текста мы сделаем шрифт побольше.
Например, 30 sp.
Здесь также можно сразу посмотреть
все внесенные изменения.
И также мы можем сделать ему отступ снизу.
20 dp.
Отлично.
И теперь для кнопок.
Например, для левой кнопки
со значением «да» мы можем
сделать отступ справа.
Со значением 20 dp.
Отлично.
Теперь разметка пришла
к читабельному виду.
Следующий шаг —добавление
идентификаторов для кнопок.
Для того чтобы мы к ним обращались
через код MainActivity и задавали им
какую-нибудь функциональность.
В нашем случае это будет нажатие на кнопку
и вывод результата.
Добавим индикатор для первой кнопки.
Начнем вводить и название зададим
то же самое, как и название
строкового ресурса — button_yes.
То же самое проделаем и для кнопки
со значением no.
Добавим и для нее идентификатор.
Со ссылкой button_no.
Обратите внимание на знак «плюс», который
присутствует в значении android:id,
но не в значениях android, например, text.
Это связано с тем, что мы создаем
идентификаторы, а на строки только
ссылаемся.
Идентификаторы существуют для того,
чтобы обращаться к элементам через
MainActivity или через разметку.
На этом мы заканчиваем первую часть
нашего приложения.
И в следующей части мы закончим его.
Также мы добавим события
для элементов Button.
Мы продолжим создание простого
тестового приложения.
После создания интерфейса требуется
наделить функциональностью
наше приложение.
Но для начала мы видим, что редактор кода
подсвечивает нам замечание о том, что
атрибут layout_marginRight можно
заменить на атрибут layout_marginEnd.
В прошлой части лекции мы назначили
кнопкам идентификаторы ресурсов.
К ним теперь можно обращаться
из MainActivity.
Перейдем на вкладку MainActivity.
Все начинается с добавления
двух переменных для наших кнопок.
Добавим две строчки для каждой из кнопок.
Здесь у нас автоматически подгрузился
пакет Button.
Но если мы удалим его, кнопка Button
у нас подсветится красным цветом.
Для того чтобы решить эту проблему,
нажмем на комбинацию клавиш: Alt + Enter.
И импортируем класс.
Пакет у нас успешно импортировался.
Следующий этап — это получение ссылок
на элементы Button.
Для получения элементов по id
класс Activity имеет метод
findViewById.
В этот метод передается
идентификатор ресурса в виде
R.id.[идентификатор элемента].
Данный метод возвращает объект View —
объект базового класса для всех
элементов, поэтому результат метода
еще необходимо привести к типу Button.
Создадим ссылки на наши кнопки.
И для второй кнопки создадим.
Как мы видим, слово Button у нас
подсвечивается серо-блеклым цветом,
что означает, что данная конструкция
устарела.
Нажимаем на Alt + Enter, и у нас выходят
два пункта меню: в первом у нас очищается
только в этом месте кнопка Button,
а Cleanup code ищет во всем
файле MainActivity элементы,
которые не используются.
Которые можно удалить.
Нажмем на Cleanup code.
И слово Button исчезло у нас
со всех строчек.
Раньше писалось так, но в последних
обновлениях данную функцию убрали.
Когда приложение ожидает наступления
конкретного события, мы говорим,
что оно прослушивает данное событие.
Объект, создаваемый для ответа на событие,
называется слушателем (Listener).
Такой объект реализует интерфейс
слушателя данного события,
который мы сейчас добавим.
Создадим обработчик нажатия кнопки
с помощью метода OnClickListener.
Функция автодополнения помогает нам
набрать текст в разы быстрее.
Достаточно начать вводить текст и
в выпадающем списке выбрать нужный метод.
Начнем с кнопки YesButton.
Мы нашли в выпадающем списке
setOnClickListener.
Далее в скобках создадим
новый объект View.
И у нас автоматически создается
конструкция для работы с методом OnClick.
Внутри данного метода мы назначим
слушателя для кнопки YesButton.
Для копки NoButton мы создадим такой же
метод OnClickListener.
В нашем приложении каждая кнопка
будет выводить на экран
временное уведомление (Toast).
Как мы помним из прошлой лекции,
это короткое сообщение, которое содержит
какую-либо информацию для пользователя.
Но также оно не требует ни ввода,
ни действий.
Наши уведомления будут сообщать
пользователю, правильно ли он
ответил на вопрос.
Напомню, что Toast можно использовать
только в коде Java.
В качестве времени показа мы можем
использовать целое численное значение
количества миллисекунд с помощью
встроенных констант длительностью
3,5 и 2 секунды соответственно.
Чтобы нам создать тосты,
для начала нужно для них создать
текст сообщения.
Перейдем в файл strings.xml.
И создадим строковый ресурс уже
программно для тостов.
Для каждой кнопки.
Для кнопочки Yes мы создадим название
со значением correct.
Correct answer.
И впишем слово «Правильно».
Либо можно «Правильный ответ».
Для того чтобы скопировать эту же строчку,
нажмем на Ctrl + D.
У нас скопировалась строчка.
И здесь мы добавим небольшие изменения,
чтобы не перепечатывать полностью.
Для кнопки NoButton.
Перейдем теперь во вкладку MainActivity.
И в конструкции mYesButton,
где мы назначили слушателя события,
пока пусто.
Мы создадим уведомление (Toast).
Уведомление создается вызовом следующего
метода класса Toast.
Наберем его.
Выберем в списке рекомендаций makeText.
Далее объявляем Activity, в которой
нам нужно запустить текст сообщения.
В нашем случае это MainActivity.
Со ссылкой this.
Далее — ссылку на текст сообщения,
который мы создали.
Вот этот текст.
И название correct_answer.
Следом нам потребуется указать
длительность показа сообщения.
Зададим ему длительное сообщение.
И последний пункт — это...
Команда для показа самого сообщения.
Метод show.
Теперь то же самое мы создаем
для кнопки NoButton.
Здесь у нас будет incorrect_answer.
Для разнообразия мы можем в тосте указать
отображение поменьше.
И заключительный метод show.
На этом создание нашего приложения
подошло к концу.
Проверьте, подсвечивает ли студия
какие-нибудь ошибки.
Ну, а здесь у нас подсвечивает
о том, что данную переменную можно
перевести в локальную.
Мы можем сконвертировать ее.
И то же самое проделать
для кнопки NoButton.
Отлично.
Теперь снова проверяем правильность
всех введенных данных,
чтобы нигде не было ошибок.
Полный листинг кода всех активностей
и разметки будет доступен
в материалах лекции.
Теперь запустим наш проект.
Для того чтобы посмотреть на результат.
Отлично, приложение у нас запустилось.
С текстом и двумя кнопками.
Нажмем на кнопку «Да».
Всплывающее уведомление Toast работает.
Кликнем на кнопку «Нет».
Здесь также работает.
На этом урок подходит к концу.
Поздравляю вас с первым работающим
приложением.
На следующем уроке мы будем работать
с выпадающим списком.
На этом все.
Создание приложения "Список сериалов"В прошлой части урока мы создали
первое работающее приложение.
Для того чтобы не закрывать полностью
студию, можно кликнуть на File —
Close Project.
И у нас запускается снова стартовое окно.
В этой части урока мы создадим еще одно
новое приложение, которое будет
немного сложнее предыдущего.
Мы научимся работать с обработкой событий
через кнопку и менять текст динамически
в соответствии с выбранным пунктом.
Создадим новый класс и научимся работать
с классом Java StringBuilder.
Откроем программу Android Studio.
Создадим новый проект.
Введем название: TV Series.
Наше приложение будет отображать
список сериалов по жанрам.
Кликнем на кнопку Next.
Далее Next.
Выберем пустой шаблон.
Next.
И оставляем значения по умолчанию.
И кликаем Finish.
Мы также снова откроем файл activity_main.
MainActivity.java и strings.xml
в окне редактора кода.
Наш проект все еще собирается.
На сборку проекта у нас ушло 12 секунд.
Как и обещали, открываем еще один файл.
Strings.xml.
Переходим в файл activity_main
и в нем создадим три элемента.
Список Spinner, который мы обсуждали
в первой части лекции.
Это выпадающий список.
Далее мы создадим кнопку Button
и текст TextView.
Следом мы также зададим
вертикальную ориентацию.
Добавим атрибут gravity
со значением center, который будет
выравнивать все дочерние элементы
по центру.
Для начала мы удалим ConstraintLayout
и добавим LinearLayout.
Добавим к нему обязательный атрибут —
ориентацию.
В данном случае будет у нас вертикальная.
Добавим атрибут gravity.
И удалим лишние строчки кода.
Первый элемент в нашем списке
будет Spinner.
Выпадающий список.
Ему зададим следующие ширину и высоту.
Здесь также можно не обозначать так,
потому что у нас будет не вложенный,
а закрыть сразу его угловой скобкой.
Далее добавим кнопку Button.
Зададим ей размер wrap_content.
И в TextView мы заменим текст
"Hello World!" на, например, «Сериал».
Посмотрим, как у нас выглядит,
во вкладке Design.
Здесь снова у нас та же самая ошибка.
Возможно, в новых версиях, когда 28 версия
станет чуточку стабильнее,
вам и нам не придется менять все
в файле build.gradle.
Если у вас возникают какие-то ошибки,
напоминаю, что существует поисковик —
Google, Яндекс, Yahoo и так далее.
И также существует классный сайт
Stack Overflow, где, соответственно,
вы можете скопировать вашу ошибку,
и, возможно, там уже кто-то решил
эту проблему — почитать,
и по большей части вам это должно помочь.
У нас сейчас синхронизируется проект.
Далее по плану у нас идет добавление
идентификаторов для всех элементов
и, соответственно, задание отступов
для того, чтобы наши вкладки
не прилипали друг к другу.
Отлично, у нас появился.
Здесь нам нужно добавить отступы.
Добавить текст для кнопки.
И добавить им идентификаторы.
Этим мы и займемся.
Для Spinner мы создадим идентификатор.
Со значением genre_list.
Зададим ему отступ снизу.
В значении 50 dp.
Для кнопки Button мы создадим
идентификатор со значением choose_button.
То есть кнопка выбора.
Также мы дадим название для кнопки.
Впишем сюда: «Выбрать сериал».
Отлично.
И для TextView мы также зададим отступ.
В нашем случае сверху.
В размере, например, 20 dp.
И зададим ему шрифт побольше.
Значение, наверное, тоже 20 sp.
Посмотрим, как все у нас выглядит,
на вкладке Design.
В принципе, с таким интерфейсом
можно уже работать.
Если вы хотите что-то изменить,
или задать дополнительные отступы
для элементов, или увеличить шрифты,
то, конечно, все в ваших руках.
Далее мы снова перейдем на вкладку Text.
Добавим строковые ресурсы.
Дадим название для кнопки, например,
снова choose_button.
А для текста просто можно TV задать.
Теперь перейдем на вкладку Design,
чтобы посмотреть, корректно ли
все отображается.
И далее нам нужно заполнить данными
наш выпадающий список.
Сейчас он пустой и ничего не отображает.
Для того чтобы создать данные,
нам требуется создать массив данных
из строк.
Для этого в strings.xml есть атрибут
string-array.
Дадим ему название choose_genre.
И заполним его следующим содержимым.
Для того чтобы каждый пункт списка
у нас отображался отдельно,
для этого существует атрибут item.
Скопируем сразу несколько.
В нашем случае нам потребуются
5 таких атрибутов.
Здесь мы введем названия наших жанров.
Первый у нас комедия.
Второй жанр — фэнтези.
Все эти жанры относятся к сериалам.
Ужасы.
Следующий — фантастика.
И последний — криминал.
Теперь для того, чтобы этот массив строк
перешел и отображался
в раскрывающемся списке,
для него нужно создать ссылку.
Для этого существует атрибут entries.
И здесь мы создадим ссылку.
На наш массив.
Так, у нас высветился.
Переходим на вкладку Design.
Отлично.
Здесь у нас не выпадает список,
поэтому проверить, выпадает он или нет,
мы можем только после того, как запустим
наш проект.
Что мы и сделаем.
Запустим наш проект.
Хочу отметить, что закрывать
окно эмулятора не рекомендуется,
если вы не прекращаете работу,
а просто закрываете сам проект.
В лучшем случае следует оставлять
эмулятор открытым, чтобы он впоследствии
просто запускал ваш проект сразу,
напрямую.
Итак, мы создали разметку,
и в следующей части мы будем работать
с кодом главной активности.
В прошлой части мы создали интерфейс
нашего приложения.
В этой части мы продолжим создание
приложения и закончим его.
Если в прошлой части мы работали
только с разметкой, то здесь мы будем
работать с кодом активности.
Создадим новый класс и поработаем
с классом StringBuilder.
Но сначала мы снова возвратимся
к разметке activity_main.
И добавим атрибут кнопке Button
android:onClick для того, чтобы
мы смогли задать ей функциональность
уже из кода активности.
Дадим ей название OnClickChoose.
Новый атрибут у нас будет работать
в главной активности MainActivity.
Для обработки нажатий на кнопку Button.
Щелкните на кнопку, на само название.
И, как мы видим, у нас выводится
предупреждение о том, что данный метод
еще не найден.
Создать мы его можем благодаря
снова комбинации Alt + Enter.
Здесь у нас снова выводится список.
В первом пункте у нас отображается
значение, где можно удалить это замечание
либо удалить полностью эту строчку.
И второй пункт — это создание
этого метода в главной активности.
Мы выберем create onClick.
И, как мы видим, у нас все создалось
в главной активности автоматически.
Благодаря этой функции Alt + Enter
мы создали новый метод без набирания
кода вручную.
Теперь в классе MainActivity мы будем
дальше работать с методом onClickChoose.
Убедимся, что все у нас работает
без ошибок, никаких подсветок в коде нет.
Далее мы перейдем в activity_main.
Здесь тоже никаких ошибок нет.
При построении прошлого приложения
мы обращались к кнопкам с помощью
идентификатора в коде XML.
В этом же приложении мы обращаемся
к кнопке с помощью атрибута onClick,
где создали метод для работы с кнопкой
в классе активности.
Теперь нам нужно получить ссылки
для текстового элемента TextView
и списка Spinner.
Далее нам нужно сделать так, чтобы
выбранный вариант из списка Spinner
отображался в TextView.
Нам потребуется получить ссылку
на TextView.
Мы еще не создали для него идентификатор.
Сейчас мы создадим его.
И дадим ему название.
Series_text.
Теперь мы введем ссылку на ресурс текста.
Следом нам нужно получить ссылку
на Spinner, на наш выпадающий список.
Дадим название, которое предлагает нам
Android Studio.
Далее нам требуется получить доступ
к нашим ресурсам.
К идентификатору Spinner у нас...
genre_list.
И теперь нам нужно получить вариант,
выбранный в Spinner.
Для этого существует следующая строчка.
String getList.
String.valueOf.
И получение выбранного пункта.
Закрываем, точка с запятой.
И теперь нам требуется вывести
выбранный вариант, который мы выбрали
в раскрывающемся списке.
Мы будем выводить его в TextView.
И закроем.
Для того чтобы создать свой вывод
для каждого жанра сериала,
нам потребуется создать новый класс.
Создадим новый класс.
На название пакета щелкните
правой кнопкой мыши.
Откроется меню.
Далее кликните на пункт New.
И перейдите на создание
нового Java-класса.
Кликаем.
Дадим ему название SeriesList.
И нажимаем на кнопку Ok.
У нас создался новый класс, где нам
потребуется написать код, который бы
обеспечивал правильность выбора каждого
жанра из списка Spinner по отдельности
с помощью логической конструкции if.
Создадим мы...
Список List.
Импортируем пакет List.
Дадим ему название,
которое нам дает студия.
И создаем новый массив строк.
Но перед этим нам нужно объявить
класс List, по которому мы будем
обращаться из класса MainActivity.
Допустим, getListTV.
Здесь мы получаем строку.
Данная конструкция будет у нас
раскрываться здесь.
Так как у нас должен возвращать
значение List, мы добавим return_list,
чтобы у нас исчезла ошибка.
Теперь мы создадим логическую конструкцию,
где при наборе определенного варианта
у нас будет выводиться нужный нам сериал.
Здесь мы будем вводить жанры сериала,
которые мы вводили в файле strings.
Первым у нас идет комедия.
Скопируем его.
Вставим.
И для него создадим вид —
сериал, например, «Друзья».
Сериал из 90-х.
Следующий у нас идет в списке фэнтези.
Скопируем.
Создадим для него конструкцию if.
И введем тот же самый код.
Для жанра фэнтези мы создадим
сериал «Игра престолов».
Для того чтобы ускорить процесс,
можно создать шаблон,
куда потом мы будем вписывать
уже готовые значения.
Обращаем внимание, что у нас тут
двойные кавычки.
Всего у нас жанров пять.
Скопируем данную конструкцию.
И добавим еще раз.
Здесь нам нужна закрывающая скобка.
И снова закрывающая скобка.
Следующий у нас — ужасы.
Скопируем.
Чтобы не вводить.
Ужасы — мы назначим сериал
«Ходячие мертвецы».
Следующий жанр — фантастика.
В фантастику мы вставим мультик
«Футурама».
Следующий жанр у нас — криминал.
И сюда мы вставим сериал «Во все тяжкие».
На этом мы создали наш список.
Теперь перейдем на вкладку Main,
куда мы добавим массив строк
для вывода значений каждого сериала
по соответствующему ему жанру.
Создадим приватную переменную
для класса SeriesList,
для того чтобы получить к нему доступ.
Дадим ему переменную, которую
предлагает нам студия.
И создадим новый объект.
Далее мы получим ссылку
на список сериалов.
Вставим его здесь.
Нам нужно добавить пакет.
И теперь создадим класс StringBuilder
с методом append.
Дадим ему переменную.
С обновленным значением.
Теперь у нас поменялся с GetList на
ListModified.
Заменим, чтобы у нас
не высвечивалась ошибка.
Класс StringBuilder с методом append
соединяет представление текстового типа
данных и получает строковое представление
через метод String.valueOf,
который мы объявили ранее,
и затем класс StringBuilder получает
строки из класса SeriesList и затем
склеивает полученные строки
в итоговую строчку.
Также конструкция StringBuilder отвечает
за то, чтобы при добавлении нового сериала
он выводился на новой строке, а не
слипался с уже существующим значением.
Для начала, чтобы проверить, что у нас
все работает, запустим проект.
Нам нужно удостовериться в том, что при
клике на жанр сериала выводится его вид.
Сборка у нас завершилась.
Заняло это 26 секунд.
Теперь это все передается эмулятору.
И эмулятор у нас выводит.
Например, «комедия» ставим.
И нажмем на кнопочку «Выбрать сериал».
Мы видим: наш сериал с жанром «комедия»
высветился.
Давайте проверим все.
Выберем «фэнтези».
Нажмем на кнопку для обновления.
Да, работает.
Ужасы.
Работает.
Фантастика.
Работает.
И криминал.
Работает.
Как уже отмечалось, конструкция
StringBuilder отвечает еще за то, чтобы
при добавлении нового сериала
он выводился на новой строке,
а не слипался с уже существующим
значением.
Поэтому для начала посмотрим,
как это выглядит.
Например, добавим новый сериал.
В жанр криминал.
Например, «Менталист».
Сейчас.
Проверим, как это будет выглядеть.
Откроем «криминал».
Выберем.
Как мы видим, у нас два сериала
не разделились ничем.
Они на одной строке.
Чтобы это исправить, для этого существует
метод append.
Он уже есть.
И мы добавим к нему разделитель.
С обратным слэшем.
И проверим работу.
Снова проверяем.
И, как мы видим, StringBuilder разделил
два сериала, выделив каждому строку.
Подробнее про StringBuilder вы можете
прочитать по ссылке в описании видео.
На этом создание приложения
«Список сериалов» окончено.
В итоге мы научились работать
с обработкой событий через кнопку
и менять текст динамически
в соответствии с выбранным пунктом.
Создали свой первый новый класс
и научились работать с классом Java
StringBuilder.
Теперь настало время для работы
с множественными активностями.
То есть если мы работали только с одним
экраном, на следующем занятии мы создадим
несколько экранов.
И создадим несколько разметок
с помощью объекта Intent.
Множественные активности и интентыСегодня тема нашей лекции — это
множественные активности и интенты.
Мы подробнее поговорим о видах интентов,
о том, что они содержат и что они делают
в нашем приложении.
Интент представляет собой объект
обмена сообщениями, с помощью которого
можно запросить выполнение действия
у компонента другого приложения.
Объекты Intent используются для запуска
конкретных компонентов приложения —
например, определенной активности
или службы.
Переход на новый экран.
Также интенты бывают двух видов:
явные и неявные.
Рассмотрим их свойства подробнее
на следующем слайде.
Явные объекты Intent указывают компонент,
который требуется запустить,
с указанием имени класса.
Явные объекты Intent обычно используются
для запуска компонента из вашего
собственного приложения,
поскольку вам известно имя класса Activity
или службы, которую необходимо запустить.
Например, можно запустить новую Activity
в ответ на действие пользователя
или запустить службу, чтобы загрузить файл
в фоновом режиме.
Неявные объекты Intent не содержат имени
конкретного компонента или адресата.
Вместо этого они в целом объявляют
действие, которое требуется выполнить,
что дает возможность компоненту
из другого приложения обработать
данный запрос.
Например, если требуется показать
пользователю место на карте,
то с помощью неявного объекта Intent
можно запросить, чтобы это сделало
другое приложение, в котором такая
возможность предусмотрена.
Обычно Intent, объект интента, содержит
информацию, на основании которой
система Android определяет,
какой компонент требуется запустить.
Например, точное имя компонента
или категорию компонентов, которые должны
получить данный объект Intent,
а также сведения, которые необходимы
компоненту-получателю, чтобы
надлежащим образом выполнить действие,
а именно: выполняемое действие и данные,
с которыми его требуется выполнить.
Основные сведения, содержащиеся
в объекте Intent, — это имя компонента.
Который требуется запустить.
Данная информация является
необязательной, но именно она
и делает объект Intent явным.
Ее наличие означает, что объект Intent
следует доставить только компоненту
приложения, определенному по имени.
При отсутствии имени компонента
объект Intent является неявным,
а система определяет, какой компонент
получит данный объект Intent, по другим
сведениям, которые в нем содержатся.
Поэтому если вам требуется запустить
определенный компонент из своего
приложения, следует указать его имя.
Следующее содержание объекта интента —
это действие.
Строка, определяющая стандартное действие,
которое требуется выполнить.
Например, просмотр или выбор.
Действие в значительной степени
определяет, каким образом структурирована
остальная часть объекта Intent.
В частности, что именно содержится
в разделе данных и дополнительных данных.
Для использования объектами Intent
в пределах своего приложения
либо для использования
другими приложениями, чтобы вызвать
компоненты из вашего приложения,
можно указать собственные действия.
Обычно же следует использовать константы
действий, определенные классом Intent
или другими классами платформы.
Вот несколько стандартных действий
для запуска операции.
Например, ACTION_VIEW.
Используйте это действие в объекте Intent
с методом startActivity, когда имеется
определенная информация, которую операция
может показать пользователю.
Например, фотография в приложении галереи
или адрес для просмотра
в картографическом приложении.
Также существует константа ACTION_SEND.
Данный объект называют Share, то есть
намерение предоставить общий доступ.
Это действие следует использовать
в объекте Intent с методом тоже
startActivity, при наличии определенных
данных, доступ к которым пользователь
может предоставить через другое
приложение — например, приложение
для работы с электронной почтой
или социальными сетями.
Другие константы, определяющие
стандартные действия, можно посмотреть
по следующей ссылке.
Все находится в документации по Android.
Здесь определены самые популярные
константы — например, константа
ACTION_DIAL существует для вызова
приложения для совершения звонков.
Вернемся к слайду.
Следующее содержание объекта интента —
это категория.
Категория является строкой, содержащей
прочие сведения о том, каким компонентом
должна выполняться обработка
объекта Intent.
В объект Intent можно поместить
любое количество описаний категорий,
однако большинству объектов Intent
категория не требуется.
Существует несколько стандартных
категорий: это CATEGORY_LAUNCHER
и CATEGORY_BROWSABLE.
Категория BROWSABLE — это целевая
операция, которая позволяет запускаться
отображению данных,
указанных по ссылке.
Категория LAUNCHER.
Эта операция является начальной
операцией задачи, она указана
в средстве запуска приложений системы.
Полный список категорий также можно
посмотреть на сайте документации Android.
Вот они — все стандартные категории.
Здесь действия.
Здесь категории.
Следующее — это у нас данные.
Здесь у нас встречается новый термин —
объект URI.
Это объект, который берет строку
и разбирает ее на составляющие,
и хранит в себе эту информацию.
Тип передаваемых данных обычно
определяется действием объекта Intent.
Например, если действием является
ACTION_EDIT, в данных должен содержаться
URI документа.
Который требуется отредактировать.
При создании объекта Intent, помимо URI,
зачастую бывает важно указать тип данных —
их тип MIME.
MIME — это многоцелевые расширения почты
Интернета, спецификация для передачи
по сети файлов различного типа:
изображений, музыки, текстов, видео
и архивов.
Например, Activity, которая может
выводить на экран изображения,
скорее всего, не сможет воспроизвести
аудиофайл, даже если у тех и у других
данных будут одинаковые форматы URI.
Поэтому указание типа MIME данных
помогает системе Android найти более
подходящий компонент для получения
вашего объекта Intent.
И последний объект интента.
Это дополнительны параметры (extras).
Пары «ключ-значение», содержащие прочую
информацию, которая необходима
для выполнения запрошенного действия.
Точно так же, как некоторые действия,
используют определенные виды URI данных,
некоторые действия используют
определенные дополнительные данные.
Добавлять дополнительные данные можно
с помощью различных методов putExtra.
Каждый из которых принимает два параметра:
имя и значение ключа.
Также можно создать объект Bundle
со всеми дополнительными данными,
затем вставить объект Bundle в объект
Intent с помощью метода putExtras.
Например, при создании объекта Intent
для отправки сообщения электронной почты
с методом ACTION_SEND можно указать
получателя с помощью ключа EXTRA_EMAIL.
А тему сообщения ― с помощью ключа
EXTRA_SUBJECT.
Этим мы займемся при создании приложения.
На примере мы рассмотрим,
как это все указывается.
Следующий слайд у нас показывает переход
на новую активность при помощи Intent.
В данном случае, как мы уже говорили,
здесь у нас метод putExtra, который
передает имя и значение ключа.
Первая активность у нас запускает
новую активность (в данном случае
DisplayMessage.class),
а вторая активность — сам класс
DisplayMessage: он принимает данные,
переданные через первую активность.
Следующий у нас слайд показывает
переход в другое приложение.
В данном случае мы здесь можем увидеть
неявный Intent.
Здесь мы просто выбираем браузер —
любой, на выбор пользователя,
который стоит открыть.
Здесь у нас явный интент, который говорит,
что именно браузер Opera
нам требуется открыть.
Следующий у нас — слайд, который
показывает выбор приложения для запуска.
В данном случае мы объявляем тип.
Передаем метод putExtra со значением
и с именем ключа.
И далее мы создаем метод createChooser,
который позволяет выбрать приложение
на усмотрение пользователя.
Следующий — это у нас Intent Filter.
Фильтр Intent — он представляет собой
выражение в файле манифеста приложения,
указывающее типы объектов Intent,
которые мог бы принимать компонент.
Например, объявив фильтр Intent
для Activity, вы даете другим приложениям
возможность напрямую запускать
вашу Activity с помощью некоторого
объекта Intent.
Точно так же, если вы не объявите
какого-либо фильтра Intent для Activity,
то ее можно запустить только с помощью
явного объекта Intent.
В данном случае Intent Filter дает
указание в файле AndroidManifest, что
класс MainActivity является запускающим.
То есть данный класс запускается первым,
данная активность запускается первой
при открытии приложения.
Несмотря на то что объекты Intent обращают
обмен данными между компонентами
по нескольким аспектам, в основном они
используются в трех ситуациях:
для запуска Activity,
для запуска сервиса (то есть службы)
и для запуска ресивера (то есть для
рассылки широковещательных сообщений),
о котором мы поговорим
на следующем слайде.
Компонент Activity представляет собой
один экран приложения.
Для запуска нового экземпляра компонента
Activity необходимо передать объект Intent
метода startActivity.
Объект Intent описывает операцию, которую
требуется запустить, а также содержит
все остальные необходимые данные.
Для запуска службы: Service является
компонентом, который выполняет
действие в фоновом режиме
без пользовательского интерфейса.
Службу можно запустить для выполнения
однократного действия (например, чтобы
загрузить файл), передав объект Intent
методу startService.
Объект Intent описывает службу,
которую требуется запустить,
а также содержит все остальные
необходимые данные.
Если служба сконструирована с интерфейсом
клиент-сервер, к ней можно установить
привязку из другого компонента,
передав объект Intent методу bindService.
И объект Intent используется
еще в одной ситуации — для рассылки
широковещательных сообщений.
То есть Receiver.
BroadcastReceiver — его полное название.
Широковещательное сообщение —
это сообщение, которое может принять
любое приложение.
Система выдает различные
широковещательные сообщения
о системных событиях.
Например, когда система загружается
или устройство начинает заряжаться.
Для выдачи широковещательных сообщений
другим приложениям необходимо передать
объект Intent методу sendBroadcast,
sendOrderedBroadcast
или sendStickyBroadcast.
Также Intent Filter можно не указывать,
если в нем нет необходимости.
Теперь мы рассмотрим приложение,
которое будем создавать.
Мы создадим в этой лекции два приложения.
Первое приложение будет передавать
какие-либо данные на другое
окно активности.
А второе приложение будет содержать в себе
четыре кнопки, которые будут запускать
четыре приложения.
Это запуск вызова.
Следом это запуск сайта.
Третье — это отправка письма.
И четвертое — это запуск карт.
Создание приложения "Передача данных"В этом уроке мы создадим приложение,
в котором будем отправлять данные
через кнопку,
создадим разметку с вводом данных,
кнопку, передающую эти данные,
и новую активность, где будут отображаться
данные, которые мы передали.
Создадим проект.
Откроется новое окно, в котором мы впишем
название нашего приложения.
Назовем его Send Intent App.
Название пакета мы оставим по умолчанию.
Кликаем Next.
Здесь у нас Android 5.0.
Кликаем Next.
Выбираем пустой шаблон Activity.
Кликаем Next.
Здесь у нас все остается по умолчанию.
И нажимаем на кнопку Finish.
Ожидаем окончания построения
нашего приложения.
Когда наше приложение подгрузится,
мы можем запустить сразу
виртуальный эмулятор.
Отлично, у нас все запустилось.
Здесь у нас один TextView.
Теперь мы будем работать.
С данной разметкой.
Мы создадим элементы Button и EditText
и разместим их по центру
и добавим текст для элементов
и назначим им идентификаторы.
Удаляем.
Макет ConstraintLayout.
Добавляем линейный макет.
Далее удаляем лишний код.
Здесь также удаляем.
Удаляем также TextView.
Нам понадобится EditText.
Зададим ему ширину и высоту.
Пусть он будет по содержимому.
Так, дадим идентификатор EditText.
С названием send_text.
И придадим подсказку, которая будет
исчезать при набирании текста.
Здесь мы ей придадим название.
Следом мы создадим кнопку Button.
Зададим ей ширину и высоту.
Также дадим ей имя с идентификатором.
Например, button_send.
И назначим ей текст.
Для подключения обработчика кнопки
добавим в элемент Button также
атрибут onClick.
Со значением sendMessage.
Значение sendMessage представляет собой
имя метода, определенного в классе
Activity, который вызывает систему
при нажатии пользователем на кнопку.
Отредактируем далее разметку
и добавим новый атрибут ems.
Длина строки со значением 15.
И также мы добавим inputType вид.
Добавим ему значение.
Со значением textEmailAddress.
Добавим строки в strings.
Для того чтобы у нас не было
предупреждений.
Дадим название send_text, например.
Так же, как название идентификатора.
И для кнопки тоже добавим
строковый ресурс.
С именем button_send.
Теперь создадим метод sendMessage
для класса Activity.
Мы автоматически перешли в класс
MainActivity и видим, что создался метод
обработки событий — нажатий на кнопку.
Теперь наша цель — передавать данные
на новый экран с помощью этой кнопки.
Мы для этого создадим объект Intent.
Объект Intent, как уже говорилось,
представляет собой такой объект, который
помогает связывать отдельные компоненты —
например, два объекта Activity.
Мы также создадим новую активность.
Далее внутри данного класса мы, как уже
говорилось, создадим новую активность
и назовем ее DisplayMessageActivity.
В этом уроке мы создали разметку
с элементами EditText и Button.
Создали метод для кнопки
под названием sendMessage.
И в следующей части нашего урока мы
продолжим работу над новым приложением,
где добавим код MainActivity
и впервые создадим новую активность
под именем DisplayMessageActivity.
А пока, чтобы проверить правильность
построения нашей разметки,
мы запустим ее на эмуляторе.
Также мы здесь забыли добавить
ориентацию — обязательный атрибут.
Вертикальную.
И расположим все элементы по центру
с помощью атрибута gravity
со значением center.
Запустим.
Чтобы проверить.
Нет ли каких у нас ошибок.
У нас запустилось приложение.
Мы видим созданный элемент EditText
и кнопку.
Мы также можем сделать отступ.
Чтобы объекты не были так близко
расположены друг к другу.
Отступ мы сделаем для кнопки EditText
снизу.
В размере 20 dp.
Во второй части нашего урока мы
продолжим создание приложения,
передающего данные
с одного окна активности в другое.
Мы перейдем на вкладку MainActivity.
Как мы уже говорили, внутри метода
sendMessage создадим объект Intent
для запуска нового объекта Activity,
который назовем DisplayMessageActivity.
Создаем объект Intent.
Импортируем пакет.
Первый параметр представляет контекст.
Ключевое слово this употребляется здесь,
так как класс Activity является
подклассом класса Context.
То есть ключевое слово this говорит нам
о том, что в этом приложении должен
происходить запуск в этой активности.
И добавляем имя нашей будущей
новой активности.
Создадим ее чуть позже.
И через нее мы будем передавать
объект Intent.
Внутри метода sendMessage используем
метод findViewById, чтобы получить
элемент EditText и передать значение
его текста в объект Intent.
Создаем EditText.
Посмотрим, какой идентификатор
мы ему дали.
По этому идентификатору мы будем
к нему обращаться.
Далее мы получим текст от EditText.
И конвертируем текст в строку.
С помощью следующей строчки.
Следующим добавляем с помощью
свойства putExtra объект,
первым параметром которого будет ключ,
а второй параметр — значение
этого объекта.
Ключом у нас будет EXTRA_MESSAGE.
Значение будет message.
В качестве переменной класса мы сейчас
создадим константу EXTRA_MESSAGE.
Мы ее создадим в качестве
публичной переменной.
Подсветка у нас исчезла.
И значение добавим —
любой произвольный текст.
Например, hello!
Использование константы в активности
достаточно является распространенной
практикой, поскольку гарантирует,
что ключ будет уникальным
при взаимодействии одного
приложения с другим.
Далее в итоге мы должны вызвать
метод startActivity.
С переменной Intent.
На этом у нас код в MainActivity
набран полностью.
Теперь нам нужно создать
новую активность.
Под именем DisplayMessageActivity.
Можно скопировать название.
Раскроем полностью наш список
всех папок.
Обратите внимание, что студия
подсвечивает те папки, в которых
она нашла ошибку.
На название пакета мы щелкаем
правой кнопкой мыши.
И создаем новую активность.
Новую пустую активность.
Задаем имя.
Также хотелось бы обратить внимание,
что мы уберем галочку со значения
Generate Layout File,
поскольку нам не требуется
автоматически созданная разметка.
Мы впервые создадим TextView
с помощью кода Java.
То есть программным образом.
Здесь также у нас появился новый
пункт меню — это Launcher Activity.
Это означает, что при нажатии
на эту галочку DisplayMessage будет
запускаться первым.
Не MainActivity, а DisplayMessage.
Поэтому мы здесь галочку
не будем ставить.
Здесь также у нас появляется новый
пункт — это целевой язык.
В данном случае у нас Java.
И нажимаем на кнопку Finish.
У нас создался новый класс.
Как мы видим, здесь не определена
разметка методом setContentView.
Как мы видим, здесь у нас исчезло
предупреждение о том, что
этой активности не существует.
Мы ее создали с тем же именем.
И нам теперь потребуется вывод
сообщения в этот экран активности.
Как мы помним, в начале мы передавали
из нашей первой и главной Activity
новое текстовое сообщение,
которое было выведено в текстовое поле.
Теперь получим его в DisplayMessage
и выведем на экран.
В данном случае нам нужно получить
сообщение из объекта Intent.
Нам потребуется получить сообщение
EXTRA_MESSAGE.
Для этого мы создаем Intent.
Мы можем получить вызывающий объект
Intent с помощью метода getIntent.
И таким образом получить
переданные с ним данные.
Для начала мы создадим сам Intent.
Подгрузим пакет.
Получаем нашу константу.
И указываем, откуда мы ее получаем.
А также ее имя.
Для вывода сообщения на экран
создадим элемент TextView
и с помощью его свойства setText
установим размер текста.
Затем добавим новый элемент
DisplayMessageActivity при помощи
метода setContentView.
Создаем программно впервые мы разметку.
С одним элементом TextView.
Определим ему размер текста.
В нашем случае это будет, например, 20 sp.
Без указания размера.
И передаем само значение.
Что должен отобразить наш TextView
на новом экране.
И теперь, чтобы это все вывелось,
нам нужно вызвать метод setContentView.
С самим текстом.
Запустим наше приложение.
Но для начала удостоверимся, что у нас
нигде ошибок нет.
И запускаем.
После запуска приложения на эмуляторе
мы видим текстовое поле с кнопкой.
Введем текст.
Например, мы задали input type вид
с передачей e-mail сообщения.
Допустим, для примера
мы просто передадим.
И, как мы видим, в новом экране
у нас отобразился данный текст.
Передавать можно любые параметры.
Можно даже цифры.
И у нас запускается новая активность.
С текстом, который мы ввели.
На этом построение приложения
у нас закончено.
Мы рассмотрели, как объект Intent передает
с помощью константы EXTRA_MESSAGE
данные с одного экрана приложения
на другой.
Создание приложения для вызова сторонних приложенийВ этой части нашей лекции мы создадим
приложение, которое будет открывать
сторонние приложения на выбор,
которые установлены на телефоне,
в зависимости от типа самого приложения.
В этой части мы подготовим разметку
и создадим шаблоны обработчика события
для каждой кнопки,
а в следующей, заключительной части —
закончим наше приложение,
добавив методы для проверки приложений
на существование установленных приложений
на телефоне или на устройстве.
Создадим проект.
Название впишем: Call Intent App.
Остальное оставляем по умолчанию.
Оставляем Android 5.0.
Создаем пустой шаблон Activity —
выбираем Empty Activity.
И оставляем по умолчанию
название класса и разметки.
Мы сначала создадим четыре кнопки.
И разместим их по центру.
Также мы добавим текст и назначим
идентификаторы каждой кнопке.
Перейдем на вкладку activity_main.
Так как у нас еще студия не собралась
до конца, нам подсвечивают все красным.
Так, замечательно.
У нас все построилось.
У нас не будет использоваться TextView.
Мы его удалим.
Также мы снова воспользуемся разметкой
LinearLayout — линейным макетом.
Удалим лишний код.
Дадим ему обязательный атрибут —
ориентацию.
И так как, я уже говорила, нам потребуется
выравнивание по центру кнопок,
мы сначала попробуем выровнять их
по центру и посмотрим, как будет лучше
отображаться на разметке.
Хотелось бы добавить отступы от края.
Со всех сторон.
Чтобы наши кнопки не были
прижаты к макету.
Мы дадим ему 16 dp.
И создаем четыре кнопки.
По ширине они будут растягиваться
на весь экран.
А по высоте они будут растягиваться
по содержимому.
Мы можем скопировать сразу кнопку Button.
Итак, далее первая кнопка у нас будет
вызывать приложение
для совершения звонков.
Дадим ему текст "Call".
И назначим ему идентификатор.
Button_call.
Следом вторая кнопка
у нас будет вызывать приложение,
которое содержит в себе карты.
Например, Яндекс.Карты, Google карты,
возможно, Яндекс.Транспорт, 2ГИС.
Мы дадим ему идентификатор button_map.
И мы пропустили линию text.
Назовем его «Просмотр карты».
Третья кнопка у нас будет просматривать
web-страницы, то есть запускать браузер.
Назовем ее "View web pages".
И дадим ему идентификатор button_web.
И последняя у нас кнопка будет вызывать
приложение для отправки писем.
Например, Gmail, Mail.ru, Яндекс.Mail.
Дадим ему название просто "Send mail".
И идентификатор со значением button_mail.
Добавим новые значения строк
в файле strings.xml.
Здесь мы оставим все по умолчанию.
Обратите внимание, что для кириллицы
нам приходится создавать
новое имя, вписывать.
А так как мы сейчас пишем все на латинице,
имя ресурса у нас создается автоматически.
Отлично, мы все создали.
Теперь мы запустим и посмотрим,
как это все у нас будет выглядеть
на виртуальном устройстве.
Отлично, у нас есть четыре кнопки,
которые расположились по центру
нашей разметки.
Теперь мы должны создать
для каждой кнопки обработчик события.
Создать для них методы.
Мы создадим новым образом.
Первый метод у нас будет — вызов.
Так как он будет добавлять методы сверху,
то мы начнем лучше с конца.
Пусть первый метод у нас будет SendMail.
Например, который мы создадим.
Мы создали метод.
Далее следующий у нас — для web-страницы.
Обратите внимание, что они будут
добавляться после друг друга.
Следующий у нас — просмотр карт.
И наш — для совершения звонков.
Так, отлично.
Теперь мы определим
каждой кнопке слушателя.
Найдем эти кнопки.
ButtonCall, например.
И создадим для buttonCall
обработчик события,
как мы делали на прошлых занятиях.
Так, отлично, мы оставим
так пустые методы.
Создадим для каждой кнопки,
чтобы в следующей части нашей лекции
мы уже работали только с кодом активности.
И заполняли эти шаблоны.
Также находим нашу кнопку Button,
которая открывать будет приложение карт.
Найдем кнопку в нашей разметке.
У нас она с идентификатором Map.
И также ей создаем слушателя.
Следующая у нас — кнопка, которая будет
открывать web-страницы, web-приложения.
В нашем случае это браузер будет.
Найдем нашу кнопку.
И также ей создадим слушателя.
И последняя кнопка у нас будет
для отправки писем.
Идентификатор у нее будет Mail.
И также создадим ей слушателя.
Мы создали четыре метода —
для каждой кнопки.
В следующей части нашей лекции
мы наполним функционалом
каждую из кнопок.
Мы продолжаем работу над приложением.
В прошлой части мы создали конструкцию
из четырех кнопок.
Теперь самое время
заполнить их содержимым.
Мы свяжем обработчик событий
View.OnClickListener с нашими кнопками
для открытия диалогового окна
в приложении.
Также мы будем использовать данные URI.
Которые мы проходили на лекции.
И будем использовать конструктор
для создания неявного намерения.
Для кнопки buttonCall мы создадим
Intent для набора номера.
Добавляем пакет.
И также нам требуется спарсить
telephone number.
Спарсить данную строку.
И вызвать Intent.
Запуском диалогового окна для выбора
приложения для совершения звонков.
Действие мы выберем ACTION_DIAL.
Значение number.
Для того чтобы просматривать карты
существует также конструкция URI.
Дадим переменной название location.
И спарсим строку с геометкой.
В нашем случае это будет точка на карте
на основании широты и долготы.
Параметр z здесь используется
для масштабирования карты.
То есть мы увеличиваем в 14 пунктов.
То есть при открытии карты
сразу выставится метка данной локации.
И также создаем Intent
для запуска приложения.
С действием ACTION_VIEW,
которое будет запускать нужное приложение
для открытия карт.
И для кнопки buttonWeb, которая будет
открывать страницу браузера,
тоже существует конструкция.
Дадим название переменной webPage
и спарсим строку с адресом сайта.
В качестве web-страницы
у нас будет ВКонтакте.
Мы будем открывать эту страницу.
Потому что ее можно открыть
как и через браузер, так и из приложения,
поскольку оно установлено
на многих устройствах
и является весьма популярным приложением.
Действие у нас будет — также просмотр.
ACTION_VIEW.
И параметр webPage.
Как вы успели заметить, здесь нет метода
startActivity, который уже напрямую
дает команду запустить приложение.
Мы его создадим попозже,
поскольку нам еще осталось заполнить
функциональностью кнопку Mail.
Она будет у нас отличаться от остальных,
поскольку здесь уже у нас конструкция,
которую открывают.
В кнопке buttonMail мы также зададим
дополнительные константы, которые
будут заполняться.
Тему сообщения мы будем заполнять.
Также мы будем передавать сообщение само.
И мы будем добавлять адресатов.
С помощью существующих констант
дополнительных.
Мы добавим Intent
с дополнительными данными
для отправки электронного сообщения
посредством приложения для отправки писем.
Лучше всего использовать приложение Gmail.
Создадим Intent.
Дадим ему название emailIntent.
Далее нам потребуется...
Существует действие ACTION_SENDTO,
специально созданное для отправки писем.
Далее мы заполняем объект URI.
И в нем мы вставим электронные адреса.
Сначала мы отправим «кому»,
а потом уже и сам адрес.
Например, мы создадим exemple@gmail.com.
Третий параметр у нас будет null.
Все это сместим на следующую строчку,
чтобы у нас помещалось все
в окне редактора.
Следующее: мы добавляем в копию
дополнительных адресатов
с помощью метода putExtra.
Мы его рассматривали на лекции.
По интентам.
Здесь существуют дополнительные данные
EXTRA_MAIL.
В данном случае EXTRA_EMAIL.
И добавляем строчку, которая будет
автоматически в поле для дополнительных
адресатов добавлять адреса.
Здесь, например, создадим hello@mail.ru.
И, например, просто hi@mail.ru.
Следующее: мы добавим текст
в тему сообщения.
С помощью дополнительной константы
EXTRA_SUBJECT.
И впишем тему сообщения, например,
Send Intent Message.
И последний параметр у нас будет
для наполнения самого окна сообщения.
Какой текст там будет указан
по умолчанию.
У нас будет EXTRA_TEXT параметр.
И здесь мы напишем, что мы отправили
этот текст через приложение Android.
И, как уже отмечалось, у нас нет метода
startActivity, который уже запускает сами
интенты, и нам потребуется создать условие
для проверки с выводом уведомления.
Для чего это нужно?
Для того чтобы проверить,
есть ли такие приложения или нет.
Если мы не создадим данное условие,
то если на телефоне не будет
таких приложений,
наше приложение упадет с ошибкой.
Поэтому мы создадим метод
для проверки правильности условия.
Если данного приложения нет, оно бы
не запускалось, а просто выдавало Toast,
то есть уведомление,
всплывающее сообщение,
которое бы говорило о том, что
такого приложения на устройстве нет.
Для этого нам нужно создать метод
isIntentSafe, который будет проверять
наличие приложения.
Так как там будет значение true или false,
то у нас тип данных будет boolean.
Для этого мы используем пакет-менеджер.
Дадим ему название packageManager.
Импортируем класс.
И получим getPackageManager,
который будет получать список
существующих приложений.
И запрос активности.
И также обязательный атрибут —
возвращение типа объекта.
Который должен быть больше нуля.
И теперь нам требуется добавить условие
проверки в каждый обработчик событий
View.OnClickListener.
То есть для каждой кнопки мы должны
создать конструкцию, которая бы проверяла,
существует ли приложение, и если
оно существует, то запускала бы его,
а если его не существует, то выдавала бы
всплывающее сообщение о том, что
приложения нет на устройстве.
Так как мы уже создали метод,
нам требуется теперь только ввести...
Условие проверки.
В нашем случае это callIntent
здесь будет для данной кнопки.
И наш метод startActivity, который будет
запускать, если приложение существует.
И следом условие проверки.
Здесь у нас будет просто
выводиться сообщение.
Поддерживает ли наш телефон
такое приложение.
То есть здесь мы написали о том, что
на этом телефоне нет приложения,
которое бы запускало вызовы.
Зададим время отображения.
Пусть это будет short.
Здесь мы перейдем на следующую строчку,
чтобы у нас все помещалось в одном окне.
И вызовем метод show.
И теперь данная конструкция у нас будет
обрабатывать все запросы.
И такую конструкцию нам нужно будет
добавить для всех кнопочек.
Вы можете скопировать,
а можете для набивания руки
писать код самостоятельно.
В данном случае я просто скопирую.
А вы можете это написать самостоятельно.
Так вы лучше запомните эту конструкцию.
Для кнопки открытия карт мы уже создали,
теперь нам нужно создать для кнопки
открытия web-страницы.
В данном случае сайта ВКонтакте.
Так, и для открытия сообщений.
Убедимся, что конструкция
присутствует везде.
И запустим наш проект.
Обратите внимание: чтобы на эмуляторе
открывались ссылки, необходимо
интернет-подключение.
Так, вызовем первую кнопку.
Так, открывает приложение
для набора номера.
Отлично, возвращаемся.
Теперь мы посмотрим карту.
Запускается приложение Google карт.
Но здесь нам потребуется вход.
Мы это пропустим.
И нам откроется метка с указанием адреса.
Возвратимся обратно.
Откроем web-страницу.
Здесь у нас предлагаются на выбор
два сервиса для открытия.
Мы выбираем Chrome.
Можем единожды его вызвать либо всегда.
Вызовем его единожды.
Примем.
Next.
В следующий раз зайдем.
И дождемся открытия сайта ВКонтакте.
Отлично, сайт у нас открылся.
И последнее приложение.
Которое должно запуститься у нас
для отправки сообщений.
У нас должен открыться Gmail.
Здесь мы тоже пропустим.
Добавим какой-нибудь адрес.
Пусть мы войдем через Google.
Для того чтобы увидеть, как заполнили
содержимое для e-mail'ов.
Если получится зайти через эмулятор,
то мы это увидим.
Если не получится, то вы можете
попробовать протестировать данное
приложение через реальное устройство.
То есть через смартфон.
Так, попробуем войти.
Отлично.
Пропустим.
И дождемся все-таки отправки.
Нашего сообщения.
Отлично, добавился наш адрес.
Мы попытаемся свернуть наше приложение
и вернуться к нашему приложению,
найти его.
И запустить уже с авторизацией.
Так, наше приложение Call Intent.
Вернемся к нему.
Все отобразилось.
Все, что мы вводили,
дополнительные данные.
Это сам адресат, от кого сообщение.
Далее мы вводили три почтовых ящика.
Здесь также подгрузилась тема сообщения.
И сам текст сообщения.
Отлично, у нас все работает,
все подключилось.
Вы можете попробовать подключить
и другие приложения.
Если у вас получится настроить действие
ACTION для каждого из них.
Все это можно посмотреть по документации.
Либо Stack Overflow
поможет вам разобраться.
Со всеми.
На этом наш урок подошел к концу.
В следующей лекции мы будем работать
с жизненным циклом Activity.
Теория жизненного циклаНа этом уроке мы поговорим
о жизненном цикле Activity,
определим цель использования
всех методов жизненного цикла,
а после — рассмотрим понятие «фрагмент».
Во время навигации пользователя
по вашему приложению
экземпляры Activity внутри приложения
переключаются между разными состояниями
их жизненного цикла.
Например, при первом запуске Activity
она получает высокий приоритет в системе
и привлекает внимание пользователя.
Во время этого процесса система Android
вызывает серию методов жизненного цикла
Activity, позволяя настроить
пользовательский интерфейс
и другие компоненты.
Если пользователь выполняет действие,
запускающее другую Activity,
или переключается на другое приложение,
система вызывает другой набор методов
жизненного цикла для Activity, поскольку
она переносится на фоновый уровень,
где Activity больше не отображается,
но экземпляр и состояние остаются
без изменений.
В зависимости от сложности Activity,
некоторые методы жизненного цикла
могут не требоваться.
Однако очень важно понимать все методы
и реализовать их так, чтобы приложение
работало так, как этого ожидают
пользователи.
Правильная реализация методов
жизненного цикла Activity
обеспечивает нормальную работу приложения
в нескольких аспектах.
В том числе: не прекращает работу, если
пользователь получает телефонный звонок
или переключается на другое приложение
во время использования вашего приложения.
Не потребляет ценные системные ресурсы,
когда пользователь не использует
его активно.
Сохраняет состояние приложения,
если пользователь выходит из него
и возвращается позднее.
Не закрывается с ошибкой и не теряет
данные пользователя при повороте экрана,
а именно при смене ориентации
между книжной и альбомной.
В течение цикла существования Activity
система вызывает базовый набор методов
жизненного цикла в последовательности,
сходной с многоступенчатой пирамидой.
Таким образом, каждый этап жизненного
цикла Activity представляет собой
отдельную ступень пирамиды.
Когда система создает новый экземпляр
Activity, каждый метод обратного вызова
перемещает состояние действия
на одну ступень вверх.
Вершина пирамиды представляет собой точку,
в которой Activity выполняется
в экранном режиме, и пользователь может
с ней взаимодействовать.
Когда пользователь начинает
выходить из Activity, система вызывает
другие методы, которые перемещают
состояние Activity вниз по пирамиде
для уничтожения Activity.
В некоторых случаях действие перемещает
Activity вниз по пирамиде только частично
и ждет (например, когда пользователь
переключается на другое приложение).
А затем Activity может быть перемещена
обратно вверх, если пользователь вернется
к Activity, и возобновлена там,
где пользователь вышел из нее.
Упрощенная иллюстрация
жизненного цикла Activity
в виде многоступенчатой схемы показывает,
что для каждого обратного вызова,
поднимающего Activity на одну ступень
к состоянию возобновления на вершине
пирамиды, существует обратный вызов,
опускающий Activity на одну ступень вниз.
Возобновление Activity также может
производиться из состояний паузы
и остановки.
Запуск Activity — метод onCreate.
В отличие от других парадигм
программирования, где приложения
запускаются с использованием метода main,
система Android запускает код
в экземпляре Activity посредством
активации определенных методов
обратного вызова, соответствующих
определенным этапам его жизненного цикла.
Существует последовательность методов
обратного вызова, которые запускают
Activity, и последовательность методов
обратного вызова, уничтожающих Activity.
Старт Activity — метод onStart.
Эти состояния создания и запуска
являются переходными, и система быстро
переходит от них к следующим состояниям
посредством вызова следующего метода
обратного вызова в жизненном цикле.
Таким образом, после вызова
метода onCreate система быстро вызывает
метод onStart, а затем сразу же вызывает
метод onResume.
Возобновление Activity — метод onResume.
Когда пользователь возобновляет Activity
после паузы, система вызывает
метод onResume.
Учтите, что система вызывает этот метод
каждый раз, когда Activity выполняется
на экране, в том числе и при
первом ее запуске.
В связи с этим нужно реализовать метод
onResume для инициализации компонентов,
освобождаемых в состоянии метода onPause,
и выполнения других операций
инициализации, которые должны происходить
каждый раз при возобновлении Activity.
Приостановка Activity — метод onPause.
Когда система вызывает метод onPause
для Activity, это технически означает, что
Activity остается частично видимой.
Однако чаще всего это означает,
что пользователь покидает Activity,
и вскоре она войдет в состояние остановки.
Обратный вызов метода onPause обычно
следует использовать для следующих целей.
Остановка анимации или других текущих
действий, которые могут потреблять
ресурсы процессора.
Запись несохраненных изменений,
если пользователи ожидают сохранения
таких изменений при выходе.
Например, черновиков электронных писем.
И высвобождение ресурсов системы,
влияющих на время работы аккумулятора
во время паузы
и не требующихся пользователю.
Остановка и перезапуск Activity.
Метод onStop и метод onRestart.
Правильное выполнение остановки
и перезапуска Activity является важным
шагом в жизненном цикле Activity,
благодаря которому пользователи понимают,
что приложение не потеряет их данные.
Например, пользователь открывает окно
«Последнее приложение» и переключается
из вашего приложения в другое приложение.
При этом останавливается Activity вашего
приложения, работающего на экране.
Если пользователь возвращается
в ваше приложение,
нажав значок запуска на главном экране
или через окно «Последнее приложение»,
данная Activity возобновляется.
Следующий пример: пользователь выполняет
в вашем приложении действие,
запускающее другую Activity.
Текущая Activity останавливается
при создании второй Activity.
Если после этого пользователь
нажимает кнопку «Назад»,
первая Activity запускается заново.
И последний пример использования
метода onStop и метода onRestart:
пользователь получает телефонный звонок
или переключается на другое приложение
во время использования вашего приложения
на своем телефоне.
В отличие от состояния паузы, означающего
частичное уничтожение пользовательского
интерфейса, в состоянии остановки
пользовательский интерфейс больше
не отображается, и пользователь
переключается на отдельную Activity
или отдельное приложение.
И последний метод жизненного цикла —
это уничтожение Activity.
Метод onDestroy.
Первым обратным вызовом жизненного
цикла Activity является onCreate,
а последним — onDestroy.
Система вызывает данный метод
для Activity, подавая окончательный сигнал
о том, что экземпляр Activity полностью
удаляется из системной памяти.
Большинству приложений не требуется
реализация этого метода,
поскольку ссылки локальных классов
уничтожаются вместе с Activity.
Основные задачи по высвобождению
ресурсов Activity выполняются в состоянии
методов onPause и onStop.
Однако если ваша Activity содержит
фоновые потоки, созданные во время
выполнения метода onCreate,
или в течение длительного времени
использует другие ресурсы,
которые могут вызвать утечку памяти
при неправильном закрытии, их нужно
уничтожить с помощью метода onDestroy.
В этом случае система сразу же вызывает
метод onDestroy, не вызывая другие
методы жизненного цикла.
Создание приложения "Жизненный цикл Activity"В данном уроке мы создадим пример,
где для каждого метода жизненного цикла
подготовим всплывающие сообщения (тосты).
А также для наглядности будем вести
запись в журнале, если нам удастся открыть
logcat и если он не будет сыпать методы
один за другим.
В приложении мы сможем наблюдать
за состоянием жизненного цикла
в нашем приложении.
Создадим уже по счету шестое приложение.
Дадим ему название Lifecycle App.
Разработка у нас будет начинаться
для Android 5.0.
Выбираем пустой шаблон активности.
И оставляем по умолчанию данные поля.
Перейдем к запуску нашего проекта.
Как обычно, мы в первой части нашей лекции
создадим разметку и подготовим все
для того, чтобы в следующей части
работать только из активности.
Мы создадим два элемента Button
и один TextView.
Также мы их разместим по центру.
И добавим текст и идентификаторы
для элементов.
Подождем, пока наш проект соберется.
Эмулятор мы не закрываем на протяжении
всего периода разработки приложения,
для того чтобы не ожидать его подгрузки.
Наш проект собрался.
Перейдем на вкладку activity_main.
Здесь нам потребуется снова
поменять разметку с ConstraintLayout
на LinearLayout.
Удалить лишний код.
Задать вертикальную ориентацию.
И разместим наши элементы тоже по центру.
Так они будут выглядеть лучше.
Текст мы заменим "Hello World!" на
слова «Приложение запущено впервые».
Добавим ему отступ со всех сторон 20 dp.
И добавим идентификатор
с названием textView.
Следующими мы создадим две кнопки.
Первая кнопка будет менять текст.
А вторая кнопка будет создавать
метод выхода из приложения.
Зададим им ширину и высоту
по содержимому.
Для первой кнопки мы также дадим
отступы со всех сторон.
Назначим ему текст.
Например, «Нажми на меня».
И далее мы добавим метод onClick.
С названием метода clickMe.
Добавим вторую кнопку, которая будет
закрывать наше приложение.
Соответственно, текст ему назначим
«Выход».
Зададим ему также отступ со всех сторон.
20 dp.
И дадим ему идентификатор
с названием exitApp
и метод onClick с именем clickExit.
То есть сначала при запуске приложения
у нас запускается TextView, Button
и Button.
Первый TextView отображает нам сообщение
«Приложение запущено впервые».
Когда вы нажимаете на кнопку Button
с текстом «Нажми на меня»,
здесь меняется текст TextView
на «Приложение уже было запущено».
И кнопка Button «Выход» позволяет
выйти вам из приложения
и закрыть его полностью.
Теперь создадим ссылки для текстовых
сообщений в файле strings.xml,
как мы делали на прошлых занятиях,
присвоив элементам TextView и Button
соответствующие им имена.
Мы можем просто назвать text_app первое.
Здесь можно click_me через нижний пробел.
И здесь click_exit.
Мы назначили им ссылки в файле strings.
Удалим обработчики событий onClick.
Они нам не понадобятся.
Нам понадобятся идентификаторы
для обращения к ним из кода.
Назовем их button_click.
А вторая может остаться так — exitApp.
Отлично, теперь мы перейдем
в файл MainActivity.
В главной активности нашего проекта
мы создадим приватные переменные.
Здесь метод onCreate вызывается
при создании и для перезапуска активности.
OnCreate может запускать и останавливать
текущие окна в зависимости от происходящих
событий и также он задает внешний вид
через метод setContentView.
Для начала мы создадим приватные
переменные, с которыми будем
работать позднее.
В данном случае текст TAG нам потребуется
для logcat'а.
Для того чтобы видеть запись
в журнале событий.
И вторая переменная.
У нас будет отображать смену
состояния TextView.
Добавим их в MainActivity.
И также создадим всплывающее сообщение,
которое будет указывать на то,
какой метод у нас запущен.
Введем здесь имя.
Время отображения.
Метод show, чтобы у нас все отобразилось.
И запись в журнале.
То есть в logcat'e.
В нижней части нашего проекта.
Здесь будут отображаться методы,
которые мы здесь пишем.
Для этого надо добавить
и также импортировать пакет.
И заполнить его содержимым.
Пока свернем его, нижнюю панель.
Добавим наш TAG.
И метод, который у нас должен будет
отображаться при запуске метода onCreate.
В итоге в данном куске кода происходит
создание всплывающего сообщения,
в котором мы определяем вывод сообщений
метода onCreate, когда приложение
перезапускается или только запускается.
Здесь у нас будет отображаться Toast
с текстом "onCreate"
при запуске приложения на устройстве.
А логи будут вести запись в журнале.
Запустим сначала наш проект.
В logcat'е мы можем наблюдать
за системными сообщениями.
Проект у нас построился.
Попробуем найти метод onCreate.
Итак, отлично, вот запись у нас произошла.
То есть то, что мы здесь писали для
logcat'a, отобразилось.
Запись в журнале идет.
Но всплывающее сообщение не появляется.
Попробуем сделать так,
чтобы он отображался чуть больше.
Запустим снова.
Чтобы проверить, выводит ли сообщение
на эмуляторе при запуске приложения.
Наше всплывающее сообщение появилось
и исчезло, поэтому для того чтобы
все методы у нас отображались,
каждому мы будем делать отображение
чуть дольше.
LONG для тоста составляет 3,5 секунды.
LENGTH_SHORT составляет 2 секунды.
На этом первая часть нашего приложения
окончена.
На следующем занятии мы добавим
все оставшиеся методы и будем следить за
изменением жизненного цикла активности.
На прошлом уроке мы подготовили разметку
и обработали метод onCreate.
Сейчас мы продолжим добавление всех
методов жизненного цикла активности,
а также назначим слушателей для кнопок.
После onCreate всегда следует
вызов onStart.
Последний вызывается для возобновления
работы приостановленного приложения.
То есть приложение останавливается
методом onStop и вызывается
непосредственно перед тем, как активность
становится видимой пользователю.
Создадим метод onStart.
То есть он у нас уже есть в системе.
Только мы будем создавать для него
всплывающее сообщение и запись в журнале.
И менять onStart на onCreate.
Метод onResume вызывается после onStart,
даже когда окно работает
в главной активности
и пользователь видит состояние.
Это означает, что пользователь
взаимодействует с созданным вами окном.
Также может вызываться после onPause.
Следует отметить, что система вызывает
метод onResume каждый раз, когда
активность находится на переднем плане,
в том числе и при первом создании.
Создадим данный метод.
Создадим для него сообщение.
Также поменяем с onStart на onResume.
Следующий метод у нас — метод onPause.
То есть когда пользователь решает перейти
к работе с новым приложением,
система вызовет для нашего приложения
метод onPause.
При вызове данного метода происходит
сворачивание активности,
сохранение данных,
идет остановка воспроизведения видео,
аудио и анимации, а также сохранение,
например, черновика письма.
От метода onPause можно перейти к методу
либо onResume, либо onStop.
Создадим метод onPause.
И также добавим для него тосты,
чтобы мы увидели, когда он вызывается.
Сменим onResume на onPause.
И следующий метод у нас — метод onStop.
Он вызывается, когда окно становится
невидимым для пользователя.
Это может произойти при ее уничтожении
или если была запущена другая активность.
Всегда сопровождает любой вызов метода
onRestart, если активность возвращается,
чтобы дальше взаимодействовать
с пользователем.
Создадим метод onStop.
Также ему назначим всплывающее сообщение
и запись в журнале.
Сменим метод onPause на onStop.
Следующий метод у нас — onRestart.
Он возвращается в приоритетный режим
после вызова onStop.
То есть вызывается после того,
как активность была остановлена
и снова запущена пользователем.
Всегда сопровождается вызовом
метода onStart.
Следует использовать его для специальных
действий, которые должны выполняться
только при повторном запуске активности.
Для него также скопируем сообщение Toast.
И сменим имя onStop на onRestart.
И последний метод у нас — метод onDestroy.
Он вызывается при окончании работы
активности, или при вызове метода finish,
или в случае, когда система уничтожает
данный экземпляр активности
для освобождения ресурсов.
Эти два сценария уничтожения можно
определить вызовом метода isFinishing.
Когда система решает завершить окно,
также вызывается метод onDestroy.
В этом случае метод удаляет
все статические данные активности.
Создадим данный метод.
Также создадим для него
тостовое сообщение.
И сменим onRestart на onDestroy.
На практике нам чаще всего придется
сталкиваться с методами onCreate,
onResume и onPause.
Метод onCreate будет вызываться
при создании пользовательского интерфейса
для работы с окном.
Данный метод позволит нам
связывать данные с компонентами
и подключать обработчики событий
компонентам пользовательского интерфейса.
При помощи же onPause мы сможем
сохранить важную информацию
в базе данных нашего приложения.
Это последний безопасный метод,
который будет вызываться перед тем,
как система завершит работу приложения.
Далее, как вы помните,
мы создавали кнопки.
Самое время назначить им события.
Они будут управлять состоянием
методов жизненного цикла.
У нас будет здесь работать цикл switch,
который будет работать с командами при
выборе одного из предложенных вариантов.
Для того чтобы нам создать обработчик
события, нам для кнопок надо будет создать
одинаковые значения для кнопок,
поскольку они будут использоваться
в одном цикле.
Так, мы создали для них метод.
OnClick.
Здесь у нас будет работать цикл switch,
который будет работать с командами при
выборе одного из предложенных вариантов.
То есть создадим...
Переключатель switch.
Здесь также в параметрах у него будет id.
И дальше идет у нас цикл
для каждых случаев.
Для случаев case.
Первая у нас кнопка была buttonClick.
Идентификатор проверим.
Да, buttonClick.
Вторая у нас exitApp.
Для buttonClick мы сделаем смену текста.
То есть когда нажмут на кнопку,
у нас поменяется текст TextView.
На «Приложение уже было запущено».
Следом мы выходим из цикла.
И создаем второй случай.
Для кнопки с именем «Выход».
ExitApp.
И задаем ему метод finish, который будет
полностью закрывать наше приложение.
И также метод break.
Также обязательный параметр у switch —
это DEFAULT.
И тоже закроем его брейком.
Чтобы красиво было, мы выровняем
случай default.
И запустим наш проект
и будем следить за сообщениями, которые
будет нам выдавать наше приложение.
Они будут всплывать
в нужной последовательности,
давая нам представление
о жизненном цикле приложения.
Также сообщения будут транслироваться
в окне logcat на вкладке Android Studio.
Дождемся запуска нашего приложения.
Следует отметить, что данное приложение
мы создаем для того, чтобы понимание
этих вещей помогло вам правильно
выстраивать логику приложения.
Мы видим, что вызвался onCreate.
Здесь.
Далее за ним должен вызваться onStart.
Ну, и так как это эмулятор виртуальный,
попробуем дождаться onPause.
Отлично, мы закрыли приложение.
Итак, все методы у нас отображаются
корректно тут.
Но эмулятор у нас подвисает.
Как мы видим, у нас после onPause
вызвался onStop и onDestroy.
Давайте попробуем снова запустить
наше приложение, чтобы отследить
уже в logcat'е нам все жизненные циклы.
Так, onCreate.
Дальше onPause.
Закрывается, и onDestroy.
Методы onRestart и onResume,
а также onStart он не показывает,
поскольку, видимо, они
не успевают вывестись.
Они вызываются сразу после onCreate.
И быстро исчезают.
Поэтому для того чтобы проверить работу
данного приложения, потребуется все-таки
запуск на реальном устройстве,
которое будет работать без задержек.
На этом построение нашего
приложения окончено.
Будем надеяться, что понимание
жизненного цикла расширит
ваши понятия в Android-разработке.
Создание приложения "Таймер"В этом практическом уроке мы поближе
познакомимся с внутренними механизмами
работы активности, стандартными
проблемами в работе приложений
и возможностями их решения с помощью
методов жизненного цикла активности.
Мы будем изучать методы жизненного цикла
приложения на примере простого
приложения-секундомера «Таймер».
Приложение включает одну активность
и один макет.
Макет состоит из текста,
в котором будет выводиться время,
кнопки Start для запуска секундомера,
кнопки Stop для его остановки
и кнопки Reset для обнуления таймера.
Создадим проект.
Назовем его Timer App.
Оставим поля по умолчанию.
Выберем Empty Activity — пустой шаблон.
И кликнем на кнопку Finish.
Также сразу запустим эмулятор.
Отлично.
Перейдем в файл интерфейса активити —
activity_main.
И создадим следующие элементы.
Три кнопки Button и текст.
Также мы их разместим по центру.
Добавим текст для элементов
и назначим им идентификаторы.
TextView будет использоваться
для прошедшего времени в секундах.
Так, удалим ConstraintLayout,
заменим его на LinearLayout.
Удалим лишние атрибуты также.
Текст у нас будет пустой.
Далее мы увеличим размер текста.
Чтобы цифры у нас отображались
большим шрифтом.
И дадим ему идентификатор time_view.
Следом мы создадим три кнопки.
Первая кнопка у нас будет Start.
Дадим ей идентификатор.
С названием button_start.
И обработчик события onClick.
Назовем onClickStart.
Также мы создадим и для кнопок
Stop и Reset.
И дадим название кнопке.
В макете activity_main у нас используются
три строковых значения.
Их необходимо добавить в файл strings.xml.
Теперь нам надо эти методы
перевести в MainActivity,
чтобы дальше работать с ними.
Они добавляются в порядке указания.
Для обновления показаний
нашего секундомера
будет использоваться метод Runtime,
который мы создадим на следующем занятии.
Он будет ежесекундно проверять работу
таймера, увеличивать число секунд и
выводить его в настроенном нами TextView.
Создадим две приватные переменные
для отслеживания состояния таймера.
В переменной seconds типа int
будет храниться число секунд,
а в переменной running типа boolean
выполняются условия работы секундомера
в настоящий момент.
Кнопки у нас будут использоваться
для управления отсчетом времени.
Методы onClickStart, onClickStop
и onClickReset существуют для запуска,
остановки и сброса значения таймера.
Начнем с кнопки onClickStart.
Здесь у нас будет происходить
запуск секундомера.
При нажатии на кнопку Start переменной
running присваивается значение true,
чтобы секундомер начал отсчет.
Далее у нас идет кнопка
остановки секундомера.
Переменная running равная false.
Что означает, что при щелчке
на кнопке Stop переменной running
присваивается значение false,
что, в свою очередь, означает
окончание времени отсчета.
И остановка секундомера и присваивание
значению seconds значение 0.
То есть Reset у нас будет обнулять
показатели таймера благодаря команде
seconds = 0.
Мы пока можем запустить
наш проект на эмуляторе.
Чтобы посмотреть на разметку.
У нас все кнопки выстроились в один ряд.
Это значит, что мы в LinearLayout
не поставили ориентацию.
И также мы выровняем
наши кнопки по центру.
С помощью атрибута gravity.
Снова запустим проект.
Отлично, все кнопки у нас
выстроились по центру.
При желании вы можете изменить им
отступы, размеры.
Даже можно поменять цвет фона.
В следующей части мы напишем код
для отсчитывания времени,
создадим формат для отображения времени.
Также используем новый объект handler
для планирования выполнения кода.
И сохраним секунды при выходе
или повороте экрана приложения.
В последнем уроке лекции
про жизненный цикл активности
мы продолжим создание приложения.
В прошлой части мы подготовили разметку
и создали методы для кнопок.
Теперь наша задача состоит в том, чтобы
написать код для отсчитывания времени.
Создать формат для отображения времени.
Использовать объект Handler
для планирования выполнения кода.
И сохранять секунды при выходе
или повороте экрана приложения.
Приступим.
Перейдем на Activity.
Настала очередь создания метода runTimer,
который получает ссылку на надпись
в макете, форматирует содержимое
переменной seconds в часы, минуты
и секунды, а затем выводит результаты
в надписи TextView.
Если переменной running
присвоено значение true,
то переменная seconds будет увеличиваться
и не будет прекращать отсчет.
Метод runTimer мы можем создать в конце.
Сначала мы получим ссылку на текст,
в котором у нас будет выводиться время.
Идентификатор у него будет time_view.
Далее мы будем использовать Handler
для передачи кода на выполнение.
Сначала его создадим.
Дадим ему переменную.
И создадим объект Handler.
Объекты Handler позволяют
планировать выполнение кода.
Также класс может использоваться
для передачи кода, который должен
выполняться в другом программном потоке.
В нашем примере Handler будет
использоваться для планирования
выполнения кода секундомера
каждую секунду.
Чтобы использовать класс Handler, мы
упакуем код, который нужно запланировать,
в объект Runnable.
После чего используем методы post
и postDelayed класса Handler
для определения того, когда должен
выполняться код.
У нас будет здесь new.
Вызов метода post передачи нового объекта
Runnable обеспечивает выполнение
без задержки, так что код в Runnable
будет выполнен практически немедленно.
Метод run объекта Runnable содержит код,
который требуется выполнить.
В нашем случае это код обновления надписи.
Мы здесь напишем самый обычный код Java
для отсчета времени.
Далее мы будем форматировать время
в формат: часы, минуты и секунды.
Если переменная running истинна, то будем
увеличивать переменную seconds на единицу.
И далее нам потребуется запланировать
повторное выполнение кода
с задержкой в одну секунду.
С помощью метода postDelayed.
В этом классе на 1000 миллисекунд.
Что равнозначно одной секунде.
Мы закроем наш метод.
И нам еще понадобится еще одна
фигурная скобка.
Чтобы обновить секундомер, мы будем
многократно планировать выполнение кода
с использованием Handler.
При этом каждый раз будет назначаться
задержка продолжительностью в 1 секунду.
Каждое выполнение кода сопровождается
увеличением переменной seconds
и обновлением записи.
Для запуска работы runTimer
объявим его в методе onCreate.
На данном этапе приложение можно запустить
и проверить работу секундомера.
Нажмем на кнопку Stop.
И обнулим.
Снова нажмем на кнопку Start.
И повернем экран.
Как мы видим, при повороте экрана
данные обнуляются.
Основная причина обновления данных
при смене ориентации заключается в том,
что при повороте экрана ориентация
и размер меняются — следовательно, система
уничтожает активность вместе с нашим
запущенным секундомером.
А точнее, с его данными,
которые использовались методом runTimer.
Теперь onCreate выполняется заново
и снова вызывает метод runTimer,
чтобы начать отсчет заново.
То же самое: мы снова повернем экран.
И, как мы видим, значения
у нас обнуляются.
Более правильный способ
обработки изменений конфигурации,
который вы будете применять чаще всего, —
это сохранение текущего состояния
активности и ее последующее создание
в методе onCreate.
Чтобы сохранить текущее состояние
активности, необходимо реализовать метод
onSaveInstanceState.
Метод onSaveInstanceState вызывается
перед уничтожением активности.
Это означает, что вам представится
возможность сохранить все значения,
которые нужно сохранить, прежде чем
они будут безвозвратно потеряны.
Метод onSaveInstanceState получает
один параметр типа bundle.
Тип bundle позволяет объединить
разные типы данных в один объект.
То есть здесь у нас хранится данный тип
bundle, и нам потребуется создать метод
onSaveInstanceState.
Здесь также у нас мы пока удалим.
Здесь нам потребуется savedInstanceState.
Метод onCreate получает параметр bundle.
Таким образом, если вы добавите значение
переменных running и seconds в bundle,
метод onCreate сможет восстановить их
при повторном создании активности.
Для включения пар имени-значения в bundle
используется метод bundle, который имеет
следующую форму: bundle.put,
имя name и значение value.
Где bundle — это имя объекта bundle,
put — это тип сохраняемого значения,
а name и value — это имя и значение
сохраняемых данных.
Например, для включения в bundle
значения seconds типа int
используется следующая команда.
PutInt, имя seconds и значение seconds.
И также мы добавим для значения running.
У него будет тип сохраняемого значения —
boolean, имя running и значение running.
В bundle можно сохранить сколько угодно
пар данных имя-значение.
Вот так выглядит полная реализация метода
onSaveInstanceState в нашем приложении.
И после того как значения переменных у нас
были сохранены в bundle, их можно будет
использовать в методе onCreate.
В bundle можно сохранить
сколько угодно пар данных.
После того как значения переменных были
сохранены в bundle, их можно будет
использовать в методе onCreate.
Для этого мы добавим условие if.
Если меняется значение.
Здесь мы получаем наши значения,
чтобы сохранить их в bundle.
Теперь мы запустим проект,
чтобы проверить, сохраняет ли bundle
наши значения
при повороте экрана.
Нажмем на кнопку Start.
И поворачиваем экран.
Как мы видим, отсчет продолжается.
Приложение сохраняет свое состояние
и продолжает считать время.
Адаптеры и спискиСегодня мы поговорим об адаптерах
и списках.
Узнаем, что представляет собой
сам адаптер, каких видов он бывает,
узнаем о его назначении и представлении.
Познакомимся с ListView,
узнаем, как его применять,
а также обратим внимание на его минусы.
Для начала нам следует обратить внимание
на одну из классификаций активити
в приложении.
Бывают активити верхнего уровня,
активити категорий
и активити детализации и редактирования.
Активити верхнего уровня
представляют собой операции,
наиболее важные для пользователя,
и предоставляют простые средства
для навигации к ним.
Активити категорий выводят данные,
принадлежащие конкретной категории,
часто в виде списка.
И активити детализации и редактирования
выводят подробную информацию
по конкретной записи.
Предоставляют пользователю возможность
редактирования существующих записей
или ввода новых записей.
Классификация активити.
Например, активити верхнего уровня
будет выводить список всех команд.
Активити категорий отображает
список курсов и специальностей.
И последняя активити выводит
уже более подробную информацию
по курсу или специальности.
Мы можем подробнее рассмотреть
данную классификацию на примере
приложения, которое построим
в следующих частях лекции.
Что мы будем делать?
В этом уроке мы создадим
простейшее приложение
со списковым представлением ListView.
Создадим адаптер, который будет связывать
данные с элементами списка.
Следующим после создания первого
приложения мы научимся работать
со списковыми представлениями,
получать данные из класса,
поработаем с классом ListView
и увидим на примере работу активити
верхнего уровня, категорий и детализации.
Итак, у нас есть набор объектов
и есть компонент View.
Назначение адаптера заключается в том,
чтобы предоставить дочерние виды
для контейнера.
Адаптер берет данные и метаданные
определенного контейнера
и строит каждый дочерний вид.
Например, мы формируем пункты списка
(массив строк) и передаем его списку
ListView с помощью адаптера.
В Android часто используются адаптеры.
Если говорить в общих чертах,
то адаптеры упрощают связывание данных
с элементами управления.
Адаптеры используются при работе
с элементами, которые дополняют
AdapterView: элементами ListView,
GridView, Spinner и Gallery.
Сам адаптер дополняет ViewGroup.
В приложениях очень часто используется
список на основе ListView.
Сам список состоит из множества элементов
TextView, которые идут друг за другом.
Но их количество будет зависеть от того,
что мы хотим отобразить.
Если нам нужны дни недели,
то достаточно 7 элементов,
если месяцы, то уже 12.
Ну, а если нам нужен список работников
большого предприятия,
то счет пойдет на сотни.
Нам нужно составить данные,
например, в виде массива,
и передать его списку.
То есть адаптер этим и занимается.
Он берет по порядку предоставленные данные
и размещает их в списке по порядку.
При этом адаптер сразу создает
нужный компонент TextView
и помещает в него приготовленный текст.
Данные могут находиться не только
в массиве, но и в базе данных.
Для такого случая используется
другой адаптер.
Существуют также уже готовые адаптеры.
На самые распространенные случаи.
Их предназначение можно определить
по именам.
Все адаптеры, содержащиеся в Android,
дополняют базовый адаптер BaseAdapter.
Вот список готовых адаптеров.
Но это не весь список,
но весь список можно посмотреть
в документации Android.
ArrayAdapter предназначен
для работы с ListView.
Данные представлены в виде массива,
который размещается в отдельных
элементах TextView.
CursorAdapter предназначен
для работы с ListView.
Предоставляет данные для списка
через курсор, который должен иметь
колонку с именем id.
SimpleAdapter — это адаптер, позволяющий
заполнить данными список
более сложной структуры — например,
два текста в одной строке списка.
ResourceCursorAdapter.
Это адаптер, который дополняет
CursorAdapter и может создавать
виды из ресурсов.
И SimpleCursorAdapter дополняет
ResourceCursorAdapter,
создает компоненты TextView, ImageView
из столбцов, содержащихся в курсоре.
Компоненты определяются в ресурсах.
Мы будем работать с ArrayAdapter.
Класс ArrayAdapter представляет
собой простейший адаптер,
который связывает массив данных
с набором элементов TextView.
Из которых, к примеру,
может состоять ListView.
То есть в данном случае источником данных
выступает массив объектов.
ArrayAdapter вызывает у каждого объекта
метод toString для приведения
к строковому виду
и полученную строку устанавливает
в элемент TextView.
Вначале получаем по id элемент ListView
и затем создаем для него адаптер.
Для создания адаптера используется
следующий конструктор.
ArrayAdapter<String>
(this, R.layout.list_item,
balticCountries).
То есть this здесь является объектом
класса Context.
Android.R.layout.simple_list_item —
это стандартная разметка списка.
И balticCountries — это массив данных.
Элемент ListView представляет собой
прокручиваемый список элементов.
Был когда-то очень популярен на мобильных
устройствах из-за своего удобства.
Компонент ListView более сложен
в применении по сравнению с TextView
и другими простыми элементами.
Работа со списком состоит из двух частей.
Сначала мы добавляем на форму
сам ListView, а затем заполняем
его элементами списка.
При работе со списками мы имеем дело
с тремя компонентами.
Во-первых, это сам элемент списков,
который отображает данные.
Во-вторых, это источник данных (массив,
объект ArrayList, база данных и т.д.),
в котором находятся отображаемые данные.
И в-третьих, это адаптеры — специальные
компоненты, которые связывают
источник данных с элементом списка.
Рассмотрим связь элемента ListView
с источником данных с помощью одного
из таких адаптеров класса ArrayAdapter.
Для добавления спискового представления
в макет используется элемент ListView.
Чтобы заполнить списковое
представление данными,
используйте атрибут android:entries
и присвойте ему массив строк.
Строки из массива будут отображаться
в списковом представлении в виде
набора надписей TextView.
Например, добавление в макет спискового
представления, которое получает значения
из массива строк options.
Массив определяется точно так же,
как это уже делалось ранее.
Данные включаются в массив strings.
Чтобы пункты списка реагировали на щелчки,
следует реализовать слушателя событий.
Слушатель событий отслеживает события,
происходящие в приложении.
Например, щелчки на представлениях,
потерю и получение ими фокуса или
нажатие физической клавиши на устройстве.
Реализация слушателя событий позволит вам
обнаруживать конкретные действия
пользователя (скажем, щелчки на вариантах
списка) и реагировать на них.
Слушатель OnItemClickListener отслеживает
щелчки на вариантах списка,
а метод onItemClick определяет
активности на щелчок.
По параметрам, передаваемым методу
OnClick, можно получить дополнительную
информацию о событии.
Например, получить ссылку на вариант
из списка, узнать его позицию в списковом
представлении (начиная с нуля)
и идентификатор записи
используемого набора данных.
OnItemClickListener.
Является вложенным классом по отношению
к классу AdapterView ListView.
Для упрощения доступа к элементам списка
используется класс ListActivity.
ListActivity представляет собой класс,
унаследованный от активити и разработанный
специально для работы со списками.
ListActivity специализируется
на работе со списком.
Использование списковой активности
ListActivity для вывода категорий данных
обладает парой преимуществ.
Вам не придется строить макет
самостоятельно.
Списковая активность определяет
свой макет на программном уровне.
Также вам не нужно будет реализовывать
собственного слушателя.
Класс ListActivity уже реализует слушателя
событий, который обнаруживает щелчки
на вариантах спискового представления.
И минусами ListView являются...
Тяжело реализовываемые анимации.
Также у них нет поддержки
просмотра изображений.
И он гораздо менее гибкий,
чем необходимо.
Также с каждым днем ListView устаревает.
И поэтому Google придумал RecyclerView.
RecyclerView — это более продвинутая
и гибкая версия ListView.
RecyclerView является более
гибким элементом управления
обработкой данных списка,
который следует за шаблонами
делегирования проблем и оставляет
для себя только одну задачу —
переработку элементов.
Но об этом мы поговорим чуть позже.
Создание простейшего спискового приложенияВ этом уроке мы создадим
простейшее приложение
со списковым представлением ListView.
Создадим адаптер, который будет
связывать данные с элементами списка.
Назовем наше приложение Array List App.
Далее у нас все остается по умолчанию.
Кликаем на кнопку Finish.
Перейдем на вкладку activity_main.
Здесь мы удалим ConstraintLayout
и заменим его на ListView.
Удалим TextView.
И удалим лишний код.
Также дадим ему идентификатор.
FoodList.
В элементе ListView у нас не будет ничего,
кроме объявления идентификатора,
ширины и высоты.
Больше он не будет ничего определять.
Перейдем на вкладку MainActivity.
И свяжем ListView через ArrayAdapter
с некоторыми данными.
Нам требуется создать набор данных,
которые мы будем отображать
в нашем списке.
Это у нас будет массив строк.
Назовем его «еда».
И здесь мы перечислим виды фастфуда.
Первый у нас будет гамбургер.
Далее пицца.
Картошка фри.
Чизбургер.
Твистер можно добавить еще.
И пепси.
Можно даже назвать это junkFood.
Что означает «вредная еда».
Далее нам нужно будет создать...
Элемент ListView.
И получим его по идентификатору.
FoodList.
Далее мы создадим адаптер.
ArrayAdapter.
В качестве параметра у нас будет string.
Дадим ему переменную.
И здесь мы укажем...
Где должен запускаться наш адаптер.
Укажем ему системную разметку.
Здесь можно перейти на следующую строчку.
В данном случае мы выберем классический
вывод текста.
И здесь нам потребуется junkFood.
Тот список, который мы будем выводить.
И здесь нам нужно установить адаптер.
Далее теперь мы можем
запустить наш проект.
Чтобы посмотреть на результат.
Как мы видим, у нас отобразился список
введенной нами еды.
И также мы можем изменить
системную разметку.
Здесь у нас классический список.
Мы можем его поменять на
какой-нибудь другой.
Из списка того, что нам предлагается.
Например...
Есть, например, browser.
Возможно, они будут.
Либо preference_catagory.
Посмотрим, что он из себя представляет.
У нас изменился список.
Точнее, его стиль отображения.
На этом разработка приложения окончена.
В следующем уроке мы создадим приложение
с тремя окнами активности,
в котором мы научимся работать более
углубленно со списковыми представлениями
и активити верхнего уровня,
категорий и детализации.
Создание приложения "Спорт"В данной части нашего урока мы начнем
создание нашего приложения, которое
будет содержать в себе три активити.
Начнем мы с создания класса, в котором
у нас будут храниться данные.
Создадим проект.
Назовем его Sport App.
Далее мы введем все по умолчанию.
В нашем проекте будут
использоваться картинки.
Наше приложение называется Sport App.
То есть у нас будет выводиться список
спортов и в новой активности у нас будет
выводиться более детальное описание,
что из себя представляет данный спорт.
Так, закроем.
Описания мы будем брать из файла paste.
Здесь у нас названия видов спорта
и их описания.
Мы научимся добавлять файлы в наш проект.
В данном случае у нас будут картинки.
У нас построился проект.
Мы создаем новый класс.
Будем с ним работать.
Но для начала мы переместим
наши картинки.
Перейдем в полную структуру проекта.
Откроем папку res.
И можно добавить картинки двумя способами.
Можно навести на данную папку.
Нам нужно все картинки переместить
в папку drawable.
Так, отлично, первая картинка
у нас переместилась.
Либо мы можем сделать так.
Скопировать их все.
Нажать на кнопку «копировать».
И здесь вставить с помощью кнопки paste.
Далее мы создадим класс Sport.
В котором у нас будут храниться
картинки и само описание.
Видов спорта.
Мы создали класс.
Класс Sport у нас является обычным
файлом класса Java, из которого
активити будет получать данные.
Класс у нас будет определять
массив из трех объектов,
представляющий виды спорта.
Каждый объект будет состоять
из названия, описания и идентификатора
ресурса изображения.
Здесь мы создаем объекты.
Из полей имени, описания и идентификатора
ресурса изображения.
Объявим их.
Name — это у нас будет название спорта.
Description — у нас будет описание спорта.
ImageResourceId — у нас, соответственно,
будет идентификатор ресурса картинки.
Мы добавили в проект картинки.
Далее нам потребуется...
Их объявить в нашем классе,
чтобы к ним получить доступ из активити.
Для этого мы создадим метод Sport.
С переменной sports.
И здесь у нас будет один объект.
С которым мы будем работать.
Здесь в первом поле у нас будет
название вида спорта.
Далее его описание.
И ссылка на изображение.
Создадим шаблон.
Всего у нас будет 10 видов спорта.
С помощью сочетания клавиш Ctrl + D
можно будет скопировать таким образом.
Недостающие объекты.
У нас есть файл paste.
Начнем вставку.
Описаний.
Здесь можно перейти,
сделать перевод на следующую строчку.
И ресурс изображения у нас будет football.
Так сделаем и для остальных видов списка.
Далее нам потребуется создать
get методы для доступа
к приватным переменным из внешнего класса.
Первый у нас — название.
Далее описание.
И картинки.
В первом также нужно в качестве
строкового представления Sport
представить название вида спорта.
Здесь нам надо возвратить объект name.
В следующей части нашего урока
мы создадим активити с главным экраном,
а именно активити верхнего уровня.
И настроим вторую активити —
активити категорий.
В новой части урока мы продолжим создание
приложения Sport.
Добавим две активити.
Первая будет реализовывать переход
на активити категорий,
а вторая будет отображать
список видов спорта, которые
в следующей части нашего урока
будут открываться в новом окне
с детальным описанием.
Мы перейдем на вкладку activity_main.
Здесь нам потребуется создать макет
для главной активити экрана.
Для этого нам нужно в файле макета
activity_main добавить компоненты
ImageView и ListView.
Для этого мы поменяем разметку макета.
На LinearLayout.
Удалим лишний код также.
Удалим TextView.
Поскольку он нам не нужен.
Добавим обязательные атрибуты
для LinearLayout.
Выровняем по центру.
Наши дочерние элементы.
И добавим...
Элемент ImageView.
То есть здесь у нас будет логотип.
И также мы здесь назначим ему адрес.
Ссылку на изображение, которое
находится в drawable.
И это у нас будет drawable/logo.
И также дадим ему идентификатор.
С таким же названием.
Создадим элемент ListView.
Он у нас будет растягиваться
по ширине экрана.
Так как у нас ListView не вложен,
мы можем закрыть его.
Дадим ему отступ сверху.
25 dp.
Значение 25 dp.
Дадим ему идентификатор.
Назовем его list_item.
И также дадим ссылку на массив Array.
Текстом мы его заполним сейчас.
Перейдем в файл strings.
И здесь создадим список для ListView.
Мы уже такое делали для спиннера.
Назовем его option.
Создадим item'ы.
Скопируем.
Первый у нас будет, как на картинке.
В презентации
первый у нас будет «Спорт».
Далее «Магазины».
И «Контакты».
Мы отредактировали файл strings.xml,
добавили к нему массив строк.
Далее нам потребуется перейти
в MainActivity.
Здесь мы будем проводить обработку
щелчков элементов в ListView.
Чтобы пункты списка реагировали на щелчки.
Следует реализовать слушателя событий.
Чтобы варианты списка реагировали
на щелчки, мы создадим объект
OnItemClickListener
и реализуем его метод onItemClick.
Слушатель OnItemClickListener будет
отслеживать щелчки на вариантах списка.
А метод onItemClick будет определять
реакцию активити на щелчок.
Добавление слушателя к списковому
представлению крайне важно.
Именно эта операция обеспечивает
получение слушателем оповещений о том,
что пользователь щелкнул
на списковом представлении.
Если этого не сделать, варианты
из спискового представления
не будут реагировать на щелчки.
Итак, вы знаете все необходимое для того,
чтобы научить списковые представления
MainActivity.java реагировать на щелчки.
Мы это уже делали на прошлых занятиях.
Создадим AdapterView.
С вложенным классом OnItemClickListener.
Дадим ему переменную OnItemClickListener.
И у нас появится вот такой конструктор.
Здесь мы создадим...
В зависимости от позиции.
Здесь также у нас надо будет
выполнять на position.
То есть в зависимости от того, на каком
пункте пользователь щелкнет,
у нас откроется новая активити.
Для этого мы реализуем переход Intent.
На новую активность.
Но мы ее реализуем только для первого
списка под именем «Спорт».
Он у нас будет первым в списке
и только он будет у нас работать.
При желании вы можете наделить
функционалом и другие кнопки.
Мы говорим, чтобы здесь работал у нас
обработчик событий в данной активити.
Мы создадим новую активность,
которая у нас будет CategorySportActivity.
И запустим.
Нашу активность.
Далее нам требуется назначить
спискового слушателя.
Дать ему переменную.
Идентификатор у него list_item.
И также нам потребуется для ListView
установить setItemClickListener.
И переменную нашего адаптера
itemClickListener.
Мы создадим новую активность
CategorySportActivity.
Она у нас будет наследоваться
от класса ListActivity.
И будет пустой шаблон активити.
Без генерации файла разметки.
CategoryActivity будет расширяться
не от AppCompatActivity,
а от ListActivity.
Вскоре мы напишем код для этого метода.
Так как класс представляет именно
списковую активность, он должен
расширять класс ListActivity
вместо класса AppCompat.
Другое отличие заключается в том,
что вам не нужно назначать макет,
используемый списковой активностью,
вызовом setContentView.
Дело в том, что списковые активности
определяют свои макеты самостоятельно,
поэтому вам это делать не придется.
Списковая активность сделает все за вас.
Чтобы использовать адаптер массива,
следует инициализировать его
и присоединить к списковому представлению.
При инициализации адаптера массива
сначала мы указываем тип данных массива.
Который мы хотим связать
со списковым представлением.
Затем адаптеру передаются три параметра.
Это контекст.
Ресурс макета, который определяет,
как должен отображаться
каждый элемент из массива.
И сам массив.
Далее мы здесь напишем вид разметки.
Который будет отображать список.
Названий видов спорта.
Они будут брать данные
из нашего класса Sport.
Дадим переменную для ArrayAdapter.
И здесь мы представим...
Стиль списков.
Как мы делали на первом занятии
при создании простейшего приложения
с использованием списковых представлений.
Здесь мы выберем классический.
Который будет брать данные
из класса Sports.
Установим адаптер.
Для listSport, не для адаптера.
Пока мы запустим наш проект.
Чтобы посмотреть, что у нас получилось.
И далее продолжим работу над ним.
Итак, у нас здесь отображается
первая активность —
главная активити.
Мы кликаем на «Спорт».
И у нас открывается список
со всеми нашими видами спорта.
Далее нам потребуется создать
новую активити.
Мы назовем ее SportActivity.
Для того чтобы при нажатии
на один из видов спорта
у нас открывалось новое окно,
где будет отображено название данного
вида спорта, его описание и картинка.
Перейдем мы в файл снова
CategorySportActivity и напишем код
для того, чтобы открывалась
новая активити.
Для этого мы создадим метод
onListItemClick.
Удалим лишний код.
И здесь мы пишем Intent.
Для открытия новой активити.
У нас будет открываться
CategorySportActivity.
В этом классе.
Новая активность у нас будет
называться SportActivity.
И чтобы передавать через нее данные,
мы снова воспользуемся константой Extra.
Также запустим.
Нашу активити.
Далее мы добавим в проект новую активити.
Под названием SportActivity.
Она будет с макетом.
Добавим SportActivity переменную
EXTRA_SPORT, чтобы пока запустить проект
и посмотреть на полученный результат.
То есть проверить,
запускается ли активность при щелчке.
На какой-нибудь вид спорта.
Мы создаем переменную EXTRA_SPORT.
И дадим ей значение sportId.
Запустим наш проект.
Чтобы проверить, открывается ли у нас
при щелчке на вид спорта новая активность.
Кликаем на кнопку «Спорт».
У нас открывается CategorySportActivity.
Нажмем на «Регби», например.
И у нас открывается новая пустая активити.
В следующей, заключительной части
мы достроим наше приложение.
Нам осталось создать разметку
для отображения этой активности.
Чтобы при нажатии на список у нас
открывалась нужная активность.
В заключительной части нашего урока
мы закончим создание нашего проекта
и запустим его на эмуляторе.
Мы создадим разметку для SportActivity.
Здесь мы снова поменяем ConstraintLayout
на LinearLayout.
Удалим лишний код.
Дадим ему обязательный атрибут
ориентации.
И выровняем наши дочерние
элементы по центру.
Нам потребуется создать одну картинку
и два элемента TextView.
Картинка у нас будет отображать...
Вид спорта.
Мы дадим ему идентификатор.
Image.
И отступы со всех сторон.
В значении 15 dp.
Также мы создадим два TextView,
которые у нас будут отображать:
первый — имя (точнее, название) спорта.
Идентификатор у него будет name.
И также мы ему дадим...
Отступ со всех сторон 15 dp.
И последний у нас будет тоже TextView.
Который будет содержать в себе
описания видов спорта.
Мы ему также дадим отступ со всех сторон.
В значении 15 dp.
И дадим ему идентификатор.
С именем description.
Теперь перейдем в активити SportActivity.
Здесь у нас уже определена константа.
Как было показано ранее,
когда активити категорий используется
для запуска активити детализации,
варианты активити категорий
реагируют на щелчки.
При выборе варианта создается интент
для запуска активити детализации.
У нас идентификатор варианта, выбранного
пользователем, передается в составе
дополнительной информации интента.
При запуске активити детализации читает
из интента дополнительную информацию
и использует ее для заполнения
своих представлений.
В нашем случае данные из интента,
запустившего SportActivity, используются
для получения подробной информации
о спорте, выбранном пользователем.
Создавая категории SportActivity,
мы включили идентификатор спорта,
выбранного пользователем,
как дополнительную информацию в интент.
Ему присваивается метка SportActivity
EXTRA_SPORT, которую мы определили
как константу в SportActivity.
И назвали ее EXTRA_SPORT.
И дали ему значение sportId.
Если интент содержит дополнительную
информацию, для чтения такой информации
используются методы getIntent.
Следующий код у нас будет читать
значения EXTRA_SPORT из интента,
запустившего SportActivity.
То есть мы напишем код для чтения
данной константы.
Здесь мы получим список.
Из класса Sport.
Далее нам потребуется получить картинки.
Для этой картинки мы будем использовать
ссылку из класса Sport.
И также описание этой картинки мы
будем брать из названия вида спорта.
Далее нам потребуется
получить ссылки на TextView.
Установим текст name.
И получим второй TextView, в котором
у нас будет храниться описание.
Также получим для него текст
из класса Sport.
У нас все готово,
мы запустим наше приложение.
У нас открылась главная активность,
переходим на вкладку «Спорт».
Выбираем, например, «Волейбол».
И, как мы видим, у нас все
корректно отобразилось,
появилась картинка с названием
и описанием волейбола.
Как мы видим, у нас все работает.
При желании вы можете отредактировать
разметку, добавить новые активити
или сменить тематику приложения
со спорта, например, на страны.
В итоге мы научились работать
со списковыми представлениями,
получать данные из класса.
Также мы поработали с ListActivity
и увидели на примере работу активити
верхнего уровня, категорий и детализации.
Основы RecyclerViewЭлемент RecyclerView является
усовершенствованным вариантом ListView,
но не является его родственником
и относится к семейству ViewGroup.
Он часто используется как замена ListView,
но его возможности намного шире.
Элемент находится в разделе AppCompat.
Элемент RecyclerView предназначен
для оптимизации работы со списками
и во многом позволяет повысить
производительность по сравнению
со стандартным ListView.
Он входит в состав библиотеки
совместимости, поэтому его можно
использовать и для старых устройств,
а не только для Android 5.0 и выше.
Стоит отметить, что вначале это был
сырой продукт, потом его доработали,
заменили несколько устаревших методов,
и на данном этапе можно считать,
что он стал полноценной заменой
списка ListView.
Поэтому RecyclerView — это подходящее
представление для использования,
когда у вас есть несколько элементов
одного типа (например, контакты,
аудиофайлы, видео, картинки и т.п.).
При прокрутке вверх и вниз
вступают в действие повторная утилизация
и повторное использование.
Как только пользователь прокручивает
видимый в данный момент элемент,
представление этого элемента может быть
переработано и повторно использовано
с помощью RecyclerView.
Это иллюстрирует скриншот
примера приложения.
Слева находится пример приложения
после первоначального запуска.
Когда вы просматриваете экран
с элементами текста, изображения,
некоторые элементы становятся
пригодными для повторной переработки.
Красная область на правом скриншоте,
например, выделяет два невидимых объекта.
Теперь переработчик Recycler может
перевести эти элементы в список,
который будет использоваться повторно,
если необходимо новое представление.
Утилизация и повторное использование
элементов — это очень полезный подход.
Это экономит ресурсы процессов Android,
поскольку вам не нужно постоянно
пересоздавать новые представления,
и это экономит память, так как не содержит
много невидимых элементов.
В то время как с ListView у нас была
жесткая связь, Google теперь использует
подход, в котором сам RecyclerView вообще
не интересуется визуальными эффектами.
Он не заботится о размещении
элементов в нужном месте.
Он не заботится о разделении каких-либо
элементов и внешнем виде каждого
отдельного элемента.
Все, что RecyclerView делает, — это
утилизация и переиспользование элементов.
Отсюда и название Recycler.
Все, что связано с макетом,
рисунком и т.д. — это все связано
с представлением набора данных.
Делегируется подключаемым классам.
Это делает новый RecyclerView
чрезвычайно гибким.
Вам нужен другой макет?
Тогда подключите другой LayoutManager.
Вы хотите разные анимации?
Тогда вставьте ItemAnimator.
И так далее.
Вот список наиболее важных классов,
которые RecyclerView использует
для представления данных.
Все эти классы являются внутренними
классами RecyclerView.
Adapter оборачивает набор данных
и создает представления
для отдельных элементов.
ViewHolder удерживает все зависимые
представления, которые зависят
от данных текущего элемента.
LayoutManager помещает объекты
в пределах доступной области.
ItemDecoration определяет отступы
вокруг или сверху элемента.
ItemAnimator — анимации элементов
во время добавления, удаления
или переупорядочивания.
Как уже говорилось, LayoutManager помещает
объекты в пределах доступной области.
Он полностью отвечает за расположение
элементов на макете.
Из-за этого нам не требуется задавать
какой-либо родительский макет.
LayoutManager отвечает за размер
и позиционирование элементов RecyclerView.
А также за определение того, когда следует
перерабатывать элементы, которые больше
не видны пользователю.
Изменяя LayoutManager,
RecyclerView может использовать
для реализации стандартного списка
прокрутки по вертикали, горизонтали,
в виде сетки и используя сложное
представление.
То есть в нем динамически будут
отображаться элементы, которые
подстраиваются под произвольный размер.
Адаптеры выполняют две роли.
Они обеспечивают доступ к базовому набору
данных и отвечают за создание правильной
компоновки для отдельных элементов.
Адаптеры всегда были частью Android
и использовались во многих местах.
Например, в ListView, Spinner.
Эти классы наследуются от AdapterView.
Для RecyclerView Google решил заменить
старый интерфейс адаптера новым базовым
классом RecyclerView.Adapter.
Поскольку RecyclerView.Adapter является
абстрактным, вам придется реализовать
эти три метода.
ViewHolder в перечисленных методах
является параметром общего типа.
Вы указываете конкретный тип, который
следует использовать при подклассификации
RecyclerView.Adapter.
ViewHolders — это в основном кеши
элементов View.
Объект ViewHolder хранит каждый
из представлений компонентов
внутри поля тега макета.
Поэтому вы можете сразу же получить к ним
доступ, не пересматривая их повторно.
Единственное, что характерно для подкласса
RecyclerView.ViewHolder, это то, что вы
всегда можете получить доступ к корневому
представлению вашего ViewHolder.
С помощью ItemDecoration вы можете
добавить отступ каждому элементу
или изменить элемент, чтобы элементы были
отделены друг от друга, выделены
или как-то разрисованы.
Алгоритм же построения RecyclerView
мы рассмотрим на следующем уроке.
Построение RecyclerViewМы поэтапно рассмотрим алгоритм
построения RecyclerView
на примере нашего приложения,
которое построим на будущих занятиях.
Мы создадим приложение с прокручиваемым
списком, используя RecyclerView.
Также мы научимся подключать библиотеки,
создавать разрешение для подключения
к сети Интернет, а также получать
по ссылке изображения и выводить их
на экран с текстом, то есть научимся
динамически подгружать данные.
По умолчанию функциональность RecyclerView
недоступна в Android Studio,
поэтому ее надо вручную добавлять.
Для этого в файле build.gradle, который
расположен в проекте внутри папки app
и который определяет конфигурацию
модуля app, добавим данную библиотеку.
Затем нам надо синхронизировать проект,
чтобы библиотека подгрузилась.
Как в ListView, нам потребуется создать
макет для отображения элементов,
чтобы к ним можно было обращаться
по идентификатору.
В главной активити требуется создать
элемент RecyclerView.
Обратите внимание, что он берется
из библиотеки поддержки,
а не из готовых элементов,
как кнопки Button или списки ListView.
Создание списков объектов данных
точно такое же, как мы его создавали
в прошлом приложении.
В данном случае мы создаем класс
GrumpyCat, который будет содержать
поля для хранения изображений котов
и их имена.
Как в случае с ListView, для вывода
сложных объектов RecyclerView необходимо
определить свой адаптер.
Поэтому добавим новый класс
GrumpyCatAdapter и внутри него
создадим объект ViewHolder.
Чтобы создать ViewHolder, мы наследуем его
от RecyclerView.ViewHolder, и в нем мы
инициализируем наши элементы,
а именно изображения и текст.
Далее мы сохраняем переменную cats
класса GrumpyCat и создаем
для переменной конструктор класса.
GetItemCount возвращает общее количество
элементов в списке.
RecyclerView.Adapter определяет метод
onCreateViewHolder, который возвращает
объект ViewHolder, хранящий данные
по одному объекту из класса GrumpyCat.
Метод onBindViewHolder выполняет привязку
объекта ViewHolder к объекту GrumpyCat
по определенной позиции.
Здесь также есть строка с элементом
Picasso — это библиотека изображений,
с которой мы познакомимся
при построении приложения.
С помощью метода initRecyclerView
устанавливается набор начальных данных.
В данном случае имеется в виду,
что в папке res/drawable находится
ряд ресурсов изображений
для объектов GrumpyCat.
Как и в случае с выводом списка через
ListView, здесь сначала получаем элемент
RecyclerView, затем мы создаем адаптер
и устанавливаем адаптер для RecyclerView.
И последний этап построения приложения —
это установка LayoutManager
для RecyclerView.
Как мы уже говорили, LayoutManager
отвечает за позиционирование
view-элементов в RecyclerView,
а также за определение того, когда
следует переиспользовать view-элементы,
которые больше не видны пользователю.
В следующей части мы начнем создавать
приложение с использованием RecyclerView.
Создание приложения "Grumpy Cat"Как говорилось в прошлой части лекции,
мы создадим приложение
с использованием RecyclerView.
В данном уроке мы настроим разметку,
подключим библиотеку в файле build.gradle
и создадим класс с объектами
из полей имени и изображений.
Мы будем придерживаться алгоритма
построения, который рассматривали
на лекции.
Создадим новый проект.
И назовем его Grumpy Cat.
Мы впервые подключим библиотеку.
И не одну, а две.
Для начала подключим мы одну
библиотеку с RecyclerView.
Рассмотрим способы, которыми
можно подключить библиотеки.
Библиотеку RecyclerView можно
добавить двумя способами.
Первый способ — это через build.gradle.
Мы откроем структуру проекта.
Тот файл, который работает с нашим
проектом, находится в модуле app.
Открываем build.gradle.
Здесь, как мы видим, подключена также
библиотека ConstraintLayout.
И после нее мы можем добавить
библиотеку RecyclerView.
Версии постоянно обновляются,
поэтому всегда нужно проверять,
какая актуальна на данный момент.
Попробуем синхронизировать.
То есть обязательно, если вы вносите
какие-то изменения в файл build.gradle,
надо синхронизировать его.
Итак, здесь он не знает версию такой
библиотеки и не высвечивает подсказку.
Как правило, версия всех библиотек
должна быть схожей с версией AppCompat.
Попробуем еще раз синхронизировать.
Отлично, у нас все синхронизировалось.
Также мы попробуем удалить все это
и добавим в проект вторым способом.
Для начала синхронизируем
изменения, которые мы внесли.
И второй способ добавления библиотеки
заключается в добавлении через
главное меню.
В пункте Project Structure
переходим в модуль app.
Здесь есть вкладка Dependencies.
Нажимая на данный плюсик, мы можем
выбрать, какую зависимость
нам требуется подключить.
Нам нужна библиотека.
Кликаем на Library Dependency.
И здесь мы ищем нашу библиотеку.
Она здесь есть, мы ее подключаем.
Отлично, у нас добавилась библиотека.
Теперь мы перейдем на вкладку
activity_main.
Здесь нам потребуется заменить
ConstraintLayout на RecyclerView.
Мы также можем ввести сразу название
RecyclerView, и он нам автоматически
его подгрузит.
Удалим TextView.
Также мы добавим для него идентификатор.
Назовем recycle_view.
Мы создали элемент для RecyclerView
так же, как мы создавали и для ListView.
Теперь нам требуется создать макет
для текста и изображения.
Мы создадим новую разметку
и наполним ее данными.
В данном случае это у нас будет
с левой стороны изображение кота,
а с правой стороны — его имя.
Разметку мы добавляем через папку layout.
Название разметки будет item_cat.
Здесь мы будем использовать
RelativeLayout.
Немного сместим наши элементы.
Для RelativeLayout мы назначим высоту
каждого нашего элемента: 158 dp.
Далее мы создадим изображение
для нашего кота.
У него будет фиксированная высота и ширина
в размере 150 dp.
Здесь также будет 150 dp.
Для ImageView мы также зададим
выравнивание с левой стороны.
Далее мы сделаем отступ со всех сторон
для картинки, в размере 4 dp.
Отцентрируем наше изображение.
И чтобы посмотреть, как оно все выглядит,
мы пока будем ссылаться на ресурс,
который у нас есть в нашем проекте.
Это, конечно, иконка,
которая находится в папке drawable.
Следом у нас будет идти имя кота.
Для него мы будем использовать TextView.
У него будет размер по содержимому.
Зададим ему выравнивание по вертикали.
Далее мы зададим ему отступ от нашей
картинки: 16 dp.
Дадим ему размер 30 sp,
чтобы текст был виден.
Здесь также нам надо показать в разметке,
откуда он должен начинаться.
То есть он должен начинаться
после нашего изображения.
Для данного изображения
мы дадим идентификатор.
Идентификатор под названием item_image.
И, соответственно, здесь он будет...
С левой стороны от картинки.
Далее мы назначим ему текст,
пока произвольный,
который будет потом меняться.
Построение разметки у нас закончено.
Теперь нам потребуется создать класс
для GrumpyCat.
Переходим мы в пакет java.
Создаем новый класс.
Так и назовем — GrumpyCat.
Далее мы создадим переменные
с именем и с картинкой.
Теперь создадим get-методы для доступа
к приватным статичным переменным
из внешнего класса.
В следующей части мы продолжим создание
приложения, а именно добавим адаптер
и подключим еще одну библиотеку
для работы с изображениями.
Продолжаем работу.
В данной части урока мы добавим адаптер
GrumpyCatAdapter.
Создадим адаптер.
Под именем GrumpyCatAdapter.
Он у нас будет наследоваться от класса
RecyclerView.Adapter.
Мы в него добавим список объектов данных,
содержащих поля для хранения
изображений котов и их имена.
Мы можем добавить методы
с помощью данной функции.
Но мы добавим это после.
Для начала нам потребуется сохранить
переменную cats класса GrumpyCat.
То есть мы подгружаем список наших котов.
Импортируем класс list.
Даем ему переменную.
И далее создаем для переменной
конструктор класса GrumpyCat.
GrumpyCatAdapter.
Теперь создадим класс, который будет у нас
брать ссылки изображений и текста.
Можно добавить его автоматически.
Но для начала мы добавим все вручную.
Первой у нас идет картинка.
Вставляем ее.
Следом за ней — текст.
И далее находим для них ссылки.
Метод super с переменной itemView.
И собственно сами картинки.
И ссылка на них.
Так, надо проверить,
какие имена им задавали.
Item_image.
Для TextView мы не задали имя,
сейчас мы зададим для него имя.
Мы можем дать ему имя item_name.
Перейдем сюда.
И для объекта name.
Определим для него ссылку.
У нас пока не подгружаются картинки
и текст, потому что мы для данного
адаптера еще не назначили разметку,
из которой он будет брать эти данные.
Сейчас нам нужно реализовать метод
getItemCount, который будет возвращать
элементы списка.
Адаптер теперь наследуется
от RecyclerView.AdapterView.
Это generic класс, параметром которого
является объект ViewHolder.
Чтобы создать ViewHolder, мы наследуем
все от его RecyclerView.ViewHolder,
и в нем, в этом классе, мы инициализируем
наши элементы, а именно
изображения и текст.
Сейчас мы вернемся к созданию списка
getItemCount.
Мы здесь будем возвращать элементы списка.
Теперь можно программно добавить
оставшиеся методы.
OnCreateViewHolder создает
новый объект ViewHolder всякий раз,
когда RecyclerView нуждается в этом.
В этот момент, когда создается разметка
строки списка, он передает объекту
ViewHolder, и каждый дочерний view-элемент
может быть найден здесь и сохранен.
Далее мы здесь назначим ему...
Из которой будем инициализировать
наши элементы.
Для этого у нас существует LayoutInflater.
В данном случае у нас viewGroup.
Мы поменяем на parent.
И здесь мы назначим разметку.
Нам он является родительским.
И также нам не нужно создание контейнера,
поэтому мы пишем false.
И возвращает у нас onCreateViewHolder
объект CatHolder.
Метод же onBideViewHolder
должен извлекать соответствующие данные
и использовать их для заполнения разметки.
В нем мы свяжем данные.
В данном случае у нас здесь есть
i — это позиция.
Мы так ее и переименуем.
И по этой позиции мы будем получать
картинку и текст.
Заполним метод onBideViewHolder.
Здесь у нас будет GrumpyCat.
Дадим ему название grumpyCat.
И получим позицию элемента.
Здесь на данном этапе нам потребуется
реализовать метод Picasso, который
будет, соответственно, подгружать
картинки в наш проект.
Библиотека Picasso является мощной
библиотекой загрузки и кеширования
изображений для Android.
Документация находится по этому адресу.
Используем данную библиотеку,
загружая картинки в Holder.
Но для начала нам требуется ее подключить
к библиотеке build.gradle.
Мы скопируем данный код
и вставим в наш файл build.gradle.
Синхронизируем наш проект.
Библиотека подгрузилась.
Переходим к GrumpyCatAdapter.
И в onBideViewHolder мы используем
библиотеку, загружая картинки
в данный Holder.
Библиотека у нас подгрузилась.
Допишем ей метод, который
указан в документации.
В данном случае get.
Далее нам потребуется загрузка
наших изображений.
Получение изображения.
И загрузка в Holder.
И здесь, так как у нас CatHolder,
мы напишем CatHolder и удалим лишнее.
Установим текст.
Отлично.
Нам все-таки нужен статичный Holder.
Мы переименовали переменные.
В следующей части мы закончим работу
над приложением, где будем уже работать
над инициализацией элемента RecyclerView,
и наконец запустим приложение,
а также узнаем, как получить разрешение
системы Android на подключение
к Интернету.
В этом заключительном уроке по построению
приложения с использованием RecyclerView
мы будем работать с MainActivity,
где добавим инициализацию для элемента
RecyclerView, установим для него линейную
разметку, используем адаптер и, наконец,
выведем список с изображением и текстом.
И перед запуском в файле AndroidManifest
напишем код, разрешающий приложению
подключиться к сети Интернет.
Перейдем в файл MainActivity.
Здесь нам потребуется добавить метод
initRecyclerView для установки
набора данных.
Далее мы создадим данный метод.
В нем нам нужно определить ссылку
на RecyclerView.
Создаем ссылку.
Мы разметку создавали еще в самом
начале нашего урока.
Вот она.
Также мы вспомним, какое имя
мы дали идентификатору.
По нему мы будем обращаться
через MainActivity.
Далее мы установим для него
линейную разметку.
Инициализируем данную разметку.
Теперь нам потребуется создать
и установить адаптер для RecyclerView.
Введем переменные.
Найдем наш адаптер.
И для него создадим метод generateCats.
В методе generateCats мы наполним
переменную grumpyCats данными,
а именно текстом и ссылкой на изображение
на хостинге imgur.
С которым мы поработаем чуть позже.
Мы создали данный метод.
И установим адаптер.
Далее таким же способом мы создадим.
Методы у нас будут статичны.
Теперь мы наполняем данными.
Но для начала обратимся
к классу GrumpyCat.
Дадим ему переменную.
Теперь у нас будет конструкция,
позволяющая добавлять новые элементы.
Первой у нас будет идти...
Сначала пусть будет картинка,
потом — ссылка на изображение.
И возвращать мы будем объекты
grumpyCat.
Собственно, этот сайт, откуда мы
будем брать картинки.
Это онлайн-сервис загрузки, хранения
и обмена изображениями.
Своего рода хостинг изображений.
Мы уже подготовили картинки
с Grumpy Cat.
И мы скопируем ссылки на каждую из них
и будем добавлять по очереди.
Но для начала мы также создадим
для них место.
И здесь мы вставим любой текст,
по желанию.
Здесь можно написать Grumpy_Cat.
Здесь можно цифры.
На этом мы еще не закончили.
Остался последний шаг.
Это — получить доступ подключению к сети
Интернет, чтобы загружать эти картинки.
С этого сайта.
Переходим в файл AndroidManifest.
В данном файле мы вставим
следующую строчку.
Нам потребуется разрешение
на подключение Интернета.
И мы закроем.
В этом файле также можно написать
разрешение для использования камеры,
контактов, хранилища данных,
отправки текстовых сообщений
и многое другое.
На этом мы закончили построение
нашего проекта.
Теперь мы его запустим.
У нас отобразился не тот вид,
который мы ожидали.
Мы ненамеренно допустили ошибку.
Но благодаря этой ошибке вы можете
сделать вывод, как важно следить
за функцией автодополнения.
В нашем случае функция автодополнения
выставила не то значение атрибута в файле
разметки, поэтому у нас некорректно
отобразилась картинка с котами.
Мы исправим это.
Перейдем в файл разметки item_cat.xml.
И здесь вместо center нам потребуется
написать centerCrop
в файле item_cat.xml.
Она отцентрирует нашу картинку.
Далее мы снова откроем наше приложение.
И у нас вместо описания картинки
выводятся ссылки на них,
хотя здесь должно быть написано
«Grumpy Cat 1», «Grumpy Cat 2» и т.д.
Данная ошибка означает, что мы
допустили ее в файле GrumpyCatAdapter,
в частности в строчке, где мы настраивали
библиотеку Picasso.
В строчке настройки текста мы вписали
получение изображения — getImage,
а нам нужно получить описание картинки.
Заменим getImage на getName.
Снова запустим проект.
Как мы видим, у нас теперь все
корректно отобразилось.
Все на месте.
RecyclerView у нас создал
прокручиваемый список.
Мы изучили современный метод построения
списков с помощью RecyclerView,
подключили мощную библиотеку
для обработки изображений Picasso.
Научились предоставлять доступ
подключению Интернета
и рассмотрели ошибку, которая может
встретиться и в вашем проекте.
В данном случае здесь следует быть
внимательным и обращать внимание на то,
что вставляет функция автодополнения.
В следующей, заключительной части лекции
мы рассмотрим, как работать
с боковым меню.
ФрагментыТемой сегодняшней лекции
являются фрагменты.
Фрагмент представляет поведение или часть
пользовательского интерфейса в активити.
Разработчик может объединить
несколько фрагментов в одну активити
для построения многопанельного
пользовательского интерфейса
и повторного использования фрагмента
в нескольких активностях.
Фрагмент можно рассматривать
как модульную часть активити.
Такая часть имеет свой жизненный цикл
и самостоятельно обрабатывает
события ввода.
Кроме того, ее можно добавить или удалить
непосредственно во время
выполнения активити.
Это нечто вроде вложенной активити,
которую можно многократно использовать
в различных активити.
Фрагмент всегда должен быть встроен
в активити, и на его жизненный цикл
напрямую влияет жизненный цикл активити.
Например, когда активити приостановлена,
в том же состоянии находятся и все
фрагменты внутри нее.
А когда активити уничтожается,
уничтожаются и все фрагменты.
Однако пока активити выполняется
(это соответствует состоянию возобновления
жизненного цикла), можно манипулировать
каждым фрагментом независимо:
например, добавлять или удалять их.
Когда фрагмент добавлен
как часть макета активити,
он находится в объекте ViewGroup
внутри иерархии представлений активити.
И определяет собственный
макет представления.
Разработчик может вставить фрагмент
в макет активити двумя способами.
Для этого следует объявить фрагмент
в файле макета активити как элемент
fragment или добавить его в существующий
объект ViewGroup в коде приложения.
Впрочем, фрагмент не обязан быть
частью макета активити.
Можно использовать фрагмент
без интерфейса в качестве невидимого
рабочего потока активити.
Фрагменты впервые появились в Android
версии 3.0 (API уровня 11).
Главным образом, для обеспечения
большей динамичности и гибкости
пользовательских интерфейсов на больших
экранах (например, у планшетов).
Поскольку экраны планшетов
гораздо больше, чем у смартфонов,
они предоставляют больше возможностей
для объединения и перестановки компонентов
пользовательского интерфейса.
Фрагменты позволяют делать это,
избавляя разработчика от необходимости
управлять сложными изменениями
в иерархии представления.
Разбивая макет активити на фрагменты,
разработчик получает возможность
модифицировать внешний вид активити
в ходе выполнения и сохранять эти
изменения в стеке переходов назад,
которым управляет активити.
Следует разрабатывать каждый фрагмент
как модульный и повторно используемый
компонент активити.
Поскольку каждый фрагмент определяет
собственный макет и собственное поведение
со своими обратными вызовами жизненного
цикла, разработчик может включить
один фрагмент в несколько активити.
Поэтому он должен предусмотреть
повторное использование фрагмента
и не допускать, чтобы один фрагмент
непосредственно манипулировал другим.
Это особенно важно, потому что
модульность фрагментов позволяет изменять
их сочетания в соответствии с различными
размерами экранов.
Если приложение должно работать
и на планшетах, и на смартфонах,
можно повторно использовать фрагменты
в различных конфигурациях макета,
чтобы оптимизировать взаимодействие
с пользователем в зависимости
от доступного размера экрана.
Например, на смартфоне может возникнуть
необходимость в разделении фрагментов
для предоставления однопанельного
пользовательского интерфейса,
если разработчику не удается поместить
более одного фрагмента в одну активити.
Пример того, как два модуля
пользовательского интерфейса,
определенные фрагментами, могут быть
объединены внутри одной активити
для работы на планшетах,
но разделены на смартфонах,
показан на рисунке.
Например, новостное приложение
может использовать один фрагмент
для показа списка статей слева,
а другой — для отображения статьи справа.
Оба фрагмента отображаются
за одну активити рядом друг с другом.
И каждый имеет собственный набор методов
обратного вызова жизненного цикла
и управляет собственными событиями
с пользовательского ввода.
Таким образом, вместо применения
одной активити для выбора статьи,
а другой — для чтения статей,
пользователь может выбрать статью
и читать ее в рамках одной активити,
как на планшете, изображенном на рисунке.
Таким образом, приложение поддерживает
как планшеты, так и смартфоны благодаря
повторному использованию фрагментов
в различных сочетаниях.
Для создания фрагмента необходимо
создать подкласс класса Fragment
или его существующего подкласса.
Класс Fragment имеет код,
во многом схожий с кодом активити.
Он содержит методы обратного вызова,
аналогичные методам активити:
onCreate, onStart, onPause и onStop.
На практике, если требуется преобразовать
существующее приложение Android так,
чтобы в нем использовались фрагменты,
достаточно просто переместить код
из методов обратного вызова активити
в соответствующие методы
обратного вызова фрагмента.
Как правило, необходимо реализовать
следующие методы жизненного цикла.
OnCreate.
Система вызывает данный метод,
когда создает фрагмент.
В своей реализации разработчик должен
инициализировать ключевые компоненты
фрагмента, которые требуется сохранить,
когда фрагмент находится в состоянии
паузы или или возобновлен после остановки.
Метод onCreateView система вызывает
при первом отображении пользовательского
интерфейса фрагмента на дисплее.
Для прорисовки пользовательского
интерфейса фрагмента следует возвратить
из этого метода объект View, который
является корневым в макете фрагмента.
Если фрагмент не имеет пользовательского
интерфейса, можно возвратить null.
Метод onPause система вызывает
как первое указание того,
что пользователь покидает фрагмент.
Это не всегда означает
уничтожение фрагмента.
Обычно именно в этот момент необходимо
фиксировать все изменения, которые должны
быть сохранены за рамками текущего сеанса
работы пользователя, поскольку
пользователь может не вернуться назад.
В большинстве приложений для каждого
фрагмента должны быть реализованы
как минимум эти три метода.
Однако существуют и другие методы
обратного вызова, которые следует
использовать для управления различными
этапами жизненного цикла фрагмента.
Существует ряд подклассов, которые,
возможно, потребуется расширить вместо
использования базового класса Fragment.
DialogFragment — это отображение
перемещаемого диалогового окна.
Использование данного класса
для создания диалогового окна
является хорошей альтернативой
вспомогательным методам диалогового
окна в классе Activity.
Дело в том, что он дает возможность
вставить диалоговое окно фрагмента
в управляемый активити стек переходов
назад для фрагментов, что позволяет
пользователю вернуться
к закрытому фрагменту.
ListFragment — это отображение списка
элементов, управляемых адаптером.
Например, SimpleCursorAdapter.
Он аналогичен классу ListActivity.
Данный класс предоставляет несколько
методов для управления списком
представлений — например, метод
обратного вызова onListItemClick
для обработки нажатий.
PreferenceFragment — это отображение
иерархии объектов Preference в виде
списка, аналогично классу
PreferenceActivity.
Этот класс полезен, когда в приложении
создается активити «Настройки».
Фрагмент обычно используется как часть
пользовательского интерфейса активити,
при этом он добавляет в активити
свой макет.
Чтобы создать макет для фрагмента,
разработчик должен реализовать метод
обратного вызова onCreateView,
который система Android вызывает,
когда для фрагмента наступает время
отобразить свой макет.
Реализация этого макета должна возвращать
объект View, который является корневым
в макете фрагмента.
Чтобы возвратить макет из метода
onCreateView, можно выполнить
его расширение из ресурса макета.
Определенного в XML-файле.
Для этой цели метод onCreate
предоставляет объект LayoutInflater.
В приведенном коде конструкция
R.layout.fragment_camera...
Является ссылкой на ресурс макета
по имени fragment_camera.xml,
хранящийся в ресурсах приложения.
Параметр container, придаваемый методу
onCreateView, является родительским
классом ViewGroup из макета активити.
В который будет вставлен макет фрагмента.
Параметр savedInstanceState является
классом Bundle, который предоставляет
данные о предыдущем экземпляре фрагмента
во время возобновления фрагмента.
Метод inflate принимает три аргумента.
Первый — это идентификатор ресурса
макета, раздувание которого
требуется выполнить.
Второй — это объект класса ViewGroup,
который должен стать родительским
для макета после расширения.
Передача параметра container необходима
для того, чтобы система смогла применить
параметр макета к корневому представлению
раздутого макета, определяемому
родительским представлением,
в которое направляется макет.
И третье — это логическое значение,
показывающее, следует ли прикрепить макет
к объекту ViewGroup во время расширения.
В данном случае это false, потому что
система уже вставляет раздутый макет
в объект container, и передача значения
true создала бы лишнюю группу
представления в окончательном макете.
Мы увидели, как создавать фрагмент,
представляющий макет.
Теперь необходимо добавить
фрагмент в активити.
Как правило, фрагмент добавляет часть
пользовательского интерфейса в активити,
и этот интерфейс встраивается в общую
иерархию представлений активити.
Разработчик может добавить фрагмент
в макет активити двумя способами.
Первый — это объявить фрагмент
в файле макета активити.
В этом случае можно указать
свойства макета для фрагмента,
как будто он является представлением.
Например, файл макета активити с двумя
фрагментами может выглядеть
следующим образом.
Атрибут name в элементе fragment
определяет класс Fragment.
Экземпляр которого создается в макете.
Когда система создает данный макет
активити, она создает экземпляр каждого
фрагмента, определенного в макете,
и для каждого вызывает метод onCreateView,
чтобы получить макет каждого фрагмента.
Система вставляет объект View,
возвращенный фрагментом,
непосредственно вместо элемента fragment.
Каждый фрагмент должен иметь уникальный
идентификатор, который система сможет
использовать для восстановления фрагмента
в случае перезапуска активити.
Предоставить идентификатор фрагменту
можно тремя способами.
Указать атрибут android:id
с уникальным идентификатором.
Указать атрибут android:tag
с уникальной строкой.
Ничего не предпринимать, чтобы система
использовала идентификатор
контейнерного представления.
И второй способ добавления фрагмента
в активити — это программный способ.
Через добавление фрагмента
в существующий объект ViewGroup.
В любой момент выполнения активити
разработчик может добавить
фрагменты в ее макет.
Для этого достаточно указать объект
ViewGroup, в котором следует
разместить фрагмент.
Для выполнения транзакций с фрагментами
внутри активити, таких как добавление,
удаление или замена фрагмента,
необходимо использовать API-интерфейсы
из FragmentTransaction.
Экземпляр класса FragmentTransaction
можно получить от объекта Activity
следующим образом, указанным на слайде.
И после этого можно добавить
фрагмент методом add.
Добавляемый фрагмент и представление,
в которое он должен быть добавлен.
Пример указан на второй картинке слайда.
Первый аргумент, передаваемый методу add,
представляет собой контейнерный объект
ViewGroup для фрагмента, указанный
при помощи идентификатора ресурса.
Второй параметр — это фрагмент,
который нужно добавить.
Выполнив изменения с помощью
FragmentTransaction, необходимо вызвать
метод commit, чтобы они вступили в силу.
Создание приложения "Фрагменты"В этом уроке мы попробуем новый шаблон
под названием Navigation Drawer.
Он представляет собой боковое меню.
Открывается меню с левой стороны.
Далее познакомимся с интерфейсом шаблона.
А в следующей части нашей лекции мы
добавим функционал для нашего приложения.
Создадим новый проект.
Назовем его Fragment App.
Далее нажмем Next.
Next.
В окне выбора макета мы выберем
новый шаблон под названием
Navigation Drawer Activity.
И нажмем на кнопку Next.
Оставим поля по умолчанию.
И нажмем на кнопку Finish.
У нас собрался проект.
Для того чтобы увидеть работу
Navigation Drawer, мы запустим его.
В Android Studio.
Так, у нас запустилось приложение наше,
которое содержит боковое меню.
Раскроем его.
Здесь, как мы видим, есть иконка
приложения.
А в настоящих, в реальных приложениях
здесь была бы аватарка пользователя.
Далее его имя, фамилия и адрес его почты.
Следующее: у нас имеются пункты меню.
В нашем приложении они не работают,
поскольку это просто шаблон.
Для того чтобы у нас открывались пункты
меню в новых активити, мы дополним
наше приложение Fragment App.
Теперь перейдем в код нашего проекта.
Раскроем папку project.
Откроем файл MainActivity.
Как мы видим, здесь добавилось...
Большое количество строк кода.
У нас изменились файлы активити.
У нас изменились файлы разметки.
Добавились новые файлы.
Также у нас добавились новые директории.
Добавились файлы еще одни — иконок.
И в целом у нас изменился
стиль приложения.
Сейчас важно запомнить, что за выдвигающую
шторку у нас отвечает элемент
NavigationView, который входит
последний в контейнере DrawerLayout
и представляет собой навигационное
меню в файле ActivityMain.
Откроем файл ActivityMain.
И, как мы видим, здесь у нас находится...
Виджет NavigationView.
Атрибут tools:openDrawer="start".
Позволяет указать студии, что
навигационное меню нужно
отобразить в раскрытом виде
в режиме просмотра разметки.
Тег NavigationView содержит ссылку
на собственную разметку в атрибуте
app:headerLayout.
Который указывает на файл
nav_header_main.xml, что означает
«верхняя часть строчки».
Он представляет код верхней части
строчки, где у нас именно открывается
аватарка приложения, название приложения
и почтовый ящик.
А также в меню, в атрибуте app:menu
он ссылается на ресурс меню,
который находится в папке menu.
Под именем activity_main_drawer.
Здесь у нас хранятся иконки
нашего бокового меню.
Посмотрим на разметку шторки —
откроем файл nav_header_main.
Разметка состоит из ImageView
и двух TextView, размещенных
в контейнере LinearLayout.
Фон контейнера определен
в ресурсе drawable/side_nav_bar.
И представляет собой градиент.
Вот здесь мы его можем увидеть.
Как мы здесь видим, здесь идет переход
от светлого оттенка зеленого
к более темному.
Снова вернемся в наш файл.
Остальные атрибуты понятны
и не требуют объяснений.
Теперь рассмотрим ресурс навигационного
меню, который находится в папке res/menu
под именем activity_main_drawer.
Каждый пункт меню представляет собой
тег item с указанием значка и текста.
Для группировки используется
элемент group.
Поведение элементов меню в группе
регулируется атрибутом
android:checkableBehavior.
В примере используется значение single.
Значит, при нажатии на пункт меню
он останется выделенным.
Это принцип переключателя RadioButton.
Теперь изучим код активности
для работы со шторкой.
Перейдем в файл MainActivity.java.
В классе активности у нас реализуется
интерфейс OnNavigationItemSelectedListener
с его методом OnNavigationItemSelected.
Логика кода ничем не отличается
от работы с обычным меню.
Определяется идентификатор выбранного
пункта, и далее вам нужно
написать свой код.
Затем вызывается метод closeDrawer.
Для закрытия шторки.
Добавим код для первого пункта меню.
Можете также добавить и для остальных
пунктов меню тип уведомления
с различным текстом.
Мы добавим объект Toast.
Для того чтобы видеть, что происходит
при нажатии на пункт меню.
Мы добавим Toast к объекту camera.
С текстом просто "Camera".
И отобразим с помощью метода show.
Запустим наш проект, чтобы посмотреть,
что у нас получилось.
Кликаем на пункт меню Import.
В данном случае у нас это объект camera,
так как он первым идет.
И, как мы видим, тостовое
сообщение работает.
Появилось сообщение о том,
что мы кликнули на камеру.
Мы разобрали происхождение
новых для нас файлов.
В следующей части мы разбавим приложение
функциональностью, благодаря которой
у нас будут открываться новые фрагменты
при нажатии на выбранный пункт меню.
В этой части нашей лекции мы закончим
создание приложения «Фрагменты».
Создадим четыре класса фрагментов
и определим им открытие по пункту
меню в Navigation Drawer.
В шаблоне у нас присутствует метод
onNavigationItemSelected.
С аннотацией SuppressWarnings
StatementWithEmptyBody, что означает
«оператор с пустым телом».
Нам нужно добавить свой код для навигации,
который должен реагировать на нажатие
в меню шторки.
Для этого нам понадобятся фрагменты.
Для примера мы создадим первый фрагмент
под именем CameraFragment.
По такому же образу мы создадим второй,
третий и четвертый фрагмент.
Назовем их GalleryFragment,
SlideshowFragment и ManageFragment.
То есть для этих четырех пунктов меню
мы создадим четыре фрагмента.
Но для начала нам следует определить
RelativeLayout в файле content_main.
Мы удалим дефолтный ConstraintLayout.
И заменим его на RelativeLayout.
Как мы помним, для того чтобы работать
с RelativeLayout, нам обязательно
требуется определить идентификатор.
Дадим ему имя container.
Далее мы удалим TextView.
Он нам больше уже не понадобится.
Теперь мы можем написать недостающий код
для навигации по фрагментам
в MainActivity.
Переходим на вкладку MainActivity.
В данном методе onNavigationItemSelected
мы создадим новый фрагмент.
Можно удалить этот комментарий.
Создаем Fragment.
Как мы видим, что здесь идет
старая поддержка.
Сейчас она не поддерживается.
Нам нужна библиотека поддержки v4.
Определяем значение null.
И класса тоже мы определяем значение null.
Теперь мы будем работать с фрагментами.
В данном случае мы будем создавать.
Новые фрагменты.
Чтобы при нажатии на пункт меню —
например, камеру — у нас открывался
фрагмент с названием Camera.
Дадим ему название CameraFragment.
У нас подсветилось.
Это означает, что у нас пока нет
такого фрагмента.
Сначала мы создадим для каждого
пункта меню свой фрагмент.
И потом их добавим уже с помощью
Android Studio.
Далее у нас следующий фрагмент
будет называться GalleryFragment.
Третий пункт меню — SlideshowFragment.
И последний пункт меню.
Будет называться ManageFragment.
Далее мы создадим обработку исключения,
для того чтобы у нас не произошло ошибки.
Чтобы приложение не упало, если какой-то
из этих фрагментов не существует.
Мы создадим проверку здесь.
С помощью блока try-catch.
Здесь нам нужен Fragment.
Теперь мы вставим фрагмент.
С помощью FragmentManager.
Вставим поддержку FragmentManager.
Далее начнем работу его.
Запустим.
Используем метод replace.
И для того чтобы изменения вступили
в силу, вызовем метод commit.
Теперь нам нужно будет отобразить
выделенный пункт меню шторки.
С помощью метода setChecked.
Со значением true.
И нам потребуется вывести выбранный
пункт меню в заголовке
с помощью метода setTitle.
Берем объект item.
И присваиваем ему метод getTitle.
Теперь нам потребуется
почистить немного код.
Нажимаем Alt + Enter.
И делаем зачистку.
Теперь нам потребуется создать фрагменты.
Для каждого класса Fragment.
Мы создадим фрагменты.
Кликнем на пакет нашего проекта.
Ищем пункт New Fragment
и выбираем Blank.
То есть абсолютно пустой.
Нам не нужно добавлять методы
и интерфейсы.
Первый фрагмент у нас называется Camera.
Мы его так и назовем.
Кликаем на кнопку Finish.
Для того чтобы понять, что открыт именно
фрагмент Camera, мы перейдем во вкладку
fragment_camera.xml и здесь напишем
Camera Fragment.
Подождем, пока студия добавит
новый фрагмент, соберется.
И потом добавим новый фрагмент.
Второй по счету.
Под именем GalleryFragment.
Можем скопировать просто название.
Так, студия собралась.
Создаем второй фрагмент.
Убираем галочки.
Кликаем Finish.
Здесь также во фрагменте в файле разметки
мы удалим hello_blank_fragment
и введем Gallery Fragment.
Подождем, пока студия соберет наш проект.
Пока скопируем название
следующего фрагмента,
который нам потребуется создать.
Так, студия нам добавила фрагмент.
Теперь добавляем третий фрагмент.
Снова убираем ненужные методы
и интерфейсы.
Называем наш следующий
фрагмент Slideshow.
Кликаем Finish.
И снова здесь прописываем текст.
SlideshowFragment.
Добавим пробел между названием.
Ждем, пока студия снова придет в себя.
После добавления фрагментов.
Скопируем пока название нашего четвертого,
последнего фрагмента, который нам
потребуется добавить сегодня.
Добавляем последний, четвертый фрагмент.
С именем ManageFragment.
Кликаем Finish.
И здесь также прописываем ему название.
В тексте: Manage Fragment.
Переходим в файл MainActivity.
У нас теперь нет ошибок в коде.
Подождем, пока проект у нас соберется.
И запустим приложение на эмуляторе,
чтобы посмотреть, как работает открытие
новых окон с помощью фрагментов.
До этого мы переходили с помощью активити
с методом intent, теперь мы...
Переходим на новые окна
с помощью Fragment.
Теперь посмотрим, как у нас работает.
Кликнем на первый.
Как мы видим, у нас первая —
Camera Fragment.
Вторая должна быть Gallery.
Все верно.
Третья — Slideshow.
Четвертая — Manage Fragment.
Все изменения у нас вступили в силу.
Единственное, что мы не добавили
для пункта меню Share.
Но так как у нас нет этого пункта,
у нас приложение закрывается.
Снова откроем наше приложение.
На этом построение приложения
с фрагментами у нас окончено.
При желании вы можете заменить кнопки.
Например, здесь поставить свою аватарку.
Здесь написать свою фамилию.
Почтовый адрес, изменить пункты меню.
В самих же фрагментах (например,
в Camera Fragment) вы здесь можете
вставить картинки, изменить функционал,
добавить виджеты, кнопки, новые функции.
Для того чтобы закрепить работу
с использованием бокового меню.
ЗаключениеПришло время подытожить наш курс
разработки для начинающих.
Мы создали с вами 10 приложений.
Начали с установки программного
обеспечения и закончили построением
многооконного приложения
с использованием фрагментов.
На курсе мы установили среду разработки
Android Studio, поработали с SDK Manager.
Построили первый проект и запустили его
на виртуальном эмуляторе.
Рассмотрели элементы управления View,
а именно использовали кнопки, текст,
изображения, выпадающие списки и т.д.
Узнали, какие бывают родительские макеты
класса ViewGroup, научились переходить
на новые окна в приложении, запускать
другие приложения благодаря интентам.
С помощью жизненного цикла в Android
узнали, как можно создать приложение
«Таймер» с сохранением времени,
несмотря на смену ориентации
или выход из приложения.
У нас получилось поработать с простейшим
списковым представлением ListView
и его заменителем RecyclerView, который
сейчас активно используется для создания
современных списков и не только.
Благодаря библиотеке Picasso мы
не сохраняли изображения в ресурсах
приложения, а дали ссылку на них,
что существенно сказалось
на производительности.
И в завершении курса использовали готовый
шаблон с боковым меню Navigation Drawer,
создав для него фрагменты.
Однозначно, мы с вами написали
более сотни строк кода и создали
более 17 разметок, где научились работать
с пользовательским интерфейсом.
Мы надеемся, что обучение
на платформе открытого образования
разработке мобильных приложений
принесло вам пользу
и необходимые знания.
К сожалению, мы не затронули еще много
новых и не менее интересных тем.
Однако будем надеяться, что данный курс
по мобильной разработке для начинающих
даст вам старт для продолжения изучения
мира зеленых роботов.
Для дальнейшего самостоятельного изучения
мы подготовили для вас библиотеку
материалов, которая будет
в описании к видео.
До следующих встреч!