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 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 và hữu ích, đồng thời có sẵn cho Android, iOS, web và Flutter. material.io/develop |
Material Design và Thành phần Material 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ố nổi bật và đẹp mắt. Bằng cách kết hợp phong cách, thương hiệu, hoạt động 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 sản phẩm có thể nhận ra tiềm năng thiết kế lớn nhất của mình.
Đối với các ứng dụng Android, Thành phần Material cho Android(MDC Android) kết hợp thiết kế và kỹ thuật với một thư viện gồm các thành phần để tạo sự nhất quán trong ứng dụng của bạn. Khi hệ thống Material Design phát triển, các thành phần này sẽ được cập nhật để đảm bảo việc triển khai nhất quán và chính xác đến từng pixel, đồng thời 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ó sẵn cho web, iOS và Flutter.
Trong lớp học lập trình này, bạn sẽ tạo 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
Đây là lớp học lập trình đầ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, một ứng dụng Android thương mại điện tử bán quần áo và đồ gia dụng. Phần này sẽ minh hoạ cách bạn có thể tuỳ chỉnh các thành phần để phản ánh mọi thương hiệu hoặc kiểu dáng bằng MDC Android.
Trong lớp học lập trình này, bạn sẽ tạo một trang đăng nhập cho Shrine có 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 của ứng dụng (Shrine)
- Hình ảnh biểu trưng của Shrine
Các thành phần MDC Android 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ề hoạt động phát triển Android
- Android Studio (tải xuống tại đây nếu bạn chưa có)
- Một trình mô phỏng hoặc thiết bị Android (có trong Android Studio)
- Mã mẫu (xem bước tiếp theo)
Bạn đánh giá kinh nghiệm của mình trong việc tạo ứng dụng Android ở mức nào?
Khởi động Android Studio
Khi bạn mở Android Studio, ứng dụng này sẽ hiển thị một cửa sổ có tiêu đề "Chào mừng bạn đến với Android Studio". Tuy nhiên, nếu đây là lần đầu tiên bạn chạy Android Studio, hãy thực hiện các bước trong Android Studio Setup Wizard (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, bạn có thể để quá trình này chạy ở chế độ nền trong khi thực hiện phần tiếp theo.
Tải ứng dụng khởi đầu của lớp học lập trình xuống
Ứng dụng khởi đầu 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
- 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 mà bạn đã cài đặt mã mẫu, rồi chọn kotlin -> shrine (hoặc tìm shrine trên máy tính) để mở dự án Vận chuyển.
- Chờ một lát để Android Studio tạo và đồng bộ hoá dự án, như được thể hiện bằng các chỉ báo hoạt động ở cuối cửa sổ Android Studio.
- Tại thời điểm này, Android Studio có thể phát sinh một số lỗi bản dựng vì bạn thiếu SDK Android hoặc các công cụ bản dựng, chẳng hạn như lỗi được minh hoạ bên dưới. Hãy làm theo hướng dẫn trong Android Studio để cài đặt/cập nhật các thành phần này và đồng bộ hoá dự án của bạn.
Thêm các phần phụ thuộc của dự án
Dự án cần có một phần phụ thuộc trên thư viện hỗ trợ MDC Android. Mã mẫu mà bạn đã tải xuống có thể đã liệt kê phần phụ thuộc này, nhưng bạn nên thực hiện các bước sau để đảm bảo.
- Chuyển đến tệp
build.gradle
của mô-đunapp
và đảm bảo rằng khốidependencies
có một phần phụ thuộc vào MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
- (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 và đồ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
|
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 của bạn. Bạn sẽ thấy tên "Shrine" và biểu trưng của Shrine ngay bên dưới.
Hãy cùng xem mã này. 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à điều hướng giữa các mảnh.
Mở MainActivity.kt
trong thư mục shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.kotlin.shrine
. Nội dung phải có:
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
bắt đầu một giao dịch Fragment
để hiển thị 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 một phương thức navigateTo(Fragment)
(được xác định trong NavigationHost
) cho phép mọi mảnh chuyển đến một mảnh khác.
Nhấn tổ hợp phím 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 cho mọi phân 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
mở rộ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
để biết giao diện của trang đăng nhập.
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>
Ở đây, chúng ta có thể thấy một <LinearLayout>
có <ImageView>
ở trên cùng, thể hiện biểu trưng của Shrine.
Sau đó, có thẻ <TextView>
đại diện cho nhãn Shrine bên dưới biểu trưng. Văn bản cho nhãn này là một tài nguyên chuỗi có tên là @string/shr_app_name
. Nếu Command + Click (hoặc Control + Click) 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
nơi các tài nguyên chuỗi được xác định. Khi bạn thêm nhiều tài nguyên chuỗi hơn trong tương lai, các tài nguyên đó sẽ được xác định tại đây. Mọi tài nguyên trong tệp này đều phải có tiền tố shr_
để biểu thị rằng chúng thuộc về ứng dụng Shrine.
Giờ bạn đã quen với mã khởi động, hãy triển khai thành phần đầu tiên.
Để bắt đầu, chúng ta sẽ thêm hai trường văn bản vào trang đăng nhập để người dùng nhập tên người dùng và mật khẩu. Chúng ta sẽ sử dụng thành phần Trường văn bản MDC, bao gồm chức năng tích hợp để hiển thị nhãn nổi và thông báo lỗi.
Thêm XML
Trong shr_login_fragment.xml
, hãy thêm hai phần tử TextInputLayout
có một 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 biểu thị 2 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 từng trường văn bản được chỉ định trong thuộc tính android:hint
.
Chúng tôi đã thêm 2 tài nguyên chuỗi mới cho trường văn bản – @string/shr_hint_username
và @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 quy trình 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 lỗi tích hợp.
Để hiện phản hồi 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ànhtrue
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ẩuTextInputEditText
. 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ó 2 trường văn bản cho "Tên người dùng" và "Mật khẩu"!
Xem ảnh động nhãn nổi:
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, có sẵn hiệu ứng gợn mực mang tính biểu tượng của Material Design.
Thêm 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 kết quả 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 bạn chạy ứng dụng, hiệu ứng gợn mực sẽ xuất hiện khi bạn nhấn vào từng nút.
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 sang một mảnh khác.
Hãy thêm một phương thức boolean riêng tư isPasswordValid
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. Để minh hoạ, chúng ta chỉ cần đảm bảo 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 "Tiếp theo" để đặt 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 trình mở rộng và dòng return view
.
Bây giờ, hãy thêm một trình nghe phím vào TextInputEditText
mật khẩu để theo dõi các sự kiện phím sẽ xoá lỗi. Trình nghe này cũng nên dùng isPasswordValid()
để kiểm tra xem mật khẩu có hợp lệ hay không. Bạn có thể thêm mã này ngay bên dưới trình nghe lượt nhấp trong onCreateView()
.
Phương thức onCreateView() của bạn hiện 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
}
}
Giờ đây, chúng ta có thể chuyển đế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 quá trình xác thực lỗi thành công. Mã clickListener
của bạn hiệ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
để chuyển đến một mảnh mới – ProductGridFragment
. Hiện tại, đây là một trang trống mà bạn sẽ làm việc trong MDC-102.
Bây giờ, hãy tạo ứng dụng. 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 bắt đầu của lớp học lập trình tiếp theo mà bạn sẽ thực hiện trong MDC-102.
Bằng cách sử dụng mã đánh dấu XML cơ bản và khoảng 30 dòng 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à hành vi 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à hai thành phần cốt lõi trong thư viện MDC Android, 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 truy cập vào MDC 102: Cấu trúc và bố cục của Material Design để tìm hiểu về thanh ứng dụng trên cùng, chế độ xem thẻ và bố cục dạng lưới. Cảm ơn bạn đã dùng thử Thành phần Material. Chúng tôi hy vọng bạn thích lớp học lập trình này!