MDC-101 Android: Kiến thức cơ bản về Thành phần Material (MDC) (Kotlin)

1. Giới thiệu

logo_components_color_2x_web_96dp.png

Thành phần Material (MDC) giúp nhà phát triển triển khai Material Design. Được tạo bởi một nhóm các kỹ sư và nhà thiết kế trải nghiệm người dùng tại Google, MDC có hàng chục thành phần giao diện người dùng đẹp mắt, dễ sử dụng và được cung cấp cho Android, iOS, web và Flutter.material.io/develop

Material Design và Material Components cho Android là gì?

Material Design là một hệ thống để xây dựng các sản phẩm kỹ thuật số táo bạo và đẹp mắt. Bằng cách hợp nhất phong cách, cách xây dựng thương hiệu, sự tương tác và chuyển động theo một bộ nguyên tắc và thành phần nhất quán, các nhóm phụ trách sản phẩm có thể phát hiện ra tiềm năng thiết kế lớn nhất của họ.

Đối với các ứng dụng Android, Material Components cho Android (MDC Android) hợp nhất thiết kế và kỹ thuật với một thư viện thành phần nhằm tạo sự nhất quán trên ứng dụng. Khi hệ thống Material Design phát triển, những thành phần này sẽ được cập nhật để đảm bảo việc triển khai pixel một cách hoàn hảo và tuân thủ các tiêu chuẩn phát triển giao diện người dùng của Google. MDC cũng được cung cấp cho web, iOS và Flutter.

Trong lớp học lập trình này, bạn sẽ xây dựng một trang đăng nhập bằng cách sử dụng một số thành phần của MDC Android.

Sản phẩm bạn sẽ tạo ra

Lớp học lập trình này là lớp đầu tiên trong số 4 lớp học lập trình sẽ hướng dẫn bạn xây dựng một ứng dụng có tên là Shrine. Đây là một ứng dụng thương mại điện tử dành cho Android, chuyên bán quần áo và đồ gia dụng. Hướng dẫn này sẽ minh hoạ cách bạn có thể tuỳ chỉnh các thành phần để phản ánh bất kỳ thương hiệu hoặc phong cách nào bằng MDC Android.

Trong lớp học lập trình này, bạn sẽ xây dựng một trang đăng nhập cho Shrine chứa:

  • Hai trường văn bản, một trường để nhập tên người dùng và trường còn lại để nhập mật khẩu
  • Hai nút, một nút "Huỷ" và một nút "Tiếp theo"
  • Tên ứng dụng (Đền)
  • Hình ảnh biểu trưng của Đền thờ

4cb0c218948144b4.png.

Các thành phần Android MDC trong lớp học lập trình này

  • Trường văn bản
  • Nút

Bạn cần có

  • Kiến thức cơ bản về phát triển Android
  • Android Studio (tải xuống tại đây nếu bạn chưa có)
  • Trình mô phỏng hoặc thiết bị Android (có sẵn thông qua Android Studio)
  • Mã mẫu (xem bước tiếp theo)

Bạn đánh giá thế nào về mức độ kinh nghiệm của mình trong việc xây dựng ứng dụng Android?

Tân binh Trung cấp Thành thạo

2. Thiết lập môi trường phát triển

Khởi động Android Studio

Khi bạn mở Android Studio, một cửa sổ có tiêu đề "Welcome to Android Studio" (Chào mừng bạn đến với Android Studio) sẽ xuất hiện. Tuy nhiên, nếu đây là lần đầu tiên bạn chạy Android Studio, hãy làm theo các bước trong Trình hướng dẫn thiết lập Android Studio với các giá trị mặc định. Bước này có thể mất vài phút để tải xuống và cài đặt các tệp cần thiết, vì vậy hãy để ứng dụng này chạy dưới nền trong khi thực hiện phần tiếp theo.

Tải ứng dụng ban đầu của lớp học lập trình xuống

Ứng dụng khởi đầu này nằm trong thư mục material-components-android-codelabs-101-starter/kotlin.

...hoặc sao chép từ GitHub

Để sao chép lớp học lập trình này từ GitHub, hãy chạy các lệnh sau:

git clone https://github.com/material-components/material-components-android-codelabs
cd material-components-android-codelabs/
git checkout 101-starter

