Компоненты Material (MDC) помогают разработчикам реализовывать принципы Material Design. MDC, созданный командой инженеров и UX-дизайнеров Google, включает в себя десятки красивых и функциональных компонентов пользовательского интерфейса и доступен для Android, iOS, веб-приложений и Flutter. material.io/develop |
Что такое Material Design и Material Components для Android?
Material Design — это система для создания смелых и красивых цифровых продуктов. Объединяя стиль, брендинг, взаимодействие и анимацию в рамках единого набора принципов и компонентов, команды разработчиков могут максимально реализовать свой дизайнерский потенциал.
Для приложений Android Material Components for Android ( MDC Android ) объединяет дизайн и разработку с библиотекой компонентов для обеспечения согласованности во всем приложении. По мере развития системы Material Design эти компоненты обновляются, обеспечивая единообразную реализацию с точностью до пикселя и соответствие стандартам Google для фронтенд-разработки. MDC также доступен для веб-приложений, iOS и Flutter.
В этой лабораторной работе вы создадите страницу входа, используя несколько компонентов MDC Android.
Что вы построите
Эта лабораторная работа — первая из четырёх, которые помогут вам создать приложение Shrine — приложение электронной коммерции для Android, продающее одежду и товары для дома. В ней будет показано, как настроить компоненты под любой бренд или стиль с помощью MDC Android.
В этой лабораторной работе вы создадите страницу входа для Shrine, которая будет содержать:
- Два текстовых поля: одно для ввода имени пользователя, другое для пароля
- Две кнопки: одна для «Отмена» и одна для «Далее»
- Название приложения (Shrine)
- Изображение логотипа Shrine
Компоненты Android MDC в этой лабораторной работе
- Текстовое поле
- Кнопка
Что вам понадобится
- Базовые знания разработки под Android
- Android Studio (загрузите здесь, если у вас ее еще нет)
- Эмулятор или устройство Android (доступно через Android Studio)
- Пример кода (см. следующий шаг)
Как бы вы оценили свой уровень опыта в создании приложений для Android?
Запустить Android Studio
При запуске Android Studio должно появиться окно с надписью «Добро пожаловать в Android Studio». Однако, если вы запускаете Android Studio впервые, следуйте инструкциям мастера установки Android Studio, используя значения по умолчанию . Загрузка и установка необходимых файлов может занять несколько минут, поэтому можете оставить его в фоновом режиме, пока вы работаете со следующим разделом.
Загрузите стартовое приложение Codelab
Стартовое приложение находится в каталоге material-components-android-codelabs-101-starter/kotlin
.
...или клонируйте его с GitHub
Чтобы клонировать эту кодовую лабу из GitHub, выполните следующие команды:
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 101-starter
Загрузите стартовый код в Android Studio
- После завершения работы мастера настройки и появления окна «Добро пожаловать в Android Studio» нажмите « Открыть существующий проект Android Studio» . Перейдите в каталог, куда был установлен пример кода, и выберите kotlin -> shrine (или найдите shrine на компьютере), чтобы открыть проект Shipping.
- Подождите немного, пока Android Studio выполнит сборку и синхронизацию проекта, на что указывают индикаторы активности в нижней части окна Android Studio.
- На этом этапе Android Studio может выдать ошибки сборки, поскольку у вас отсутствует Android SDK или инструменты сборки, например, показанные ниже. Следуйте инструкциям Android Studio, чтобы установить/обновить их и синхронизировать свой проект.
Добавить зависимости проекта
Проекту требуется зависимость от библиотеки поддержки MDC для Android . В загруженном примере кода эта зависимость уже должна быть указана, но для её обеспечения рекомендуется выполнить следующие шаги.
- Перейдите к файлу
build.gradle
модуляapp
и убедитесь, что блокdependencies
включает зависимость от MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
- (Необязательно) При необходимости отредактируйте файл
build.gradle
, чтобы добавить следующие зависимости и синхронизировать проект.
dependencies { api 'com.google.android.material:material:1.1.0-alpha06' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.android.volley:volley:1.1.1' implementation 'com.google.code.gson:gson:2.8.5' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21" testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:core:1.1.0' androidTestImplementation 'androidx.test.ext:junit:1.1.0' androidTestImplementation 'androidx.test:runner:1.2.0-alpha05' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05' }
Запустите стартовое приложение
|
Успех! Стартовый код страницы входа Shrine должен быть запущен в вашем эмуляторе. Вы должны увидеть название Shrine и логотип Shrine прямо под ним.
Давайте взглянем на код. В нашем примере кода мы предоставили простую структуру навигации Fragment
для отображения фрагментов и навигации между ними.
Откройте MainActivity.kt
в каталоге shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.kotlin.shrine
. Он должен содержать следующее:
MainActivity.kt
package com.google.codelabs.mdc.kotlin.shrine
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
class MainActivity : AppCompatActivity(), NavigationHost {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.shr_main_activity)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.add(R.id.container, LoginFragment())
.commit()
}
}
override fun navigateTo(fragment: Fragment, addToBackstack: Boolean) {
val transaction = supportFragmentManager
.beginTransaction()
.replace(R.id.container, fragment)
if (addToBackstack) {
transaction.addToBackStack(null)
}
transaction.commit()
}
}
Это действие отображает файл макета R.layout.shr_main_activity
, определенный в shr_main_activity.xml
.
Видно, что в onCreate(),
MainActivity.kt
запускает транзакцию Fragment
для отображения LoginFragment
. В этой лабораторной работе мы будем модифицировать LoginFragment
. В активности также реализован метод navigateTo(Fragment)
, определённый в NavigationHost
, который позволяет любому фрагменту переходить к другому фрагменту.
Нажмите Command + Click (или Control + Click ) shr_main_activity
в файле активности, чтобы открыть файл макета, или перейдите к файлу макета в app -> res -> layout -> shr_main_activity.xml
.
shr_main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"/>
Здесь мы видим простой <FrameLayout>
, который действует как контейнер для любых фрагментов, отображаемых действием.
Далее откроем LoginFragment.kt
.
LoginFragment.kt
package com.google.codelabs.mdc.kotlin.shrine
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
class LoginFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.shr_login_fragment, container, false)
return view
}
}
LoginFragment
заполняет файл макета shr_login_fragment
и отображает его в onCreateView()
.
Теперь давайте посмотрим на файл макета shr_login_fragment.xml
чтобы увидеть, как выглядит страница входа.
shr_login_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/loginPageBackgroundColor"
tools:context=".LoginFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
android:padding="24dp"
android:paddingTop="16dp">
<ImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="48dp"
android:layout_marginBottom="16dp"
app:srcCompat="@drawable/shr_logo" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="132dp"
android:text="@string/shr_app_name"
android:textAllCaps="true"
android:textSize="16sp" />
</LinearLayout>
</ScrollView>
Здесь мы видим <LinearLayout>
с <ImageView>
наверху, представляющим логотип Shrine.
Далее следует тег <TextView>
, представляющий метку Shrine под логотипом. Текст этой метки — строковый ресурс с именем @string/shr_app_name
. Если нажать Command + Click (или Control + Click ) на имени строкового ресурса или открыть app -> res -> values -> strings.xml
, можно увидеть файл strings.xml
, в котором определены строковые ресурсы. При добавлении дополнительных строковых ресурсов они будут определены здесь. Каждый ресурс в этом файле должен иметь префикс shr_
, указывающий на то, что он является частью приложения Shrine.
Теперь, когда вы знакомы с начальным кодом, давайте реализуем наш первый компонент.
Для начала добавим на страницу входа два текстовых поля для ввода имени пользователя и пароля. Мы будем использовать компонент MDC Text Field, который включает встроенную функцию отображения плавающей метки и сообщений об ошибках.
Добавьте XML
В shr_login_fragment.xml
добавьте два элемента TextInputLayout
с дочерним элементом TextInputEditText
внутри <LinearLayout>
под меткой «SHRINE» <TextView>
:
shr_login_fragment.xml
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="@string/shr_hint_username">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/password_text_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="@string/shr_hint_password">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
В приведенном выше фрагменте кода представлены два текстовых поля, каждое из которых состоит из элемента <TextInputLayout>
и дочернего элемента <TextInputEditText>
. Текст подсказки для каждого текстового поля указывается в атрибуте android:hint
.
Мы добавили два новых строковых ресурса для текстового поля — @string/shr_hint_username
и @string/shr_hint_password
. Откройте strings.xml
, чтобы увидеть эти строковые ресурсы.
strings.xml
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
Добавить проверку входных данных
Компоненты TextInputLayout
предоставляют встроенную функцию обратной связи об ошибках.
Чтобы отобразить сообщение об ошибке, внесите следующие изменения в shr_login_fragment.xml
:
- Установите атрибут
app:errorEnabled
в значениеtrue
для элемента PasswordTextInputLayout
. Это добавит дополнительный отступ для сообщения об ошибке под текстовым полем. - Установите атрибут
android:inputType
в значение "textPassword
" для элемента PasswordTextInputEditText
. Это скроет вводимый текст в поле пароля.
С этими изменениями текстовые поля в shr_login_fragment.xml
должны выглядеть следующим образом:
shr_login_fragment.xml
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="@string/shr_hint_username">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/password_text_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:hint="@string/shr_hint_password"
app:errorEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
Теперь попробуйте запустить приложение. Вы увидите страницу с двумя текстовыми полями: «Имя пользователя» и «Пароль»!
Посмотрите на анимацию плавающей этикетки:
Далее мы добавим на страницу входа две кнопки: «Отмена» и «Далее». Мы будем использовать компонент MDC Button, в который встроен культовый эффект чернильной ряби в стиле Material Design.
Добавьте XML
В shr_login_fragment.xml
добавьте элемент <RelativeLayout>
к элементу <LinearLayout>
под элементами TextInputLayout
. Затем добавьте два элемента <MaterialButton>
к элементу <RelativeLayout>
.
Полученный XML-файл должен выглядеть следующим образом:
shr_login_fragment.xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/next_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:text="@string/shr_button_next" />
<com.google.android.material.button.MaterialButton
android:id="@+id/cancel_button"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginRight="12dp"
android:layout_toStartOf="@id/next_button"
android:layout_toLeftOf="@id/next_button"
android:text="@string/shr_button_cancel" />
</RelativeLayout>
Вот и всё! При запуске приложения при нажатии каждой кнопки будет появляться чернильная рябь.
Наконец, мы добавим немного кода Kotlin в LoginFragment.kt
, чтобы подключить нашу кнопку «ДАЛЕЕ» для перехода к другому фрагменту.
Давайте добавим приватный логический метод isPasswordValid
в LoginFragment.kt
под onCreateView()
с логикой для определения корректности пароля. Для целей этой демонстрации мы просто убедимся, что пароль содержит не менее 8 символов:
LoginFragment.kt
private fun isPasswordValid(text: Editable?): Boolean {
return text != null && text.length >= 8
}
Затем добавьте прослушиватель кликов к кнопке «Далее», который устанавливает и сбрасывает ошибку на основе метода isPasswordValid()
который мы только что создали. В onCreateView()
этот прослушиватель кликов должен быть расположен между строкой инфлятора и строкой return view
.
Теперь добавим прослушиватель нажатия клавиш к TextInputEditText
, который будет отслеживать события нажатия клавиш, которые сбрасывают ошибку. Этот прослушиватель также должен использовать isPasswordValid()
для проверки корректности пароля. Вы можете добавить его непосредственно под прослушивателем нажатия клавиш в onCreateView()
.
Теперь ваш метод onCreateView() должен выглядеть примерно так:
LoginFragment.kt
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment.
val view = inflater.inflate(R.layout.shr_login_fragment, container, false)
// Set an error if the password is less than 8 characters.
view.next_button.setOnClickListener({
if (!isPasswordValid(password_edit_text.text!!)) {
password_text_input.error = getString(R.string.shr_error_password)
} else {
// Clear the error.
password_text_input.error = null
}
})
// Clear the error once more than 8 characters are typed.
view.password_edit_text.setOnKeyListener({ _, _, _ ->
if (isPasswordValid(password_edit_text.text!!)) {
// Clear the error.
password_text_input.error = null
}
false
})
return view
}
}
Теперь мы можем перейти к другому фрагменту. В onCreateView()
обновите OnClickListener
для перехода к другому фрагменту при успешной проверке на наличие ошибки. Код clickListener
должен выглядеть следующим образом:
LoginFragment.kt
// Set an error if the password is less than 8 characters.
view.next_button.setOnClickListener({
if (!isPasswordValid(password_edit_text.text!!)) {
password_text_input.error = getString(R.string.shr_error_password)
} else {
// Clear the error.
password_text_input.error = null
// Navigate to the next Fragment.
(activity as NavigationHost).navigateTo(ProductGridFragment(), false)
}
})
Мы добавили строку (
activity
as
NavigationHost).navigateTo(ProductGridFragment(),
false
)
в блок else
обработчика кликов. Эта строка вызывает метод navigateTo()
из MainActivity
для перехода к новому фрагменту — ProductGridFragment
. В настоящее время это пустая страница, с которой вы будете работать в рамках курса MDC-102.
Теперь создайте приложение. Нажмите кнопку «Далее».
Вы справились! Этот экран станет отправной точкой нашей следующей лабораторной работы, над которой вы будете работать в MDC-102.
Используя базовую разметку XML и около 30 строк кода Kotlin, библиотека Material Components for Android помогла вам создать красивую страницу входа, которая соответствует принципам Material Design, а также выглядит и ведет себя одинаково на всех устройствах.
Следующие шаги
Текстовое поле и кнопка — два основных компонента библиотеки MDC Android, но их гораздо больше! Вы можете изучить остальные компоненты MDC Android . Кроме того, ознакомьтесь с разделом MDC 102: Material Design Structure and Layout, чтобы узнать больше о верхней панели приложения, карточном представлении и сетке. Спасибо за знакомство с Material Components. Надеемся, вам понравилась эта практическая работа!