MDC-101 Android: podstawy komponentów Material Design (MDC) (Kotlin)

1. Wprowadzenie

logo_components_color_2x_web_96dp.png

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

4cb0c218948144b4.png

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?

Początkujący Średnio zaawansowany Zaawansowany

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

  1. 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.
  2. 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.
  3. 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.

KzoYWC1S7Se7yL8igi1vXF_mbVxAdl2lg5kb7RODrsVpEng0G6U3NK1Qnn0faBBZd2u71yMXioy9tD-7fv3NXvVO4N3EtMMeWDTmqBMMl6egd9R5uXX0T_SKmahbmRor3wZZHX0ByA

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ść.

  1. Otwórz plik build.gradle modułu app i upewnij się, że blok dependencies zawiera zależność od MDC na Androida:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (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

  1. Upewnij się, że konfiguracja kompilacji po lewej stronie przycisku Uruchom/Odtwórz to app.
  2. Aby skompilować i uruchomić aplikację, kliknij zielony przycisk Uruchom / Odtwórz.
  3. Jeśli w oknie Wybieranie miejsca docelowego wdrożenia na liście dostępnych urządzeń jest już widoczne urządzenie z Androidem, przejdź do kroku 8. W przeciwnym razie kliknij Utwórz nowe urządzenie wirtualne.
  4. Na ekranie Wybierz sprzęt wybierz telefon, na przykład Pixel 2, i kliknij Dalej.
  5. Na ekranie Obraz systemu wybierz najnowszą wersję Androida, najlepiej z najwyższym poziomem interfejsu API. Jeśli nie jest zainstalowana, kliknij widoczny link Pobierz i pobierz aplikację.
  6. Kliknij Dalej.
  7. Na ekranie Urządzenie wirtualne z Androidem (AVD) pozostaw ustawienia bez zmian i kliknij Zakończ.
  8. W oknie docelowym wdrożenia wybierz urządzenie z Androidem.
  9. Kliknij OK.
  10. Android Studio kompiluje aplikację, wdraża ją i automatycznie otwiera na urządzeniu docelowym.

Gotowe! Kod startowy strony logowania Shrine powinien być uruchomiony w Twoim emulatorze. Powinieneś zobaczyć nazwę „Shrine” i logo Shrine tuż pod nią.

e7ed014e84755811.png

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><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.

d83c47fb4aed3a82.png

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@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 na true elementu Password TextInputLayout. Spowoduje to dodanie dodatkowego odstępu dla komunikatu o błędzie pod polem tekstowym.
  • W elemencie Password TextInputEditText ustaw atrybut android: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:

333184b615aed4f7.gif

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.

4cb0c218948144b4.png

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.

9dd162d65e4a92a2.gif

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.

Udało mi się ukończyć to ćwiczenia z programowania w rozsądny sposób i w rozsądny sposób

Całkowicie się zgadzam Zgadzam się Nie mam zdania Nie zgadzam się Całkowicie się nie zgadzam

Chcę w przyszłości nadal używać komponentów Material Komponenty

Zdecydowanie się zgadzam Zdecydowanie się zgadzam Nie mam zdania Nie zgadzam się Zdecydowanie się nie zgadzam