Tải mã khởi đầu trong Android Studio

  1. Sau khi trình hướng dẫn thiết lập hoàn tất và cửa sổ Welcome to Android Studio (Chào mừng bạn đến với Android Studio) xuất hiện, hãy nhấp vào Open an existing Android Studio project (Mở một dự án hiện có trong Android Studio). Chuyển đến thư mục nơi bạn đã cài đặt mã mẫu rồi chọn kotlin -> Shrine (hoặc tìm kiếm shrine trên máy tính) để mở dự án Vận chuyển.
  2. Chờ một lát để Android Studio tạo và đồng bộ hoá dự án, như được hiển thị bằng các chỉ báo hoạt động ở cuối cửa sổ Android Studio.
  3. Tại thời điểm này, Android Studio có thể phát sinh một số lỗi bản dựng do bạn đang thiếu SDK Android hoặc công cụ xây dựng, chẳng hạn như lỗi hiển thị dưới đây. Làm theo hướng dẫn trong Android Studio để cài đặt/cập nhật các SDK này và đồng bộ hoá dự án.

KzoYWC1S7Se7yL8igi1vXF_mbVxAdl2lg5kb7RODrsVpEng0G6U3NK1Qnn0faBBZd2u71yMXioy9tD-7fv3NXvVO4N3EtMMeWDTmqBMMl6egd9R5uXX0T_SKmahbmRor3wZZHX0ByA

Thêm phần phụ thuộc của dự án

Dự án cần có phần phụ thuộc trên thư viện hỗ trợ MDC Android. Mã mẫu mà bạn tải xuống phải có phần phụ thuộc này, nhưng bạn nên làm theo các bước sau để đảm bảo.

  1. Chuyển đến tệp build.gradle của mô-đun app và đảm bảo rằng khối dependencies bao gồm một phần phụ thuộc trên MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (Không bắt buộc) Nếu cần, hãy chỉnh sửa tệp build.gradle để thêm các phần phụ thuộc sau đây rồi đồng bộ hoá dự án.
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'
}

Chạy ứng dụng khởi đầu

  1. Đảm bảo cấu hình bản dựng ở bên trái nút Chạy / Chạyapp.
  2. Nhấn vào nút Chạy/Phát màu xanh lục để tạo và chạy ứng dụng.
  3. Trong cửa sổ Select Deployment Target (Chọn mục tiêu triển khai), nếu bạn đã có một thiết bị Android được liệt kê trong các thiết bị có sẵn, hãy chuyển sang Bước 8. Nếu không, hãy nhấp vào Create New Virtual Device (Tạo thiết bị ảo mới).
  4. Trên màn hình Select Hardware (Chọn phần cứng), hãy chọn một thiết bị điện thoại, chẳng hạn như Pixel 2, sau đó nhấp vào Next (Tiếp theo).
  5. Trong màn hình System Image (Hình ảnh hệ thống), hãy chọn một phiên bản Android gần đây, tốt nhất là cấp độ API cao nhất. Nếu chưa cài đặt, hãy nhấp vào đường liên kết Tải xuống xuất hiện rồi hoàn tất quá trình tải xuống.
  6. Nhấp vào Tiếp theo.
  7. Trên màn hình Thiết bị Android ảo (AVD), hãy giữ nguyên chế độ cài đặt và nhấp vào Hoàn tất.
  8. Chọn một thiết bị Android trong hộp thoại mục tiêu triển khai.
  9. Nhấp vào Ok.
  10. Android Studio sẽ tạo ứng dụng, triển khai ứng dụng và tự động mở ứng dụng trên thiết bị mục tiêu.

Thành công! Mã khởi động cho trang đăng nhập của Shrine sẽ chạy trong trình mô phỏng. Bạn sẽ thấy tên "Shrine" (Đền thờ) và biểu trưng của Shrine ngay bên dưới tên đó.

e7ed014e84755811.png

Hãy cùng xem xét mã. Chúng tôi đã cung cấp một khung điều hướng Fragment đơn giản trong mã mẫu để hiển thị các mảnh và di chuyển giữa các mảnh.

Mở MainActivity.kt trong thư mục shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.kotlin.shrine. Tệp này phải chứa nội dung sau:

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()
   }
}

Hoạt động này hiển thị tệp bố cục R.layout.shr_main_activity, được xác định trong shr_main_activity.xml.

