1. Wprowadzenie
Material Komponenty (MDC) pomagają deweloperom wdrażać interfejs Material Design. MDC, stworzona przez zespół inżynierów i projektantów UX w Google, zawiera dziesiątki pięknych i funkcjonalnych komponentów interfejsu. Jest dostępny na Androida, iOS, internet oraz Flutter.material.io/develop |
Czym są interfejsy Material Design i Material Komponenty na Androida?
Material Design to system do tworzenia odważnych i atrakcyjnych 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 system Material Komponenty na Androida (MDC Android) łączy projekt i inżynierię z biblioteką komponentów, aby zapewnić spójność w każdej aplikacji. W miarę rozwoju systemu Material Design komponenty te są aktualizowane w celu zapewnienia spójnej implementacji pikseli i zgodności ze standardami Google dotyczącymi programowania interfejsów. Narzędzie MDC jest też dostępne w wersji internetowej, na iOS i w aplikacji Flutter.
W ramach tego ćwiczenia w Codelabs utworzysz stronę logowania, korzystając z kilku komponentów MDC na Androida.
Co utworzysz
To pierwsze z 4 ćwiczeń w Codelabs, które poprowadzą Cię przez proces tworzenia aplikacji o nazwie Shrine – e-commerce na Androida, w którym możesz kupić odzież i artykuły gospodarstwa domowego. Zademonstruje, jak dostosować komponenty pod kątem dowolnej marki lub stylu przy użyciu MDC-Android.
W ramach tego ćwiczenia w Codelabs utworzysz stronę logowania do Shrine, która zawiera:
- Dwa pola tekstowe, jedno na wpisanie nazwy użytkownika, a drugie na hasło.
- Dwa przyciski, jeden do „Anuluj” a drugi „Dalej”
- Nazwa aplikacji (świątynia)
- Obraz logo Shrine
Komponenty MDC na Androida w tym ćwiczeniu z 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 Androida lub urządzenie (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
Uruchamianie Androida Studio
Gdy otworzysz Android Studio, powinno wyświetlić się okno „Welcome to Android Studio”. Jeśli jednak uruchamiasz Androida Studio po raz pierwszy, wykonaj czynności opisane 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ę startową z programowania
Aplikacja startowa znajduje się w katalogu material-components-android-codelabs-101-starter/java
.
...lub skopiuj je z GitHuba
Aby skopiować to ćwiczenia z programowania 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 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 polecenie java -> świątynia (lub wyszukaj na komputerze shrine), aby otworzyć projekt Shrine.
- Poczekaj, aż Android Studio skompiluje i zsynchronizuje projekt, zgodnie ze wskaźnikami aktywności u dołu okna Android Studio.
- W tym momencie Android Studio może zgłaszać błędy kompilacji, ponieważ brakuje w nim pakietu Android SDK lub narzędzi do kompilacji, takich jak ten poniżej. Postępuj zgodnie z instrukcjami w Android Studio, aby zainstalować lub zaktualizować te aplikacje i zsynchronizować projekt.
Dodaj zależności projektu
Projekt musi być zależny od biblioteki pomocy MDC Android. Ta zależność powinna już być widoczna w pobranym przykładowym kodzie, ale warto wykonać te czynności, aby mieć pewność.
- Przejdź do pliku
build.gradle
modułuapp
i upewnij się, że blokdependencies
zawiera zależność od MDC na Androidzie:
api 'com.google.android.material:material:1.1.0-alpha06'
- (Opcjonalnie) W razie potrzeby zmodyfikuj plik
build.gradle
, aby dodać poniższe 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' }
Uruchamianie aplikacji startowej
|
Gotowe! Kod startowy strony logowania Shrine powinien być uruchomiony w Twoim emulatorze. Powinna być widoczna nazwa „Shrine”. i logo Shrine tuż pod nim.
Spójrzmy na kod. W przykładowym kodzie udostępniliśmy prostą platformę nawigacyjną Fragment
, która pozwala wyświetlać fragmenty i poruszać się między nimi.
Otwórz plik MainActivity.java
w katalogu shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.java.shrine
. Powinien zawierać ten tekst:
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();
}
}
Ta aktywność wyświetla plik układu R.layout.shr_main_activity
zdefiniowany w zasadzie shr_main_activity.xml
.
W aplikacji onCreate(),
MainActivity.java
rozpoczyna się transakcja Fragment
, aby wyświetlić LoginFragment
. LoginFragment.
To właśnie zmienimy w ramach tego ćwiczenia z programowania. Działanie to implementuje również metodę navigateTo(Fragment)
zdefiniowaną w zasadzie NavigationHost
, która umożliwia dowolnemu fragmentowi przechodzenie do innego fragmentu.
Użyj Command + Click (lub Control + Click) 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ść. Otwórzmy aplikację LoginFragment.java
.
LoginFragment.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
rozszerza plik układu shr_login_fragment
i wyświetla go w narzędziu onCreateView()
. 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" />
<!-- Snippet from "Add text fields" section goes here. -->
<!-- Snippet from "Add buttons" section goes here. -->
</LinearLayout>
</ScrollView>
Tutaj widzimy obiekt <LinearLayout>
z napisem <ImageView>
na górze, który reprezentuje „świątynię”. logo.
Następnie znajduje się tag <TextView>
reprezentujący wartość „SHRINE”. . Tekst tej etykiety to zasób ciągu znaków o nazwie @string/shr_app_name
. Jeśli naciśniesz Command + Click (lub Control + Click) nazwę zasobu ciągu tekstowego lub otworzysz 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 2 elementy TextInputLayout
z elementem podrzędnym TextInputEditText
w elemencie <LinearLayout>
, pod przyciskiem „SHRINE” etykieta <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>
Powyższy fragment kodu reprezentuje 2 pola tekstowe, każde z elementem <TextInputLayout>
i elementem podrzędnym <TextInputEditText>
. Tekst podpowiedzi dla każdego pola tekstowego jest określony w atrybucie android:hint
.
Dodaliśmy 2 nowe zasoby w postaci ciągów tekstowych w polu tekstowym – @string/shr_hint_username
i @string/shr_hint_password
. Otwórz plik strings.xml
, aby zobaczyć te zasoby ciągów znaków.
strings.xml
...
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
...
Dodaj weryfikację danych wejściowych
Komponenty TextInputLayout
mają wbudowaną funkcję przesyłania informacji o błędach.
Aby wyświetlić komunikat o błędzie, wprowadź te zmiany w shr_login_fragment.xml
:
- Ustaw atrybut
app:errorEnabled
na „true” dla elementu PasswordTextInputLayout
(Hasło). Spowoduje to dodanie dodatkowego dopełnienia komunikatu o błędzie pod polem tekstowym. - Ustaw wartość atrybutu
android:inputType
na „textPassword
” w elemencie PasswordTextInputEditText
. Spowoduje to ukrycie tekstu wpisywanego w polu hasła.
Po wprowadzeniu tych zmian pola tekstowe w polu 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"
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>
Teraz spróbuj uruchomić aplikację. Powinna wyświetlić się strona z 2 polami tekstowymi „Nazwa użytkownika”. i „Hasło”.
Zobacz animację pływającej etykiety:
4. Dodaj przyciski
Następnie dodamy do naszej strony logowania dwa przyciski: „Anuluj” i „Dalej”. Wykorzystamy komponent przycisku MDC, który ma wbudowany efekt fali atramentu w stylu Material Design.
Dodaj plik XML
W narzędziu 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. Gdy uruchomisz aplikację, po kliknięciu każdego przycisku pojawi się fala atramentu.
5. Przejdź do następnego fragmentu
Na koniec dodajemy do języka LoginFragment.java
kod w Javie, żeby połączyć do innego fragmentu. Jak widać, do każdego komponentu, który dodaliśmy do układu, jest przypisany element id
. Wykorzystamy te obiekty typu id
, aby odwołać się do komponentów w naszym kodzie i dodać pewne błędy dotyczące sprawdzania błędów oraz nawigacji.
Dodajmy w metodzie LoginFragment.java
prywatną wartość logiczną isPasswordValid
w polu onCreateView()
, używając logiki do określenia, czy hasło jest prawidłowe. Na potrzeby tej prezentacji zadbamy tylko o to, aby hasło miało co najmniej 8 znaków:
LoginFragment.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;
}
Następnie dodaj detektor kliknięć do sekcji „Dalej” który ustawia i usuwa błąd na podstawie utworzonej przed chwilą metody isPasswordValid()
. W onCreateView()
ten detektor kliknięć powinien znajdować się między linią nadrzędną a linią return view
.
Teraz dodajmy do hasła TextInputEditText
detektor klucza, aby nasłuchiwać kluczowych zdarzeń, które mogą 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 detektorem kliknięć w usłudze onCreateView()
.
Twoja metoda onCreateView() powinna teraz wyglądać mniej więcej tak:
LoginFragment.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;
}
Teraz przejdziemy do kolejnego fragmentu. Zaktualizuj pole OnClickListener
w pliku onCreateView()
, aby przejść do innego fragmentu po pomyślnej weryfikacji błędu. Możesz to zrobić, dodając ten wiersz, by przejść do ProductGridFragment
do przypadku else
detektora kliknięć:
LoginFragment.java
...
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
...
Detektor kliknięć powinien teraz wyglądać tak:
LoginFragment.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
}
}
});
...
Ten nowy wiersz kodu wywołuje metodę navigateTo()
z MainActivity
, aby przejść do nowego fragmentu – ProductGridFragment
. Obecnie jest to pusta strona, nad którą będziesz pracować w narzędziu MDC-102.
Teraz stwórz aplikację. Kliknij 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
Dzięki podstawowym znacznikom XML i ok. 30 wierszom kodu Java biblioteka Material Komponenty dla Androida pomaga stworzyć piękną 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 główne komponenty biblioteki MDC na Androida, ale jest ich znacznie więcej. Możesz zapoznać się z pozostałymi komponentami MDC na Androida. Możesz też przejść do artykułu 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 narzędzia Material Komponenty. Mamy nadzieję, że to ćwiczenie z programowania Ci się podobało.