1. Introduction
Material Components (MDC) aide les développeurs à implémenter Material Design. Conçu par une équipe d'ingénieurs et de spécialistes de l'expérience utilisateur chez Google, MDC propose des dizaines de composants d'interface utilisateur élégants et fonctionnels. Il est disponible pour Android, iOS, le Web et Flutter.material.io/develop. |
Que sont Material Design et Material Components pour Android ?
Material Design est un système permettant de créer des produits numériques audacieux et esthétiques. Les équipes produit peuvent ainsi réaliser leurs meilleurs graphismes en combinant style, branding, interactions et animations selon des principes communs et des composants harmonieux.
Pour les applications Android, Material Components for Android (MDC Android) allie la conception et l'ingénierie à une bibliothèque de composants pour assurer la cohérence de votre application. À mesure que le système Material Design évolue, ces composants sont mis à jour afin de garantir une implémentation homogène au pixel près et le respect des normes de développement front-end de Google. MDC est également disponible pour le Web, iOS et Flutter.
Dans cet atelier de programmation, vous allez créer une page de connexion à l'aide de plusieurs composants de MDC Android.
Objectifs de l'atelier
Cet atelier de programmation est le premier d'une série de quatre ateliers de programmation qui vous aideront à créer une application appelée Shrine, une application d'e-commerce Android pour la vente de vêtements et d'articles pour la maison. Il vous montrera comment personnaliser les composants pour refléter n'importe quelle marque ou style à l'aide de MDC-Android.
Dans cet atelier de programmation, vous créerez une page de connexion pour Shrine contenant :
- Deux champs de texte, un pour le nom d'utilisateur et l'autre pour un mot de passe
- Deux boutons, un pour "Annuler" et une pour "Suivant"
- Le nom de l'application (Shrine)
- Image du logo Shrine
Composants Android de MDC dans cet atelier de programmation
- Champ de texte
- Bouton
Prérequis
- Connaissances de base sur le développement Android
- Android Studio (téléchargez-le ici si vous ne l'avez pas déjà fait)
- Un émulateur ou un appareil Android (disponible via Android Studio)
- L'exemple de code (voir l'étape suivante)
Comment évalueriez-vous votre niveau d'expérience en création d'applications Android ?
<ph type="x-smartling-placeholder">2. Configurer l'environnement de développement
Démarrer Android Studio
Lorsque vous ouvrez Android Studio, une fenêtre de bienvenue s'affiche. Toutefois, si vous lancez Android Studio pour la première fois, suivez les étapes de l'assistant de configuration Android Studio en conservant les valeurs par défaut. Le téléchargement et l'installation des fichiers nécessaires peuvent prendre plusieurs minutes. Par conséquent, n'hésitez pas à passer à la section suivante en laissant ces opérations s'exécuter en arrière-plan.
Télécharger l'application de départ de l'atelier de programmation
Elle se trouve dans le répertoire material-components-android-codelabs-101-starter/java
.
… ou cloner l'atelier depuis GitHub
Pour cloner cet atelier de programmation à partir de GitHub, exécutez les commandes suivantes :
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 101-starter
Charger le code de départ dans Android Studio
- Une fois l'assistant de configuration terminé et la fenêtre de bienvenue dans Android Studio affichée, cliquez sur Open an existing Android Studio project (Ouvrir un projet Android Studio existant). Accédez au répertoire dans lequel vous avez installé l'exemple de code, puis sélectionnez java -> sanctuaire (ou recherchez shrine sur votre ordinateur) pour ouvrir le projet Shrine.
- Attendez qu'Android Studio crée et synchronise le projet (voir les indicateurs d'activité situés en bas de la fenêtre Android Studio).
- À ce stade, Android Studio peut générer des erreurs de compilation, car vous ne disposez pas du SDK Android ni de certains outils de compilation, comme celui présenté ci-dessous. Suivez les instructions fournies dans Android Studio pour installer/mettre à jour ces éléments et synchroniser votre projet.
Ajouter des dépendances de projet
Le projet a besoin d'une dépendance sur la bibliothèque Support MDC pour Android. Cette dépendance devrait déjà être listée dans l'exemple de code que vous avez téléchargé, mais il est recommandé de suivre les étapes ci-dessous pour vous en assurer.
- Accédez au fichier
build.gradle
du moduleapp
et assurez-vous que le blocdependencies
inclut une dépendance sur MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
- (Facultatif) Si nécessaire, modifiez le fichier
build.gradle
pour ajouter les dépendances suivantes et synchroniser le projet.
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' }
Exécuter l'application de départ
|
Opération réussie. Le code de démarrage de la page de connexion de Shrine doit s'exécuter dans votre émulateur. Vous devriez voir le nom "Shrine". et le logo Shrine juste en dessous.
Voyons à présent le code. Nous avons fourni un framework de navigation Fragment
simple dans notre exemple de code pour afficher les fragments et naviguer entre eux.
Ouvrez MainActivity.java
dans le répertoire shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.java.shrine
. Il doit contenir les éléments suivants :
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();
}
}
Cette activité affiche le fichier de mise en page R.layout.shr_main_activity
, défini dans shr_main_activity.xml
.
Vous pouvez voir que dans onCreate(),
, MainActivity.java
lance une transaction Fragment
pour afficher le LoginFragment
. LoginFragment.
C'est ce que nous allons modifier dans cet atelier de programmation. L'activité implémente également une méthode navigateTo(Fragment)
, définie dans NavigationHost
, qui permet à tout fragment d'accéder à un autre fragment.
Commande+clic (ou Ctrl+clic) shr_main_activity
dans le fichier d'activité pour ouvrir le fichier de mise en page, ou accédez au fichier de mise en page dans 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" />
Ici, nous voyons un simple <FrameLayout>
qui sert de conteneur pour tous les fragments affichés par l'activité. Ouvrons 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
gonfle le fichier de mise en page shr_login_fragment
et l'affiche dans onCreateView()
. Examinons le fichier de mise en page shr_login_fragment.xml
pour voir à quoi ressemble la page de connexion.
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>
Ici, nous pouvons voir un <LinearLayout>
avec un <ImageView>
en haut, qui représente la "Shrine" .
Ensuite, une balise <TextView>
représente le "SHRINE". libellé. Le texte de ce libellé est une ressource de chaîne nommée @string/shr_app_name
. Si vous appuyez sur Commande+Clic (ou en appuyant sur Ctrl+Clic) sur le nom de la ressource de chaîne ou si vous ouvrez app -> res -> values -> strings.xml
, vous pouvez voir le fichier strings.xml
, dans lequel les ressources de chaîne sont définies. Lorsque d'autres ressources de chaîne seront ajoutées ultérieurement, elles seront définies ici. Chaque ressource de ce fichier doit comporter le préfixe shr_
pour indiquer qu'elle fait partie de l'application Shrine.
Maintenant que vous connaissez le code de démarrage, vous pouvez implémenter notre premier composant.
3. Ajouter des champs de texte
Pour commencer, nous allons ajouter deux champs de texte à notre page de connexion pour que les utilisateurs puissent saisir leur nom d'utilisateur et leur mot de passe. Nous allons utiliser le composant de champ de texte MDC, qui inclut une fonctionnalité intégrée permettant d'afficher un libellé flottant et des messages d'erreur.
Ajouter le fichier XML
Dans shr_login_fragment.xml
, ajoutez deux éléments TextInputLayout
avec un TextInputEditText
enfant à l'intérieur de <LinearLayout>
, sous la section "SHRINE". libellé <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>
L'extrait ci-dessus représente deux champs de texte, chacun composé d'un élément <TextInputLayout>
et d'un enfant <TextInputEditText>
. Le texte d'aide pour chaque champ de texte est spécifié dans l'attribut android:hint
.
Nous avons inclus deux nouvelles ressources de chaîne pour le champ de texte : @string/shr_hint_username
et @string/shr_hint_password
. Ouvrez strings.xml
pour afficher ces ressources de chaîne.
strings.xml
...
<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>
...
Ajouter une validation des entrées
Les composants TextInputLayout
intègrent une fonctionnalité de retour d'erreur.
Pour afficher les commentaires d'erreur, apportez les modifications suivantes à shr_login_fragment.xml
:
- Définissez l'attribut
app:errorEnabled
sur "true" dans l'élémentTextInputLayout
Password (Mot de passe). Cela ajoutera une marge intérieure supplémentaire pour le message d'erreur sous le champ de texte. - Définissez l'attribut
android:inputType
sur "textPassword
" dans l'élément PasswordTextInputEditText
(Mot de passe). Le texte saisi dans le champ du mot de passe est alors masqué.
Avec ces modifications, les champs de texte dans shr_login_fragment.xml
devraient se présenter comme suit:
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>
Essayez maintenant d'exécuter l'application. Vous devriez voir une page avec deux champs de texte pour le nom d'utilisateur. et "Mot de passe" !
Regardez l'animation du libellé flottant :
4. Ajouter des boutons
Nous allons ensuite ajouter deux boutons sur notre page de connexion : "Cancel" (Annuler) et "Next" (Suivant). Nous allons utiliser le composant MDC Button, qui intègre l'emblématique effet d'ondulation d'encre Material Design.
Ajouter le fichier XML
Dans shr_login_fragment.xml
, ajoutez un <RelativeLayout>
à <LinearLayout>
, sous les éléments TextInputLayout
. Ajoutez ensuite deux éléments <MaterialButton>
à <RelativeLayout>
.
Le fichier XML obtenu doit se présenter comme suit:
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>
Et voilà ! Lorsque vous exécutez l'application, une ondulation d'encre s'affiche lorsque vous appuyez sur chaque bouton.
5. Accéder au fragment suivant
Enfin, nous ajouterons du code Java à LoginFragment.java
pour relier notre "NEXT" à un autre fragment. Vous remarquerez que chacun des composants que nous avons ajoutés à notre mise en page est associé à un id
. Nous utiliserons ces id
pour référencer les composants de notre code, et ajouter une vérification des erreurs et une navigation.
Ajoutons une méthode booléenne privée isPasswordValid
dans LoginFragment.java
sous onCreateView()
, avec une logique pour déterminer si le mot de passe est valide ou non. Pour les besoins de cette démonstration, nous allons simplement nous assurer que le mot de passe comporte au moins huit caractères:
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;
}
Ajoutez ensuite un écouteur de clics qui définit et supprime l'erreur en fonction de la méthode isPasswordValid()
que nous venons de créer. Dans onCreateView()
, cet écouteur de clics doit être placé entre la ligne de gonflage et la ligne return view
.
Ajoutons ensuite un écouteur de touches au mot de passe TextInputEditText
pour écouter les événements clés qui effacent l'erreur. Cet écouteur doit également utiliser isPasswordValid()
pour vérifier si le mot de passe est valide ou non. Vous pouvez l'ajouter directement sous l'écouteur de clics dans onCreateView()
.
Votre méthode onCreateView() devrait maintenant se présenter comme suit:
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;
}
Nous pouvons maintenant accéder à un autre fragment. Mettez à jour OnClickListener
dans onCreateView()
pour accéder à un autre fragment lorsque la validation de l'erreur aboutit. Pour ce faire, ajoutez la ligne suivante pour accéder à ProductGridFragment
dans le cas else
de l'écouteur de clics:
LoginFragment.java
...
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
...
Votre écouteur de clics devrait maintenant se présenter comme suit:
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
}
}
});
...
Cette nouvelle ligne de code appelle la méthode navigateTo()
à partir de MainActivity
pour accéder à un nouveau fragment : ProductGridFragment
. Il s'agit actuellement d'une page vide sur laquelle vous allez travailler dans MDC-102.
Maintenant, créez l'application. Allez-y, cliquez sur le bouton "Suivant".
Bravo ! Cet écran constitue le point de départ de notre prochain atelier de programmation sur lequel vous allez travailler dans MDC-102.
6. Terminé
Grâce au balisage XML de base et à environ 30 lignes de code Java, la bibliothèque Material Components pour Android vous a aidé à créer une belle page de connexion conforme aux consignes Material Design, et à s'afficher et se comporter de manière cohérente sur tous les appareils.
Étapes suivantes
Le champ de texte et le bouton sont deux composants principaux de la bibliothèque Android MDC, mais il en existe beaucoup d'autres. Vous pouvez explorer les autres composants de MDC Android. Vous pouvez également accéder à MDC 102: Structure et mise en page Material Design pour en savoir plus sur la barre d'application supérieure, la vue Fiche et la mise en page sous forme de grille. Merci d'avoir essayé Material Components. Nous espérons que cet atelier de programmation vous a plu.