Komponenty Material (MDC) pomagają deweloperom wdrażać Material Design. MDC to stworzona przez zespół inżynierów i projektantów UX z Google biblioteka zawierająca dziesiątki atrakcyjnych i funkcjonalnych komponentów interfejsu. Jest dostępna na platformy Android, iOS, internet i Flutter. material.io/develop |
Czym są Material Design i Material Components na Androida?
Material Design to system tworzenia atrakcyjnych i funkcjonalnych produktów cyfrowych. Łącząc styl, branding, interakcje i animacje w spójny zestaw zasad i komponentów, zespoły produktowe mogą w pełni wykorzystać swój potencjał projektowy.
W przypadku aplikacji na Androida Material Components for Android(MDC Android) łączy projektowanie i inżynierię z biblioteką komponentów, aby zapewnić spójność w aplikacji. Wraz z rozwojem systemu Material Design komponenty te są aktualizowane, aby zapewnić spójną implementację z dokładnością do piksela i zgodność ze standardami Google dotyczącymi tworzenia interfejsu. MDC jest też dostępny w przypadku internetu, iOS i Fluttera.
W tym ćwiczeniu z programowania utworzysz stronę logowania za pomocą kilku komponentów MDC Androida.
Co utworzysz
Te warsztaty to pierwsze z 4 części, które pomogą Ci w tworzeniu aplikacji o nazwie Shrine. Jest to aplikacja e-commerce na Androida, która służy do sprzedaży odzieży i artykułów gospodarstwa domowego. Dowiesz się z niego, jak dostosowywać komponenty, aby odzwierciedlały dowolną markę lub styl przy użyciu MDC Android.
W tym ćwiczeniu utworzysz stronę logowania do aplikacji Shrine, która będzie zawierać:
- Dwa pola tekstowe: jedno do wpisania nazwy użytkownika, a drugie do wpisania hasła.
- 2 przyciski: „Anuluj” i „Dalej”.
- Nazwa aplikacji (Shrine)
- Obraz logo Shrine
Komponenty MDC Android użyte w tym kursie
- Pole tekstowe
- Przycisk
Czego potrzebujesz
- Podstawowa wiedza na temat programowania aplikacji na Androida
- Android Studio (jeśli nie masz jeszcze tego środowiska, pobierz je tutaj)
- emulator lub urządzenie z Androidem (dostępne w Android Studio);
- Przykładowy kod (patrz następny krok)
Jak oceniasz swoje doświadczenie w tworzeniu aplikacji na Androida?
Uruchamianie Androida Studio
Po otwarciu Android Studio powinno się wyświetlić okno „Welcome to Android Studio” (Witamy w Android Studio). Jeśli jednak uruchamiasz Android Studio po raz pierwszy, wykonaj czynności opisane w Kreatorze konfiguracji Androida Studio, używając wartości domyślnych. Pobranie i zainstalowanie niezbędnych plików może potrwać kilka minut, więc możesz pozostawić ten proces w tle i przejść do następnej sekcji.
Pobieranie aplikacji do ćwiczeń z programowania
Aplikacja startowa znajduje się w katalogu material-components-android-codelabs-101-starter/kotlin
.
...lub sklonuj go z GitHub
Aby sklonować ten codelab z GitHuba, uruchom te polecenia:
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 101-starter
Wczytaj kod startowy w Android Studio
- Gdy kreator konfiguracji zakończy działanie i wyświetli się okno Witamy w Android Studio, kliknij Otwórz istniejący projekt Android Studio. Przejdź do katalogu, w którym został zainstalowany przykładowy kod, i wybierz kotlin –> shrine(lub wyszukaj na komputerze shrine), aby otworzyć projekt Shipping.
- Poczekaj chwilę, aż Android Studio utworzy i zsynchronizuje projekt. Wskaźniki aktywności w dolnej części okna Android Studio będą pokazywać postęp.
- W tym momencie Android Studio może zgłosić błędy kompilacji, ponieważ brakuje Ci pakietu SDK Androida lub narzędzi do kompilacji, np. takich jak te pokazane poniżej. Postępuj zgodnie z instrukcjami w Android Studio, aby zainstalować lub zaktualizować te komponenty i zsynchronizować projekt.
Dodawanie zależności projektu
Projekt musi być zależny od biblioteki pomocy MDC na Androida. Pobrany przykładowy kod powinien już zawierać tę zależność, ale warto wykonać poniższe czynności, aby się upewnić.
- Otwórz plik
build.gradle
modułuapp
i upewnij się, że blokdependencies
zawiera zależność od MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
- (Opcjonalnie) W razie potrzeby edytuj plik
build.gradle
, aby dodać te zależności, i zsynchronizuj projekt.
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' }
Uruchom aplikację startową
|
Gotowe! Kod początkowy strony logowania Shrine powinien być uruchomiony w emulatorze. Powinna się wyświetlić nazwa „Shrine” i logo Shrine tuż pod nią.
Przyjrzyjmy się kodowi. W przykładowym kodzie udostępniliśmy prostą Fragment
strukturę nawigacji, która umożliwia wyświetlanie fragmentów i przechodzenie między nimi.
Otwórz plik MainActivity.kt
w katalogu shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.kotlin.shrine
. Powinien zawierać te informacje:
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()
}
}
Ta aktywność wyświetla R.layout.shr_main_activity
plik układu zdefiniowany w shr_main_activity.xml
.
Możesz to zobaczyć w onCreate(),
. MainActivity.kt
rozpoczyna transakcję Fragment
, aby wyświetlić LoginFragment
. W tym ćwiczeniu zmodyfikujemy plik LoginFragment
. Aktywność implementuje też metodę navigateTo(Fragment)
zdefiniowaną w NavigationHost
, która umożliwia dowolnemu fragmentowi przejście do innego fragmentu.
Command + kliknięcie (lub Control + kliknięcie) shr_main_activity
w pliku aktywności, aby otworzyć plik układu, lub przejdź do pliku układu w 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"/>
Widzimy tu prosty element <FrameLayout>
, który służy jako kontener dla wszystkich fragmentów wyświetlanych przez aktywność.
Następnie otwórzmy 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
rozszerza plik układu shr_login_fragment
i wyświetla go w onCreateView()
.
Teraz przyjrzyjmy się plikowi układu shr_login_fragment.xml
, aby zobaczyć, jak wygląda strona logowania.
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>
Widzimy tu <LinearLayout>
z <ImageView>
u góry, co symbolizuje logo świątyni.
Pod logo znajduje się tag <TextView>
reprezentujący etykietę Shrine. Tekst tej etykiety to zasób tekstowy o nazwie @string/shr_app_name
. Jeśli klikniesz nazwę zasobu ciągu znaków z naciśniętym klawiszem Command (lub Control) albo otworzysz plik app -> res -> values -> strings.xml
, zobaczysz plik strings.xml
, w którym zdefiniowane są zasoby ciągu znaków. Gdy w przyszłości dodamy więcej zasobów ciągów tekstowych, będą one zdefiniowane w tym miejscu. Każdy zasób w tym pliku powinien mieć prefiks shr_
, aby wskazywać, że jest częścią aplikacji Shrine.
Znasz już kod początkowy, więc teraz zaimplementujmy pierwszy komponent.
Na początek dodamy do strony logowania 2 pola tekstowe, w których użytkownicy będą mogli wpisać nazwę użytkownika i hasło. Użyjemy komponentu MDC Text Field, który ma wbudowaną funkcję wyświetlania pływającej etykiety i komunikatów o błędach.
Dodawanie pliku XML
W sekcji shr_login_fragment.xml
dodaj 2 elementy TextInputLayout
z elementem podrzędnym TextInputEditText
w sekcji <LinearLayout>
pod etykietą „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>
Powyższy fragment kodu zawiera 2 pola tekstowe, z których każde składa się z elementu <TextInputLayout>
i elementu podrzędnego <TextInputEditText>
. Tekst podpowiedzi w każdym polu tekstowym jest określony w atrybucie android:hint
.
Dodaliśmy 2 nowe zasoby ciągów znaków dla pola tekstowego – @string/shr_hint_username
i @string/shr_hint_password
. Otwórz strings.xml
, aby wyświetlić te zasoby ciągów znaków.
strings.xml
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
Dodawanie weryfikacji danych wejściowych
Komponenty TextInputLayout
mają wbudowaną funkcję przekazywania informacji o błędach.
Aby wyświetlać informacje o błędach, wprowadź w pliku shr_login_fragment.xml
te zmiany:
- Ustaw atrybut
app:errorEnabled
natrue
w elemencie HasłoTextInputLayout
. Spowoduje to dodanie dodatkowego dopełnienia komunikatu o błędzie pod polem tekstowym. - Ustaw atrybut
android:inputType
na „textPassword
” w elemencie HasłoTextInputEditText
. Spowoduje to ukrycie wpisanego tekstu w polu hasła.
Po wprowadzeniu tych zmian pola tekstowe w shr_login_fragment.xml
powinny wyglądać tak:
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>
Teraz spróbuj uruchomić aplikację. Powinna pojawić się strona z 2 polami tekstowymi: „Nazwa użytkownika” i „Hasło”.
Sprawdź animację etykiety pływającej:
Następnie dodamy do strony logowania 2 przyciski: „Anuluj” i „Dalej”. Użyjemy komponentu MDC Button, który ma wbudowany charakterystyczny efekt fali atramentu Material Design.
Dodawanie pliku XML
W sekcji shr_login_fragment.xml
dodaj <RelativeLayout>
do <LinearLayout>
pod elementami TextInputLayout
. Następnie dodaj do elementu <RelativeLayout>
2 elementy <MaterialButton>
.
Wynikowy plik XML powinien wyglądać tak:
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>
Znakomicie. Gdy uruchomisz aplikację, po kliknięciu każdego przycisku pojawi się efekt rozchodzącego się atramentu.
Na koniec dodamy kod Kotlin do pliku LoginFragment.kt
, aby połączyć przycisk „DALEJ” z przejściem do innego fragmentu.
Dodajmy prywatną metodę logiczną isPasswordValid
w LoginFragment.kt
pod onCreateView()
, która będzie określać, czy hasło jest prawidłowe. Na potrzeby tej wersji demonstracyjnej sprawdzimy tylko, czy hasło ma co najmniej 8 znaków:
LoginFragment.kt
private fun isPasswordValid(text: Editable?): Boolean {
return text != null && text.length >= 8
}
Następnie dodaj do przycisku „Dalej” odbiornik kliknięć, który ustawia i usuwa błąd na podstawie utworzonej przez nas metody isPasswordValid()
. W onCreateView()
ten odbiornik kliknięć powinien znajdować się między wierszem inflatora a wierszem return view
.
Teraz dodajmy detektor klawiszy do pola hasła TextInputEditText
, aby nasłuchiwać zdarzeń klawiszy, które spowodują usunięcie błędu. Ten odbiornik powinien też używać funkcji isPasswordValid()
, aby sprawdzić, czy hasło jest prawidłowe. Możesz dodać ten kod bezpośrednio pod elementem nasłuchującym kliknięć w onCreateView()
.
Metoda onCreateView() powinna teraz wyglądać mniej więcej tak:
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
}
}
Teraz możemy przejść do innego fragmentu. W onCreateView()
zaktualizuj OnClickListener
, aby po pomyślnej weryfikacji błędu przejść do innego fragmentu. Kod clickListener
powinien teraz wyglądać tak:
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)
}
})
Do else
przypadku detektora kliknięć dodaliśmy wiersz (
activity
as
NavigationHost).navigateTo(ProductGridFragment(),
false
)
. Ten wiersz wywołuje metodę navigateTo()
z MainActivity
, aby przejść do nowego fragmentu – ProductGridFragment
. Obecnie jest to pusta strona, nad którą będziesz pracować w module MDC-102.
Teraz skompiluj aplikację. Kliknij przycisk Dalej.
Udało się! Ten ekran będzie punktem wyjścia do kolejnego modułu, nad którym będziesz pracować w MDC-102.
Korzystając z podstawowego znacznika XML i około 30 wierszy kodu w języku Kotlin, biblioteka Material Components for Android pomogła Ci utworzyć atrakcyjną stronę logowania, która jest zgodna z wytycznymi Material Design, a także wygląda i działa spójnie na wszystkich urządzeniach.
Dalsze kroki
Pole tekstowe i przycisk to 2 podstawowe komponenty biblioteki MDC Android, ale jest ich znacznie więcej. Pozostałe komponenty w MDC Android możesz sprawdzić tutaj. Możesz też zapoznać się z artykułem MDC 102: Material Design Structure and Layout, aby dowiedzieć się więcej o górnym pasku aplikacji, widoku kart i układzie siatki. Dziękujemy za wypróbowanie komponentów Material. Mamy nadzieję, że te ćwiczenia z programowania były przydatne.