Bạn có thể thấy rằng trong onCreate(),, MainActivity.kt sẽ bắt đầu một giao dịch Fragment để cho thấy LoginFragment. Trong lớp học lập trình này, chúng ta sẽ sửa đổi LoginFragment. Hoạt động này cũng triển khai phương thức navigateTo(Fragment), được xác định trong NavigationHost, cho phép mọi mảnh điều hướng đến một mảnh khác.

Command + Click (hoặc Control + Click) shr_main_activity trong tệp hoạt động để mở tệp bố cục hoặc chuyển đến tệp bố cục trong 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"/>

Ở đây, chúng ta thấy một <FrameLayout> đơn giản đóng vai trò là vùng chứa dành cho mọi mảnh mà hoạt động hiển thị.

Tiếp theo, hãy mở 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 tăng cường tệp bố cục shr_login_fragment và hiển thị tệp đó trong onCreateView().

Bây giờ, hãy xem tệp bố cục shr_login_fragment.xml để xem trang đăng nhập trông như thế nào.

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>

Tại đây, chúng ta có thể thấy <LinearLayout> với <ImageView> ở đầu, đại diện cho biểu trưng Shrine.

Tiếp theo là thẻ <TextView> đại diện cho nhãn Shrine (Đền thờ) bên dưới biểu trưng. Văn bản của nhãn này là một tài nguyên chuỗi có tên @string/shr_app_name. Nếu bạn nhấn tổ hợp phím Command + Nhấp (hoặc Control + Nhấp) vào tên tài nguyên chuỗi hoặc mở app -> res -> values -> strings.xml, bạn có thể thấy tệp strings.xml trong đó tài nguyên chuỗi được xác định. Khi thêm các tài nguyên chuỗi khác trong tương lai, chúng sẽ được xác định tại đây. Mỗi tài nguyên trong tệp này phải có tiền tố shr_ để biểu thị rằng chúng là một phần của ứng dụng Shrine.

Giờ bạn đã quen thuộc với mã khởi động, hãy triển khai thành phần đầu tiên.

3. Thêm trường văn bản

Để bắt đầu, chúng tôi sẽ thêm hai trường văn bản vào trang đăng nhập để mọi người nhập tên người dùng và mật khẩu của họ. Chúng ta sẽ sử dụng thành phần Trường văn bản MDC, trong đó có chức năng tích hợp hiển thị nhãn nổi và thông báo lỗi.

d83c47fb4aed3a82.png

Thêm tệp XML

Trong shr_login_fragment.xml, hãy thêm 2 phần tử TextInputLayout có phần tử con TextInputEditText bên trong <LinearLayout>, bên dưới nhãn "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>

Đoạn mã trên đại diện cho hai trường văn bản, mỗi trường bao gồm một phần tử <TextInputLayout> và một phần tử con <TextInputEditText>. Văn bản gợi ý cho mỗi trường văn bản được chỉ định trong thuộc tính android:hint.

Chúng tôi đã thêm hai tài nguyên chuỗi mới cho trường văn bản – @string/shr_hint_username@string/shr_hint_password. Mở strings.xml để xem các tài nguyên chuỗi này.

strings.xml

<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>

Thêm phương thức xác thực dữ liệu đầu vào

Các thành phần TextInputLayout cung cấp chức năng phản hồi về lỗi tích hợp sẵn.

Để hiển thị phản hồi về lỗi, hãy thực hiện các thay đổi sau đối với shr_login_fragment.xml:

  • Đặt thuộc tính app:errorEnabled thành true trên phần tử Mật khẩuTextInputLayout. Thao tác này sẽ thêm khoảng đệm cho thông báo lỗi bên dưới trường văn bản.
  • Đặt thuộc tính android:inputType thành "textPassword" trên phần tử Mật khẩu TextInputEditText. Thao tác này sẽ ẩn văn bản nhập trong trường mật khẩu.

Với những thay đổi này, các trường văn bản trong shr_login_fragment.xml sẽ có dạng như sau:

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>

Bây giờ, hãy thử chạy ứng dụng. Bạn sẽ thấy một trang có hai trường văn bản cho "Tên người dùng" và "Mật khẩu"!

Xem ảnh động của nhãn nổi:

333184b615aed4f7.gif

4. Thêm nút

Tiếp theo, chúng ta sẽ thêm hai nút vào trang đăng nhập: "Huỷ" và "Tiếp theo". Chúng ta sẽ sử dụng thành phần Nút MDC, đi kèm với hiệu ứng gợn sóng mực mang tính biểu tượng của Material Design.

