1. Wprowadzenie
Material Komponenty (MDC) pomagają deweloperom wdrażać interfejs Material Design. MDC to biblioteka stworzona przez zespół inżynierów i projektantów UX w Google. Zawiera dziesiątki pięknych i funkcjonalnych komponentów UI. Jest dostępna na Androida, iOS, web i Flutter.material.io/develop |
Czym jest Material Design i Material Components na Androida?
Material Design to system do tworzenia odważnych i pięknych produktów cyfrowych. Łącząc styl, budowanie marki, interakcję i ruch w ramach spójnego zestawu zasad i komponentów, zespoły zajmujące się poszczególnymi produktami i usługami mogą w pełni wykorzystać swój potencjał projektowy.
W przypadku aplikacji na Androida składniki Material Design na Androida (MDC na Androida) łączą projektowanie i inżynierię z biblioteką komponentów, aby zapewnić spójność aplikacji. Wraz z rozwojem systemu Material Design komponenty te są aktualizowane, aby zapewnić spójne wdrożenie z zachowaniem dokładności do piksela i przestrzeganie standardów Google dotyczących tworzenia interfejsu. Narzędzie MDC jest też dostępne w przeglądarce, na iOS i w aplikacji Flutter.
W tym ćwiczeniu z programowania utworzysz stronę logowania, korzystając z kilku komponentów MDC na Androida.
Co utworzysz
To pierwsze z 4 laboratoriów kodu, które pomogą Ci stworzyć aplikację Shrine – aplikację e-commerce na Androida, która sprzedaje odzież i artykuły gospodarstwa domowego. Pokażemy, jak dostosowywać komponenty, aby pasowały do każdej marki i stylu za pomocą MDC na Androida.
W tym ćwiczeniu utworzysz stronę logowania do Shrine, która zawiera:
- Dwa pola tekstowe, jedno na wpisanie nazwy użytkownika, a drugie na hasło.
- Dwa przyciski: „Anuluj”, a drugi „Dalej”
- Nazwa aplikacji (świątynia)
- Obraz logo Shrine
Komponenty MDC na Androida w tym kursie programowania
- Pole tekstowe
- Przycisk
Czego potrzebujesz
- Podstawowa wiedza o programowaniu aplikacji na Androida
- Android Studio (pobierz tę aplikację stąd, jeśli jeszcze jej nie masz)
- emulator lub urządzenie z Androidem (dostępne w Android Studio).
- Przykładowy kod (patrz następny krok)
Jak oceniasz swój poziom doświadczenia w tworzeniu aplikacji na Androida?
2. Konfigurowanie środowiska programistycznego
Uruchom Android Studio
Gdy otworzysz Android Studio, powinno wyświetlić się okno „Welcome to Android Studio”. Jeśli jednak uruchamiasz Androida Studio po raz pierwszy, postępuj zgodnie z instrukcjami w kreatorze konfiguracji Android Studio, używając wartości domyślnych. Pobranie i zainstalowanie niezbędnych plików może potrwać kilka minut, więc w każdej sekcji możesz pozostawić je uruchomione w tle.
Pobierz aplikację Codelab dla początkujących
Aplikacja startowa znajduje się w katalogu material-components-android-codelabs-101-starter/kotlin
.
...lub skopiuj je z GitHuba
Aby skopiować to laboratorium programistyczne 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
Wczytywanie kodu startowego w Android Studio
- Gdy kreator zakończy konfigurację i zobaczy 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 -> Temple (lub wyszukaj na komputerze shrine), aby otworzyć projekt Shipping.
- Poczekaj chwilę, aż Android Studio utworzy i zsynchronizuje projekt. Postęp prac będzie widoczny na wskaźnikach aktywności u dołu okna Android Studio.
- W tym momencie Android Studio może wyświetlić błędy kompilacji, ponieważ brakuje pakietu Android SDK lub narzędzi do kompilacji, takich jak pokazane poniżej. Postępuj zgodnie z instrukcjami w Android Studio, aby zainstalować lub zaktualizować te biblioteki i zsynchronizować swój projekt.
Dodaj zależności projektu
Projekt musi być zależny od biblioteki obsługi MDC na Androida. Ta zależność powinna już być widoczna w pobranym przykładowym kodzie, ale warto wykonać te czynności, aby mieć pewność.
- Otwórz plik
build.gradle
modułuapp
i upewnij się, że blokdependencies
zawiera zależność od MDC na Androida:
api 'com.google.android.material:material:1.1.0-alpha06'
- (Opcjonalnie) W razie potrzeby zmodyfikuj plik
build.gradle
, aby dodać te zależności i zsynchronizować 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' }
Uruchomienie aplikacji startowej
|
Gotowe! Kod startowy strony logowania Shrine powinien być uruchomiony w Twoim emulatorze. Powinieneś zobaczyć nazwę „Shrine” i logo Shrine tuż pod nią.
Spójrzmy na kod. W przykładowym kodzie udostępniliśmy prosty Fragment
, który umożliwia wyświetlanie fragmentów i przechodzenie między nimi.
Otwórz MainActivity.kt
w katalogu shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.kotlin.shrine
. Powinien zawierać ten tekst:
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 plik układu R.layout.shr_main_activity
zdefiniowany w zasadzie shr_main_activity.xml
.
Jak widać, w onCreate(),
MainActivity.kt
inicjuje transakcję Fragment
, aby wyświetlić LoginFragment
. Na potrzeby tego ćwiczenia w programie wprowadzimy zmiany w dokumencie LoginFragment
. Aktywność implementuje też metodę navigateTo(Fragment)
zdefiniowaną w NavigationHost
, która umożliwia przechodzenie z jednego fragmentu do drugiego.
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ść.
Teraz otwórz 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
napełnia plik układu shr_login_fragment
i wyświetla go w onCreateView()
.
Przyjrzyjmy się teraz 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>
Tutaj widzimy <LinearLayout>
z <ImageView>
u góry, co oznacza logo Shrine.
Pod logo znajduje się tag <TextView>
, który reprezentuje etykietę Shrine. Tekst tej etykiety to zasób ciągu znaków o nazwie @string/shr_app_name
. Jeśli klikniesz Command + kliknięcie (lub Control + kliknięcie) nazwę zasobu ciągu znaków albo otworzysz plik app -> res -> values -> strings.xml
, zobaczysz plik strings.xml
, w którym zdefiniowano zasoby ciągu znaków. Gdy w przyszłości dodamy więcej zasobów w formacie tekstowym, zostaną one zdefiniowane tutaj. Każdy zasób w tym pliku powinien mieć prefiks shr_
, który wskazuje, że są częścią aplikacji Shrine.
Teraz, gdy znasz już kod startowy, zaimplementujmy nasz pierwszy komponent.
3. Dodaj pola tekstowe
Na początek dodamy do naszej strony logowania dwa pola tekstowe, w których użytkownicy będą mogli wpisać nazwę użytkownika i hasło. Wykorzystamy komponent Pole tekstowe MDC, który zawiera wbudowane funkcje wyświetlające pływającą etykietę i komunikaty o błędach.
Dodaj plik XML
W narzędziu shr_login_fragment.xml
dodaj dwa elementy TextInputLayout
z elementem podrzędnym TextInputEditText
w elemencie <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 reprezentuje 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ągu znaków dla pola tekstowego: @string/shr_hint_username
i @string/shr_hint_password
. Aby wyświetlić te zasoby ciągu znaków, otwórz strings.xml
.
strings.xml
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
Dodaj weryfikację danych wejściowych
TextInputLayout
uwzględniają wbudowaną funkcję zgłaszania błędów.
Aby wyświetlić komunikat o błędzie, wprowadź te zmiany w shr_login_fragment.xml
:
- Ustaw atrybut
app:errorEnabled
natrue
elementu PasswordTextInputLayout
. Spowoduje to dodanie dodatkowego odstępu dla komunikatu o błędzie pod polem tekstowym. - W elemencie Password
TextInputEditText
ustaw atrybutandroid:inputType
na „textPassword
”. Spowoduje to ukrycie tekstu wejściowego w polu hasła.
Po wprowadzeniu tych zmian pola tekstowe w sekwencji 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 uruchom aplikację. Powinna się wyświetlić strona z 2 polami tekstowymi „Nazwa użytkownika” i „Hasło”.
Zobacz animację etykiety pływającej:
4. Dodawanie przycisków
Następnie dodamy do strony logowania dwa przyciski: „Anuluj” i „Dalej”. Wykorzystamy komponent przycisku MDC, który ma wbudowany efekt fali atramentu w stylu Material Design.
Dodawanie pliku XML
W komponencie shr_login_fragment.xml
dodaj element <RelativeLayout>
do elementu <LinearLayout>
pod elementami TextInputLayout
. Następnie dodaj 2 elementy <MaterialButton>
do <RelativeLayout>
.
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. Po uruchomieniu aplikacji po dotknięciu każdego przycisku pojawi się fala atramentu.
5. Przejdź do następnego fragmentu
Na koniec dodamy do pliku LoginFragment.kt
kod Kotlin, aby połączyć przycisk „DALEJ” pozwalający przejść do kolejnego fragmentu.
Dodajmy w metodzie LoginFragment.kt
prywatną wartość logiczną isPasswordValid
w kodzie onCreateView()
, która pozwoli za pomocą logiki określić, czy hasło jest prawidłowe. Na potrzeby tego demonstracyjnego przykładu upewnimy się, że 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” odbiorczy kod reagujący na kliknięcie, który ustawia i wyczyścia błąd na podstawie właśnie utworzonej metody isPasswordValid()
. W onCreateView()
ten odbiornik kliknięć powinien znajdować się między linią inflatera a linią return view
.
Teraz dodajmy do hasła TextInputEditText
detektor klucza, aby nasłuchiwać kluczowych zdarzeń, które mogłyby spowodować usunięcie błędu. Ten detektor powinien też używać isPasswordValid()
do sprawdzania, czy hasło jest prawidłowe. Możesz go dodać bezpośrednio pod odbiornikiem kliknięć w onCreateView()
.
Twoja 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 przejdziemy do kolejnego fragmentu. W funkcji onCreateView()
zaktualizuj wartość OnClickListener
, aby po pomyślnej weryfikacji błędów przejść do innego fragmentu. Twój 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)
}
})
Dodaliśmy wiersz (
activity
as
NavigationHost).navigateTo(ProductGridFragment(),
false
)
do else
przypadku detektora kliknięć. Ten wiersz wywołuje metodę navigateTo()
z elementu MainActivity
, aby przejść do nowego fragmentu kodu – ProductGridFragment
. Obecnie jest to pusta strona, nad którą będziesz pracować w MDC-102.
Teraz skompiluj aplikację. Naciśnij przycisk Dalej.
Udało się! Ten ekran będzie punktem wyjścia dla kolejnego ćwiczenia z programowania, nad którymi będziesz pracować w ramach MDC-102.
6. Wszystko gotowe
Korzystając z podstawowego oznaczenia XML i około 30 wierszy kodu Kotlin, biblioteka Material Components for Android pomogła Ci utworzyć atrakcyjną stronę logowania, która jest zgodna ze wskazówkami dotyczącymi Material Design, a także wygląda i działa spójnie na wszystkich urządzeniach.
Dalsze kroki
Pole tekstowe i przycisk to 2 główne komponenty biblioteki MDC na Androida, ale jest ich znacznie więcej. Pozostałe komponenty MDC na Androida możesz sprawdzić w MDC na Androida. Możesz też otworzyć artykuł MDC 102: Material Design Struktura i układ, by 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 to ćwiczenie z programowania Ci się podobało.