1. Введение
Material Components (MDC) помогают разработчикам реализовать Material Design. Созданный командой инженеров и UX-дизайнеров Google, MDC включает в себя десятки красивых и функциональных компонентов пользовательского интерфейса и доступен для 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
Компоненты Android MDC в этой лаборатории кода
- Текстовое поле
- Кнопка
Что вам понадобится
- Базовые знания Android-разработки.
- Android Studio (скачайте здесь , если у вас его еще нет)
- Эмулятор Android или устройство (доступно через Android Studio).
- Пример кода (см. следующий шаг)
Как бы вы оценили свой опыт создания приложений для Android?
2. Настройте среду разработки
Запустите Android Studio
Когда вы открываете Android Studio , должно появиться окно под названием «Добро пожаловать в Android Studio». Однако если вы запускаете Android Studio впервые, выполните шаги мастера установки Android Studio со значениями по умолчанию . Этот шаг может занять несколько минут для загрузки и установки необходимых файлов, поэтому не стесняйтесь оставить этот процесс в фоновом режиме, пока вы выполняете следующий раздел.
Загрузите начальное приложение Codelab.
Стартовое приложение находится в каталоге material-components-android-codelabs-101-starter/java
.
...или клонируйте его с 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» . Перейдите в каталог, в который вы установили пример кода, и выберите java -> shrine (или найдите на своем компьютере shrine ), чтобы открыть проект Shrine.
- Подождите, пока Android Studio создаст и синхронизирует проект, как показывают индикаторы активности в нижней части окна Android Studio.
- На этом этапе Android Studio может вызвать некоторые ошибки сборки, поскольку вам не хватает Android SDK или инструментов сборки, таких как показанный ниже. Следуйте инструкциям в Android Studio, чтобы установить/обновить их и синхронизировать проект.
Добавить зависимости проекта
Проекту нужна зависимость от библиотеки поддержки Android MDC . В загруженном вами примере кода эта зависимость уже должна быть указана, но чтобы убедиться в этом, рекомендуется выполнить следующие шаги.
- Перейдите к файлу
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.java
в каталоге shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.java.shrine
. Он должен содержать это:
MainActivity.java
package com.google.codelabs.mdc.java.shrine;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends AppCompatActivity implements NavigationHost {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shr_main_activity);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.add(R.id.container, new LoginFragment())
.commit();
}
}
/**
* Navigate to the given fragment.
*
* @param fragment Fragment to navigate to.
* @param addToBackstack Whether or not the current fragment should be added to the backstack.
*/
@Override
public void navigateTo(Fragment fragment, boolean addToBackstack) {
FragmentTransaction transaction =
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment);
if (addToBackstack) {
transaction.addToBackStack(null);
}
transaction.commit();
}
}
Это действие отображает файл макета R.layout.shr_main_activity
, определенный в shr_main_activity.xml
.
Вы можете видеть, что в onCreate(),
MainActivity.java
запускает транзакцию 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.java
.
ЛогинФрагмент.java
package com.google.codelabs.mdc.java.shrine;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
/**
* Fragment representing the login screen for Shrine.
*/
public class LoginFragment extends Fragment {
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.shr_login_fragment, container, false);
// Snippet from "Navigate to the next Fragment" section goes here.
return view;
}
// "isPasswordValid" from "Navigate to the next Fragment" section method goes here
}
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" />
<!-- Snippet from "Add text fields" section goes here. -->
<!-- Snippet from "Add buttons" section goes here. -->
</LinearLayout>
</ScrollView>
Здесь мы видим <LinearLayout>
с <ImageView>
вверху, представляющим логотип Shrine.
После этого идет тег <TextView>
, представляющий метку «SHRINE». Текст этой метки представляет собой строковый ресурс с именем @string/shr_app_name
. Если вы нажмете Command + Click (или Control + Click ) по имени строкового ресурса или откроете app -> res -> values -> strings.xml
, вы увидите файл strings.xml
, в котором определены строковые ресурсы. Когда в будущем будут добавлены дополнительные строковые ресурсы, они будут определены здесь. Каждый ресурс в этом файле должен иметь префикс shr_
обозначающий, что он является частью приложения Shrine.
Теперь, когда вы знакомы со стартовым кодом, давайте реализуем наш первый компонент.
3. Добавьте текстовые поля
Для начала мы добавим на нашу страницу входа в систему два текстовых поля, чтобы люди могли вводить свое имя пользователя и пароль. Мы будем использовать компонент «Текстовое поле MDC», который включает в себя встроенные функции отображения плавающей метки и сообщений об ошибках.
Добавьте 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"
android:inputType="text"
android:maxLines="1" />
</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
, чтобы увидеть эти строковые ресурсы.
строки.xml
...
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
...
Добавить проверку ввода
Компоненты TextInputLayout
предоставляют встроенную функцию обратной связи об ошибках.
Чтобы отобразить обратную связь об ошибках, внесите следующие изменения в shr_login_fragment.xml
:
- Установите
app:errorEnabled
значение true в элементеTextInputLayout
пароля . Это добавит дополнительное дополнение к сообщению об ошибке под текстовым полем. - Установите для атрибута
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"
android:inputType="text"
android:maxLines="1" />
</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>
Теперь попробуйте запустить приложение. Вы должны увидеть страницу с двумя текстовыми полями «Имя пользователя» и «Пароль»!
Посмотрите анимацию плавающей метки:
4. Добавьте кнопки
Далее мы добавим на нашу страницу входа две кнопки: «Отмена» и «Далее». Мы будем использовать компонент 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>
Вот и все! Когда вы запустите приложение, при нажатии на каждую кнопку будет отображаться рябь от чернил.
5. Перейдите к следующему фрагменту.
Наконец, мы добавим Java-код в LoginFragment.java
, чтобы подключить нашу кнопку «ДАЛЕЕ» к другому фрагменту. Вы заметите, что каждому из компонентов, которые мы добавили в наш макет, был присвоен id
. Мы будем использовать эти id
для ссылки на компоненты в нашем коде и добавим некоторую проверку ошибок и навигацию.
Давайте добавим частный логический метод isPasswordValid
в LoginFragment.java
под onCreateView()
с логикой, позволяющей определить, действителен ли пароль. Для целей этой демонстрации мы просто убедимся, что длина пароля составляет не менее 8 символов:
ЛогинФрагмент.java
/*
In reality, this will have more complex logic including, but not limited to, actual
authentication of the username and password.
*/
private boolean isPasswordValid(@Nullable Editable text) {
return text != null && text.length() >= 8;
}
Затем добавьте прослушиватель кликов к кнопке «Далее», который устанавливает и очищает ошибку на основе только что созданного нами метода isPasswordValid()
. В onCreateView()
этот прослушиватель кликов должен быть помещен между строкой надувателя и строкой return view
.
Далее, давайте добавим к паролю прослушиватель ключей TextInputEditText
чтобы прослушивать ключевые события, которые устранят ошибку. Этот прослушиватель также должен использовать isPasswordValid()
чтобы проверить, действителен ли пароль. Вы можете добавить это непосредственно под прослушивателем кликов в onCreateView()
.
Ваш метод onCreateView() теперь должен выглядеть примерно так:
ЛогинФрагмент.java
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.shr_login_fragment, container, false);
final TextInputLayout passwordTextInput = view.findViewById(R.id.password_text_input);
final TextInputEditText passwordEditText = view.findViewById(R.id.password_edit_text);
MaterialButton nextButton = view.findViewById(R.id.next_button);
// Set an error if the password is less than 8 characters.
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!isPasswordValid(passwordEditText.getText())) {
passwordTextInput.setError(getString(R.string.shr_error_password));
} else {
passwordTextInput.setError(null); // Clear the error
}
}
});
// Clear the error once more than 8 characters are typed.
passwordEditText.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (isPasswordValid(passwordEditText.getText())) {
passwordTextInput.setError(null); //Clear the error
}
return false;
}
});
return view;
}
Теперь мы можем перейти к другому фрагменту. Обновите OnClickListener
в onCreateView()
чтобы перейти к другому фрагменту при успешной проверке ошибок. Это можно сделать, добавив следующую строку для перехода к ProductGridFragment
в else
прослушивателя кликов:
ЛогинФрагмент.java
...
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
...
Теперь ваш прослушиватель кликов должен выглядеть следующим образом:
ЛогинФрагмент.java
...
MaterialButton nextButton = view.findViewById(R.id.next_button);
// Set an error if the password is less than 8 characters.
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!isPasswordValid(passwordEditText.getText())) {
passwordTextInput.setError(getString(R.string.shr_error_password));
} else {
passwordTextInput.setError(null); // Clear the error
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
}
}
});
...
Эта новая строка кода вызывает метод navigateTo()
из MainActivity
для перехода к новому фрагменту — ProductGridFragment
. В настоящее время это пустая страница, над которой вы будете работать в MDC-102.
Теперь создайте приложение. Идем дальше и нажимаем кнопку «Далее».
Вы сделали это! Этот экран станет отправной точкой нашей следующей лаборатории кода, над которой вы будете работать в MDC-102.
6. Все готово
Используя базовую XML-разметку и около 30 строк Java, библиотека Material Components для Android помогла вам создать красивую страницу входа, которая соответствует рекомендациям Material Design, а также одинаково выглядит и ведет себя на всех устройствах.
Следующие шаги
Текстовое поле и кнопка — это два основных компонента библиотеки MDC Android, но их гораздо больше! Остальные компоненты MDC Android вы можете изучить. Альтернативно, перейдите к MDC 102: Структура и макет Material Design, чтобы узнать о верхней панели приложения, представлении карточек и макете сетки. Спасибо за попытку использования Material Components. Мы надеемся, что вам понравилась эта кодовая лаборатория!