4cb0c218948144b4.png.

Thêm tệp XML

Trong shr_login_fragment.xml, hãy thêm <RelativeLayout> vào <LinearLayout>, bên dưới các phần tử TextInputLayout. Sau đó, hãy thêm 2 phần tử <MaterialButton> vào <RelativeLayout>.

Tệp XML thu được sẽ có dạng như sau:

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>

Vậy là xong! Khi chạy ứng dụng, bạn sẽ thấy một gợn sóng khi nhấn vào từng nút.

9dd162d65e4a92a2.gif

5. Chuyển đến mảnh tiếp theo

Cuối cùng, chúng ta sẽ thêm một số mã Kotlin vào LoginFragment.kt để kết nối nút "TIẾP THEO" nhằm chuyển đổi sang một mảnh khác.

Hãy thêm phương thức isPasswordValid boolean riêng tư trong LoginFragment.kt bên dưới onCreateView(), với logic để xác định xem mật khẩu có hợp lệ hay không. Đối với bản minh hoạ này, chúng tôi sẽ chỉ đảm bảo rằng mật khẩu dài ít nhất 8 ký tự:

LoginFragment.kt

private fun isPasswordValid(text: Editable?): Boolean {
   return text != null && text.length >= 8
}

Tiếp theo, hãy thêm một trình nghe lượt nhấp vào nút "Next" (Tiếp theo) để thiết lập và xoá lỗi dựa trên phương thức isPasswordValid() mà chúng ta vừa tạo. Trong onCreateView(), trình nghe lượt nhấp này phải được đặt giữa dòng tăng cường và dòng return view.

Bây giờ, hãy thêm trình nghe phím vào mật khẩu TextInputEditText để theo dõi các sự kiện phím giúp xoá lỗi. Trình nghe này cũng nên sử dụng isPasswordValid() để kiểm tra xem mật khẩu có hợp lệ hay không. Bạn có thể thêm phần này ngay bên dưới trình nghe lượt nhấp trong onCreateView().

Bây giờ, phương thức onCreateView() sẽ có dạng như sau:

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

Bây giờ, chúng ta có thể điều hướng đến một mảnh khác. Trong onCreateView(), hãy cập nhật OnClickListener để chuyển đến một mảnh khác khi xác thực lỗi thành công. Bây giờ, mã clickListener của bạn sẽ có dạng như sau:

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)
   }
})

Chúng tôi đã thêm dòng (activity as NavigationHost).navigateTo(ProductGridFragment(), false) vào trường hợp else của trình nghe lượt nhấp. Dòng này gọi phương thức navigateTo() từ MainActivity để điều hướng đến một mảnh mới – ProductGridFragment. Hiện tại, trang này trống mà bạn sẽ xử lý trong MDC-102.

Bây giờ, hãy tạo ứng dụng. Hãy tiếp tục và nhấn vào nút Tiếp theo.

Các bạn đã làm được! Màn hình này sẽ là điểm xuất phát của lớp học lập trình tiếp theo mà bạn sẽ làm việc trong MDC-102.

6. Đã xong

Bằng cách sử dụng mã đánh dấu XML cơ bản và khoảng 30 dòng mã Kotlin, thư viện Thành phần Material cho Android đã giúp bạn tạo một trang đăng nhập đẹp mắt, tuân thủ các nguyên tắc của Material Design, đồng thời có giao diện và hoạt động nhất quán trên tất cả các thiết bị.

Các bước tiếp theo

Trường văn bản và Nút là 2 thành phần cốt lõi trong thư viện Android MDC, nhưng còn nhiều thành phần khác nữa! Bạn có thể khám phá các thành phần còn lại trong MDC Android. Ngoài ra, hãy chuyển đến phần MDC 102: Cấu trúc và bố cục Material Design để tìm hiểu về thanh ứng dụng trên cùng, chế độ xem thẻ và bố cục lưới. Cảm ơn bạn đã dùng thử Material Components. Chúng tôi hy vọng bạn đã thích lớp học lập trình này!

Tôi có thể hoàn thành lớp học lập trình này với thời gian và công sức hợp lý

Hoàn toàn đồng ý Đồng ý Trung lập Không đồng ý Hoàn toàn không đồng ý

Tôi muốn tiếp tục sử dụng Thành phần Material trong tương lai

Hoàn toàn đồng ý Đồng ý Trung lập Không đồng ý Hoàn toàn không đồng ý