Chuyển đến nội dung chính

Jetpack Compose Tutorial for Android: Getting Started

 


Trong hướng dẫn Jetpack Compose này, bạn sẽ học cách sử dụng khung giao diện người

dùng khai báo mới đang được nhóm Android phát triển bằng cách tạo ứng dụng sách nấu ăn.


Các đổi mới phát triển ứng dụng dành cho thiết bị di động thường đi theo làn sóng hoặc xu

hướng. Cho dù xu hướng hiện tại là về sự ổn định và an toàn của ngôn ngữ hay cải tiến hiệu

suất của nền tảng, thì điều quan trọng là phải theo kịp các xu hướng, vì một số trong số đó

thay đổi hoàn toàn cách chúng tôi phát triển ứng dụng. Một hoặc hai năm qua đều xoay quanh

việc xây dựng chương trình phản ứng và khai báo khi nói đến logic kinh doanh của ứng dụng.


Điều này có nghĩa là mọi người đã chuyển từ cách tiếp cận

MVC/P (Model-View-Controller / Presenter) mệnh lệnh cổ điển, sang một cách tiếp cận phản

ứng hơn như MVVM (Model-View-ViewModel), nơi bạn cập nhật các luồng dữ liệu trong

ViewModel và giao diện người dùng phản ứng với thay đổi bằng cách tự vẽ lại hoặc chỉ cập

nhật các phần của giao diện người dùng. Điều này là do lập trình khai báo ít mắc lỗi hơn,

dễ tổng hợp hơn và dễ kiểm tra hơn vì bạn chủ yếu làm việc với các giá trị dữ liệu hơn là các

tương tác.




Theo xu hướng như vậy, điều tự nhiên là việc xây dựng giao diện người dùng cũng đi theo

hướng đó, với xu hướng của các bộ công cụ và khung giao diện người dùng khai báo. Các bộ

công cụ và khuôn khổ giao diện người dùng như React.js và Flutter ngày càng trở nên phổ biến

hơn và điều này đã ảnh hưởng đến các nền tảng khác để đưa ra các triển khai của riêng họ, sử

dụng cùng một cách tiếp cận.


Tại Google I/O 2019, Google lần đầu tiên công bố Jetpack Compose. Jetpack Compose là phản

ứng của họ đối với xu hướng khung giao diện người dùng khai báo, mà nhóm Android đang phát

triển để thay đổi cơ bản cách các nhà phát triển tạo giao diện người dùng, giúp viết dễ dàng hơn,

nhanh hơn và chạy hiệu suất hơn. Nó là một phần của bộ thư viện Jetpack và như vậy sẽ cung

cấp khả năng tương thích trên các phiên bản nền tảng, loại bỏ nhu cầu tránh một số tính năng

nhất định vì bạn đang nhắm mục tiêu các thiết bị cấp thấp hơn hoặc các phiên bản Android cũ hơn.


Mặc dù vẫn ở trạng thái xem trước ban đầu, tính năng Compose thư đã tạo nên làn sóng lớn

trongcộng đồng Android. Nếu bạn muốn cập nhật công nghệ mới nhất và tốt nhất, hãy đọc tiếp!


Trong hướng dẫn này, bạn sẽ tìm hiểu về các khái niệm cơ bản của Jetpack Compose, chẳng hạn

như các chức năng có thể kết hợp, thiết lập nội dung trên màn hình và cập nhật nội dung. Sau khi

đã nắm vững các kiến thức cơ bản, bạn sẽ tiếp tục sử dụng Jetpack Compose để tạo ứng dụng

sách nấu ăn, ứng dụng này hiển thị danh sách các công thức nấu ăn được cung cấp bởi

Material-design, với thẻ, hình ảnh và văn bản.


Lưu ý: Tính năng Compose vẫn ở trạng thái tiền alpha ban đầu. Bạn không nên sử dụng nó trong

các ứng dụng sản xuất, vì nó có thể thay đổi và có thể làm hỏng mã của bạn.


1. Why Build With Jetpack Compose?


Trước khi bạn viết ứng dụng đầu tiên của mình bằng Compose, hãy xem xét lý do tại sao nhóm

Android lại viết thư viện.


Compose có ba lợi ích to lớn trong quá trình xây dựng giao diện người dùng hiện tại trong Android.

  • It’s Declarative

Jetpack Compose là một khung giao diện người dùng khai báo, có nghĩa là bạn mô tả chế độ

xem của mình mà không dựa vào các khái niệm lập trình bắt buộc truyền thống và đột biến hơn.


Lấy chế độ xem làm ví dụ. Với bộ công cụ giao diện người dùng hiện tại, bạn thường sử dụng

một phương thức như findViewById() để tham chiếu đến View bạn muốn ẩn, sau đó gọi

setVisibility() trên đó.


Trong giao diện người dùng khai báo, thay vào đó bạn mô tả giao diện người dùng có hiển thị

hay không. Khi bạn muốn thay đổi chế độ hiển thị, bạn chạy lại mã mô tả giao diện người dùng.


Vì vậy, bạn không còn lấy tham chiếu đến View sau khi tạo. Thay vào đó, bạn chỉ cần chạy lại

mã đã tạo View với các tham số khác nhau.


Lưu ý: Compose không thực sự xây dựng lại toàn bộ View khi bạn cập nhật nội dung nào đó.

Nó đủ thông minh để chỉ thay đổi phần cần thay đổi.

  • It’s Independent

Compose là một thư viện không được kết hợp với hệ điều hành. Đây là một lợi thế lớn cho các

nhà phát triển.


Ngay bây giờ, nếu Google muốn cập nhật thành phần LinearLayout, nó cần phát hành một phiên

bản hệ điều hành mới. Thật không may, các vấn đề phân mảnh ngăn cản nhiều người sử dụng

các phiên bản Android mới nhất.


Điều đó có nghĩa là bạn không thể dựa vào việc người dùng có quyền truy cập vào các tính năng

mới của bộ công cụ giao diện người dùng hiện tại cho đến nhiều năm sau khi chúng được phát

hành khi hầu hết mọi người cuối cùng đã nâng cấp.


Với Jetpack Compose, các nhà phát triển có thể thêm các tính năng mới mà không cần thay đổi

phiên bản hệ điều hành. Bạn có thể tin tưởng vào việc chúng hoạt động, bất kể hệ điều hành trên

thiết bị của người dùng là gì.


Không chỉ vậy, không giống như thành phần LinearLayout, việc phát hành phiên bản mới của

Jetpack Compose sẽ không phá vỡ các ứng dụng hiện có, vì bạn không phải nâng cấp lên phiên

bản Jetpack Compose mới hơn trừ khi bạn muốn. Nó cũng không sử dụng bộ công cụ giao diện

người dùng hiện có từ Android, vì vậy đây là một khởi đầu mới, để khắc phục một số vấn đề lâu

đời mà hệ thống phân cấp View gặp phải. Trong khi ngay sau khi bạn nâng cấp lên phiên bản

Android mới, thành phần LinearLayout, là một phần của hệ điều hành, cũng được nâng cấp và nó

có thể mang lại những thay đổi đột phá cho các ứng dụng dựa nhiều vào nó.

  • It’s, Ahem, Composable

Cuối cùng nhưng không kém phần quan trọng, Jetpack Compose sẽ giải quyết một số vấn đề lâu

dài với bộ công cụ giao diện người dùng hiện tại. Điều này đi cùng với ý tưởng về nó là độc lập.


Android đã ra mắt được hơn mười năm và mã tạo giao diện người dùng của nó đang bắt đầu có

tuổi. Chỉ riêng lớp View đã chứa hơn mười nghìn dòng mã! Đó là rất nhiều mã kế thừa cần hỗ trợ.


Compose sẽ cho phép Google bắt đầu lại từ đầu theo cách dễ dàng hơn.


2. Getting Started


Bắt đầu bằng cách nhấp vào nút Download Materials ở đầu hoặc cuối trang này để tải xuống mọi

thứ bạn cần cho dự án này.


Vì Jetpack Compose đang ở trạng thái tiền alpha sớm như vậy nên bạn cần chạy ít nhất Android

Studio 4.0 Canary 3 trở lên.


Tại thời điểm viết bài, bạn cần ở trên Canary channel của Android Studio để làm việc với tính năng

Compose. Để chuyển sang Canary channel để cập nhật, hãy đi tới hộp thoại Check for Updates

và nhấp vào Configure ở góc dưới cùng bên trái của hộp thoại.


Tiếp theo, chọn Canary Channel trong menu thả xuống trên màn hình cấu hình.



Nhấp vào OK và chạy lại Check for Updates. Bạn sẽ thấy lời nhắc cài đặt phiên bản Canary

của Android Studio.


Cài đặt phiên bản mới. Bạn có thể cài đặt cả Canary và phiên bản ổn định của Android Studio cùng một lúc. Bạn sẽ biết mình đang sử dụng phiên bản Canary vì nó có phiên bản màu vàng của biểu tượng Android Studio.






Bây giờ bạn đã cài đặt phiên bản Android Studio phù hợp, đã đến lúc đi sâu vào Jetpack

Compose.


3. Getting Up and Running With Jetpack Compose


Đi tới tài liệu bạn đã tải xuống và mở dự án bắt đầu trong phiên bản Canary của Android Studio.


Xây dựng và chạy và bạn sẽ thấy một màn hình trắng, trống với dòng chữ Hello World của một

dự án Android Studio hoàn toàn mới.





Bây giờ, hãy mở tệp app/build.gradle và xem khối phụ thuộc. Bạn sẽ thấy ba phần phụ thuộc

thú vị:


implementation 'androidx.ui:ui-layout:0.1.0-dev02'
implementation 'androidx.ui:ui-material:0.1.0-dev02'
implementation 'androidx.ui:ui-tooling:0.1.0-dev02'

Compose sử dụng không gian tên androidx.ui cho các phần phụ thuộc tạo nên thư viện.


Ngoài những phụ thuộc đó, bạn cũng cần thêm cờ compose là true, trong khối buildFeatures trong android:


buildFeatures {
compose true
}

Bây giờ bạn đã biết những phụ thuộc nào bạn cần cho dự án Jetpack Compose, bạn có thể bắt đầu làm việc.


4. Dipping Your Toes Into Jetpack Compose


Vì Jetpack Compose cho thấy một cách có lập trình để xây dựng giao diện người dùng, bạn sẽ không sử dụng bất kỳ XML nào. Điều này có nghĩa là bạn sẽ không sử dụng setContentView () trong các hoạt động hoặc phân đoạn của mình, thay vào đó bạn sẽ sử dụng setContent () để thiết lập giao diện người dùng của mình.


Để thực hiện việc này, hãy mở MainActivity.kt và thay thế lệnh gọi hiện có thành setContentView () bằng lệnh sau:


setContent {
Text("Hello, World!")
}

Đảm bảo nhập các phụ thuộc từ gói androidx.ui.core, khi bạn làm như vậy. setContent () là một hàm mở rộng Kotlin trong Activity lấy lambda @Composable làm tham số. Bạn sẽ tìm hiểu thêm về ý nghĩa của @Composable sau này.


Ngoài setContent (), có một trình phát mới khác trong thị trấn trong đoạn mã trên: Text ().


Trong Jetpack Compose, bạn sử dụng các phương pháp được đánh dấu bằng chú thích @Composable để xây dựng giao diện người dùng của mình. Nếu bạn Command-Click trên Mac hoặc Control khi nhấp vào Windows trên Text (), bạn sẽ thấy một cái gì đó như sau:


@Composable
fun Text(
...
)

Text () thực sự là một hàm được đánh dấu bằng @Composable. Bạn đoán xem Text () có thể kết hợp phụ trách vẽ văn bản trên màn hình hay không. Bạn có thể coi nó là phiên bản Compose của TextView.


Lưu ý: Thông thường, bạn sẽ sử dụng camelCase khi đặt tên cho các phương pháp. Tuy nhiên, khi bạn tạo các bản tổng hợp, bạn viết hoa tên phương thức để rõ ràng rằng bạn đang tạo một bản sao của một bản tổng hợp. Tương tự như cách các widget Flutter hoạt động hoặc các hàm Kotlin Coroutine như Job () được đặt tên.


Xây dựng và chạy và bạn sẽ thấy Text () trên màn hình:




Bạn có thể tùy chỉnh văn bản của mình bằng cách sử dụng TextStyle. Hãy thử bằng cách thay thế Text() hiện có bằng văn bản sau:

Text("Hello, World!", style = TextStyle(color = Color.Red))

Một lần nữa, hãy đảm bảo nhập các gói androidx.ui thích hợp. Xây dựng và chạy và bạn sẽ thấy rằng văn bản hiện có màu đỏ.




Khi sử dụng Jetpack Compose, bạn sẽ sử dụng các đối số phương thức và mã Kotlin thông thường thay vì các kiểu và thuộc tính XML để tùy chỉnh giao diện người dùng của mình. Bạn sẽ thử làm điều này trong phần tiếp theo.


5. Creating a Composable Function


Một trong những lợi ích sâu sắc nhất của Jetpack Compose là bạn xây dựng giao diện người

dùng của mình theo cách mô-đun với nhiều chức năng nhỏ thay vì sử dụng một tệp XML khổng

lồ cho mỗi Activity.


Giờ bạn đã quen với Text (), bạn có thể tạo hàm @Composable đầu tiên của mình.


Thêm chức năng sau vào bên dưới MainActivity:


@Composable
fun Greeting() {
Text("Hello, World!", style = TextStyle(color = Color.Red))
}

Xin chúc mừng, bạn vừa tạo chức năng Có thể dùng một lần tùy chỉnh đầu tiên của mình!


Để sử dụng nó, hãy thay thế cuộc gọi hiện tại tới Text () trong setContent () bằng một cuộc gọi tới Greeting ():


setContent {
Greeting()
}

Xây dựng và chạy. Giống như trước đây, bạn sẽ thấy văn bản màu đỏ chói của mình!



Sử dụng nhiều chức năng nhỏ là một cách tuyệt vời để tạo nhiều giao diện người dùng mà bạn có thể sử dụng lại trên các màn hình khác nhau.


Tuy nhiên, một điều cần lưu ý là bạn chỉ có thể gọi một hàm @Composable từ bên trong một hàm @Composable khác; nếu không, ứng dụng của bạn sẽ bị lỗi.


Điều này tương tự với Kotlin Coroutines, nơi bạn chỉ có thể gọi các hàm tạm ngưng từ bên trong các hàm hoặc coroutines tạm ngưng khác.


Previewing a Composable


Thông thường, khi bạn tạo giao diện người dùng cho một trong các hoạt động của mình bằng XML, bạn sử dụng bản xem trước bố cục để xem chế độ xem của bạn trông như thế nào mà không cần phải xây dựng và chạy ứng dụng của mình.


Jetpack Compose đi kèm với một công cụ tương tự.


Thêm @Preview bên dưới @Composable trên Greeting (), mà bạn đã xác định trước đó:


@Composable
@Preview
fun Greeting() {
Text("Hello, World!", style = TextStyle(color = Color.Red))
}

Sau khi nhập chú thích, bạn sẽ thấy một thông báo bật lên ở đầu Android Studio cho bạn biết rằng giờ đây bạn có thể hiển thị bản xem trước của phần có thể tổng hợp.


Nhấp vào Show Preview và đợi bản dựng hoàn tất. Bạn sẽ thấy bản xem trước của bản có thể tổng hợp của mình ở bên phải màn hình.




Mỗi khi cập nhật bản phối mà bạn đang xem trước, bạn sẽ phải làm mới bản dựng để xem bản cập nhật. Bạn chỉ có thể xem trước các bản tổng hợp không có bất kỳ đối số nào.


Bây giờ bạn có thể xem trước các thành phần của mình, đã đến lúc tìm hiểu cách làm việc với bố cục.


6. Laying Out Composables


Chỉ có một Text trên màn hình không tạo ra một ứng dụng đặc biệt thú vị. Tuy nhiên, có ba Text trên màn hình sẽ tạo ra một trải nghiệm hoàn toàn hấp dẫn! :]


Cập nhật Greeting() để sử dụng Text() ba lần:


Text("Hello, World!", style = TextStyle(color = Color.Red))
Text("Hello, Second World!", style = TextStyle(color = Color.Red))
Text("Hello, Third World!", style = TextStyle(color = Color.Red))

Bạn mong đợi vật tổng hợp này trông như thế nào? Xây dựng và chạy và xem trong cửa sổ xem trước để xem kết quả có phù hợp với mong đợi của bạn hay không.




Hoàn hảo.


Đùa thôi, trông khá khủng khiếp! 


Không có gì chi phối vị trí của các điều khiển Text này, vì vậy tất cả chúng đều vẽ chồng lên nhau như thể chúng đang ngồi trong một FrameLayout. May mắn thay, Jetpack Compose cung cấp một bộ sưu tập lớn các bố cục tổng hợp.


Trong trường hợp này, bạn sẽ sử dụng Column có thể tổng hợp để thêm trật tự cho sự hỗn loạn này.


Using the Column Composable


Hãy nghĩ về một Column như một LinearLayout với hướng dọc. Nó chỉ đơn giản là đặt tất cả các vật tổng hợp con của nó trong một cột dọc.


Cập nhật Greeting() để bọc ba Text() trong một Column():


@Composable
@Preview
fun Greeting() {
Column {
Text("Hello, World!", style = TextStyle(color = Color.Red))
Text("Hello, Second World!", style = TextStyle(color = Color.Red))
Text("Hello, Third World!", style = TextStyle(color = Color.Red))
}
}

Column() nhận một khối lambda @Composable, là nơi bạn khai báo các phần tử con của cột.


Trong Greeting(), bạn đang thêm ba Text làm cột con này. Kiểu có một hàm có thể kết hợp chấp nhận một lambda để tạo các hàm có thể kết hợp khác là điều phổ biến trong Jetpack Compose. Bạn thậm chí có thể nói rằng đó là toàn bộ ý tưởng bao gồm. :]


Xây dựng và chạy và bạn sẽ thấy rằng bây giờ bạn đã sắp xếp ba Text trong một cột dọc. Tốt hơn nhiều!




Ngoài Column(), bạn có thể sử dụng Row() để sắp xếp các con thành một hàng ngang. Điều này trông giống như một LinearLayout với hướng nằm ngang.


7. Introducing ComposableCookBook


Đó là một phần giới thiệu khá thú vị, và tôi chỉ có thể tưởng tượng được rằng bạn đang ở đâu đó rất hào hứng và thích thú như thế nào! Nhưng bạn có thể muốn tự sáng tác vì bạn sẽ làm việc trên một tính năng thậm chí còn thú vị hơn cho dự án! :]


Thay vì tạo các văn bản màu đỏ đơn giản, bạn sẽ xây dựng một ứng dụng sách nấu ăn có tên là ComposableCookBook hiển thị danh sách các công thức nấu ăn ngon. Dự án đi kèm với một Reciep được xác định trước:


data class Recipe(
@DrawableRes val imageResource: Int,
val title: String,
val ingredients: List<String>
)

Reciep có hình ảnh, tiêu đề và danh sách các thành phần. Ứng dụng cũng đi kèm với một danh sách các công thức nấu ăn mặc định trong Recipes.kt. Bạn sẽ sử dụng danh sách các công thức nấu ăn này để xây dựng ứng dụng sách nấu ăn của mình.


8. Creating a Recipe Composable


Mục tiêu của bạn là sử dụng Jetpack Compose để làm cho ứng dụng công thức ComposeCookbook trông đẹp hơn, bằng cách tạo giao diện người dùng hiển thị từng công thức trong thẻ với hình ảnh của công thức ở đầu thẻ và danh sách các thành phần bên dưới.


Bước đầu tiên của bạn là tạo một bản tổng hợp thể hiện một công thức riêng lẻ.


Nhấp chuột phải vào gói ComposableCookBook và chọn New ▸ New Kotlin File/Class. Sau đó chọn File từ danh sách và nhập tên RecipeCard. Cuối cùng, thêm phương thức có thể kết hợp, RecipeCard(), được hiển thị bên dưới:


@Composable
fun RecipeCard(recipe: Recipe) {
Text(recipe.title)
}

Hiện tại, nó chỉ hiển thị tiêu đề của công thức bằng Text().


Vì RecipeCard() nhận một tham số, bạn không thể sử dụng @Preview. Tuy nhiên, bạn có thể tạo một phương thức có thể kết hợp khác cung cấp RecipeCard() mặc định. Thêm vào bên dưới RecipeCard():


@Composable
@Preview
fun DefaultRecipeCard() {
RecipeCard(defaultRecipes[0])
}

Xây dựng và chạy. Bây giờ bạn có thể xem trước RecipeCard()



Tiếp theo, bạn sẽ thêm một hình ảnh vào RecipeCard(), phía trên tiêu đề.

  • Adding an Image to the RecipeCard

Thay thế nội dung của RecipeCard() bằng nội dung sau:


// 1
val image = +imageResource(recipe.imageResource)
Column {
// 2
Container(expanded = true, height = 144.dp) {
// 3
DrawImage(image = image)
}
Text(recipe.title)
}

Đảm bảo nhập tất cả các hàm có thể được đánh dấu là màu đỏ, dưới dạng các tham chiếu chưa được giải quyết. Có rất nhiều điều kỳ diệu đang diễn ra ở đó cho một đoạn mã nhỏ như vậy! Đây là bảng phân tích:


- Mỗi Công thức đi kèm với một tài nguyên hình ảnh trỏ đến một Drawable. Thông thường, bạn sẽ đặt có thể vẽ trên ImageView hoặc sử dụng Context để có được một phiên bản của Drawable.

Trong Jetpack Compose, bạn sử dụng một cơ chế khác để lấy một phiên bản của Hình ảnh. Dòng này yêu cầu Jetpack Compose tìm nạp một Hình ảnh từ một định danh tài nguyên có thể vẽ nhất định.


- Tiếp theo, bạn cần một số cách để định kích thước hình ảnh mà bạn sẽ hiển thị. Container là một bố cục đơn giản có thể ghép lại có thể giúp bạn định kích thước một đứa trẻ có thể ghép lại được. Trong trường hợp này, bạn đang yêu cầu nó mở rộng hoàn toàn theo chiều ngang và có chiều cao là 144 dp.

Đặc biệt chú ý đến phương thức .dp được gọi trên chiều cao. Compose tiết lộ một phương pháp mở rộng cực kỳ tiện dụng để biến số thành dps!


- Cuối cùng, bạn đang sử dụng DrawImage() để hiển thị hình ảnh, chuyển qua Hình ảnh bạn đã truy xuất ở bước đầu tiên.


Làm mới bản xem trước và bạn sẽ thấy thẻ công thức của mình bắt đầu thành hình!



Món ramen đó trông khá ngon - nhưng bạn cần những nguyên liệu gì để nấu nó? Đối với nhiệm vụ tiếp theo, bạn sẽ tạo một danh sách thành phần.

  • Listing Ingredients

Để liệt kê các thành phần, bạn sẽ sử dụng Text() tiện dụng của mình. Vì bạn đã xác định một Column() ở bước trước, nên việc thêm các thành phần sẽ dễ dàng.


Thêm phần sau vào bên dưới Text vẽ tiêu đề của công thức:


for (ingredient in recipe.ingredients) {
Text(ingredient)
}

Một trong những điều tuyệt vời về Jetpack Compose là bạn có thể sử dụng mã Kotlin bình thường để thể hiện các chi tiết giao diện người dùng phức tạp hơn một chút.


Trong đoạn mã trên, bạn sử dụng vòng lặp for để liệt kê tất cả các thành phần Text. Nếu bạn xây dựng lại giao diện người dùng, bạn sẽ thấy tất cả các thành phần của bữa ăn ramen ngon lành này được liệt kê bên dưới tiêu đề. Khá tuyệt, phải không? Và bạn không cần phải xác định RecyclerView.Adapter hoặc ViewHolders!



Món ramen đó trông có vẻ ngon, nhưng bản thân recipe card trông khá vuông vắn. Tiếp theo,

bạn sẽ thêm các góc tròn vào thẻ công thức để làm cho thẻ đẹp hơn.

  • Rounding the RecipeCard’s Corners

Sử dụng Surface() parent cung cấp cho bạn tùy chọn để làm tròn các góc của mục của bạn.

Thay thế nội dung hiện có của RecipeCard() bằng nội dung sau:


Surface(shape = RoundedCornerShape(8.dp), elevation = 8.dp) {
val image = +imageResource(recipe.imageResource)
Column {
Container(expanded = true, height = 144.dp) {
DrawImage(image = image)
}
Text(recipe.title)
for (ingredient in recipe.ingredients) {
Text("• $ingredient")
}
}
}

Surface() xử lý các hình vẽ và cung cấp độ cao của thành phần. Đối với recipe card, bạn sẽ sử dụng Surface() với RoundedCornerShape() và độ cao 8 dp.


Xây dựng và chạy để cập nhật bản xem trước và bạn sẽ nhận thấy rằng không có gì xảy ra. Bạn cũng sẽ thấy biểu tượng dấu chấm than nhỏ ở trên cùng bên phải của cửa sổ xem trước, biểu tượng này cho biết lỗi hoặc cảnh báo.



Nhấp vào biểu tượng đó và bạn sẽ thấy thông báo lỗi. Nó có thể nói rằng chế độ xem không thể có chiều rộng bằng không (0) hoặc không tìm thấy màu sắc nào để vẽ giao diện người dùng. Tại thời điểm viết hướng dẫn, chúng tôi đã nhận được các lỗi khác nhau trên các máy khác nhau, vì vậy bạn có thể gặp phải lỗi khác. Không có vấn đề gì, thông báo lỗi này không chỉ ra rõ ràng vấn đề - một nhược điểm của Jetpack Compose vẫn đang ở giai đoạn tiền alpha.


Tuy nhiên, vấn đề là Jetpack Compose không thể vẽ giao diện người dùng, do thiếu giá trị màu, nhưng sự thiếu hụt đó xuất phát từ việc thiếu Theme, vì vậy đó chính là nguyên nhân gây ra.

  • Adding a Theme

Để tìm nguồn gốc của vấn đề thực sự, Command-Click trên Mac hoặc Control-click trong Windows trên Surface(). Bạn sẽ thấy một cái gì đó như thế này:


@Composable
fun Surface(
shape: Shape = RectangleShape,
color: Color = +themeColor { surface },
border: Border? = null,
elevation: Dp = 0.dp,
children: @Composable() () -> Unit
)

Lưu ý dòng xác định màu:

color: Color = +themeColor { surface }

Compose sử dụng một công cụ chủ đề cho phép bạn hoán đổi các chủ đề khác nhau khi giao diện người dùng của bạn ra lệnh. Tuy nhiên, bạn cần đảm bảo rằng bạn có một chủ đề có thể kết hợp trên bất kỳ vật phẩm có thể kết hợp nào đang cố gắng lấy màu chủ đề.


Trong trường hợp này, bản xem trước không hiển thị vì không có chủ đề nào có thể kết hợp cao hơn trong chuỗi cho Surface() này biết màu bề mặt nên là gì.


Khắc phục sự cố bằng cách bọc RecipeCard() bằng MaterialTheme() trong DefaultRecipeCard():


@Composable
@Preview
fun DefaultRecipeCard() {
MaterialTheme {
RecipeCard(defaultRecipes[0])
}
}

MaterialTheme()/code> là một chủ đề tích hợp cung cấp nhiều màu sắc và kiểu văn bản.


Làm mới bản dựng. Bản xem trước bây giờ sẽ hiển thị một thẻ làm tròn!



Thẻ đang bắt đầu định hình, nhưng nó thiếu hai thứ: một số kiểu cơ bản trên thành phần tiêu đề

và một số phần đệm giữa các phần tử. Bạn sẽ giải quyết vấn đề đó trong bước tiếp theo.

  • Improving the Recipe Card's Look

Bắt đầu bằng cách thêm một kiểu văn bản bên trong tiêu đề công thức Text():


Text(recipe.title, style = +themeTextStyle { h4 })

Tại đây, bạn sử dụng tham số kiểu để tạo kiểu cho văn bản của mình. Chức năng + themeTextStyle yêu cầu kiểu văn bản h4 từ chủ đề ứng dụng của bạn. Nếu bạn xây dựng lại bản xem trước, bạn sẽ thấy rằng tiêu đề của bạn hiện lớn hơn và đậm hơn. Tốt đẹp!


  • Adding Padding to the Recipe Card

Để thêm phần đệm vào thẻ của bạn, hãy bọc tiêu đề và thành phần Text() bên trong một Column() khác và thêm công cụ sửa đổi sau:


Column(modifier = Spacing(16.dp)) {
Text(recipe.title, style = +themeTextStyle { h4 })
for (ingredient in recipe.ingredients) {
Text("• $ingredient")
}
}

Công cụ sửa đổi cho phép bạn điều chỉnh giao diện người dùng của một tập hợp. Trong trường hợp này, bạn đang sử dụng một công cụ sửa đổi để thêm khoảng cách xung quanh cột.


Bạn có thể sử dụng công cụ sửa đổi cho nhiều thứ hơn là khoảng cách, bao gồm cả việc mở rộng một tập hợp hoặc áp dụng một tỷ lệ khung hình.


Xây dựng lại bản xem trước. Bạn sẽ thấy một thẻ công thức tuyệt đẹp:



Recipe card của bạn bây giờ trông tuyệt vời. Đã đến lúc cung cấp cho người dùng của bạn khả năng lập danh sách các công thức nấu ăn yêu thích của họ.


9. Creating a List of Recipes


Thông thường, để tạo danh sách, bạn sẽ sử dụng thứ gì đó giống như RecyclerView. Các tác giả Jetpack Compose vẫn đang nỗ lực tìm cách tốt nhất để tạo danh sách các mục trong bộ công cụ giao diện người dùng mới. Hiện tại, bạn sẽ sử dụng VerticalScroller(). Điều này hoạt động tương tự như ScrollView trong bộ công cụ giao diện người dùng cũ.


Để bắt đầu tập hợp danh sách các công thức nấu ăn của bạn, hãy nhấp chuột phải vào gói mã gốc một lần nữa và chọn New ▸ New Kotlin File / Class. Sau đó chọn File từ danh sách và nhập tên RecipeList. Cuối cùng, thêm RecipeList() vào tệp:


@Composable
fun RecipeList(recipes: List<Recipe>) {
// 1
VerticalScroller {
// 2
Column {
// 3
for (recipe in recipes) {
// 4
Padding(16.dp) {
RecipeCard(recipe)
}
}
}
}
}

Đảm bảo nhập các tài liệu tham khảo còn thiếu. Dưới đây là bảng phân tích những gì bạn vừa thêm:


- Bạn sử dụng VerticalScroller để tạo danh sách các recipe card có thể cuộn được.


- VerticalScroller dự kiến chỉ có một phần tử con, tương tự như cách hoạt động của ScrollView, vì vậy bạn thêm một Column.


- Sau đó, bạn lặp lại từng công thức trong danh sách của mình và tạo RecipeCard, thẻ này sẽ thêm chúng vào Column.


- Cuối cùng, bạn thêm 16 dp đệm xung quanh mỗi RecipeCard để làm cho danh sách trông đẹp hơn.


Giờ đây, bạn đã có một tập hợp để hiển thị danh sách các công thức nấu ăn của mình, đã đến lúc kết nối mọi thứ trong MainActivity và xem công việc khó khăn của bạn trên một thiết bị!


10. Wiring Everything Up


Điều hướng đến MainActivity và thay thế nội dung của setContent() bằng nội dung sau:

MaterialTheme {
RecipeList(defaultRecipes)
}

Bạn cần phải bao gồm MaterialTheme() trong thư mục gốc của nội dung của mình để các thành phần tiếp cận các giá trị chủ đề có thứ gì đó để nắm bắt, giống như bạn đã làm với DefaultRecipeCard().


Xây dựng và chạy. Bạn sẽ thấy một danh sách các món ăn ngon hấp dẫn.





Ứng dụng có vẻ tốt, nhưng nó thiếu thanh công cụ! Bạn sẽ thêm một cái làm bước cuối cùng của mình.


Adding a Toolbar


Có Toolbar là hành vi mặc định của các ứng dụng Android, vì vậy, điều quan trọng là phải bao gồm Thanh công cụ! Thay thế nội dung của setContent() bằng nội dung sau:


MaterialTheme {
// 1
FlexColumn {
// 2
inflexible {
// 3
TopAppBar(title = {
Text("ComposableCookBook")
})
}
// 4
flexible(flex = 1f) {
RecipeList(defaultRecipes)
}
}
}

Đó là rất nhiều thứ mới! Dưới đây là bảng phân tích các khái niệm mới:


- Bạn sử dụng FlexColumn() để chứa thanh ứng dụng và danh sách các công thức nấu ăn của mình. FlexColumn tương tự như một Column thông thường ngoại trừ việc nó sử dụng một hệ thống flex để bố trí và kích thước các thành phần.


Bạn có thể nghĩ về flex như một LinearLayouts với trọng số; nghĩa là, một hệ thống mà bạn định kích thước các mục tùy thuộc vào số lượng các mục khác trong cột.


- Bạn không muốn kích thước thanh công cụ thực bằng flex - thay vào đó, bạn muốn nó có chiều cao tĩnh. Để làm điều này, bạn bọc thanh công cụ trong một lệnh gọi không linh hoạt.


- Sau đó, bạn sử dụng TopAppBar() để tạo một dạng xem ở đầu màn hình tương tự như Thanh công cụ trong bộ công cụ giao diện người dùng hiện tại.


- Cuối cùng, bạn thêm RecipeList của mình và yêu cầu nó mở rộng để lấp đầy khoảng trống còn lại bằng cách đặt cho nó giá trị flex là 1.


Xây dựng và chạy và bạn sẽ thấy một thanh công cụ mới lạ mắt ở đầu ComposeCookbook.




Xin chúc mừng! Bạn đã tạo ứng dụng đầu tiên của mình bằng Jetpack Compose.


11. Where to Go From Here?


Giờ đây, bạn đã trải qua một số thay đổi mới nhất và lớn nhất đến với thế giới giao diện

người dùng trên Android. Nhưng bạn mới chỉ sơ lược về những gì mà Soạn phải cung

cấp và nhiều API này nhất định sẽ thay đổi đáng kể trước khi thư viện ổn định.


Trong hướng dẫn này, bạn đã học về:


Triết lý và động lực đằng sau Jetpack Compose.

Cách tạo một tệp có thể tổng hợp bằng cách sử dụng chú thích @Composable.

Cách xem trước một bản có thể tổng hợp bằng cách sử dụng chú thích @Preview.

Những điều cơ bản về cách bố trí các vật phẩm tổng hợp bằng cách sử dụng Có thể tổng hợp cột.

Cách thêm kiểu chủ đề vào các thành phần của bạn bằng cách sử dụng phương thức +.


Để tìm hiểu thêm về Jetpack Compose, hãy xem tài liệu chính thức dành cho nhà phát triển.


Bạn cũng có thể xem một số yếu tố mới nhất và tuyệt vời đang hoạt động bằng cách duyệt qua ứng dụng mẫu JetNews mà một số tác giả của Jetpack Compose phát triển và duy trì.


Bạn cũng có thể tham khảo khóa học Jetpack Compose Primer từ nhóm khóa học video của chính chúng tôi! Nó bao gồm hầu hết những gì bạn đã đề cập trong hướng dẫn này, nhưng nó đề cập đến một số chi tiết của FlexRow. Bạn cũng có thể xem nó để lặp lại những điều bạn đã học ở đây, trên một ví dụ khác!


Chúng tôi hy vọng rằng bạn thích hướng dẫn này! Nếu bạn có bất kỳ câu hỏi hoặc nhận xét nào, vui lòng tham gia thảo luận diễn đàn bên dưới.






Nhận xét

Bài đăng phổ biến từ blog này

Thiết kế giao diện với DotNetBar (Phần 1)

Đây là phiên bản DotNetBar hỗ trợ C# và Visual Basic https://www.dropbox.com/s/wx80jpvgnlrmtux/DotNetBar.rar  , phiên bản này hỗ trợ giao diện Metro cực kỳ “dễ thương” Các bạn load về và cài đặt, khi cài đặt xong sẽ có source code mẫu của tất cả các control. Để sử dụng được các control của DotNetBar các bạn nhớ add item vào controls box. Thiết kế giao diện với DotNetBar, giao diện sẽ rất đẹp. Link các video hướng dẫn chi tiết cách sử dụng và coding: http://www.devcomponents.com/dotnetbar/movies.aspx Hiện tại DotNetBar có rất nhiều công cụ cực mạnh, trong đó có 3 công cụ dưới đây: DotNetBar for Windows Forms Requires with Visual Studio 2003, 2005, 2008, 2010 or 2012.   DotNetBar for WPF Requires with Visual Studio 2010 or 2012 and Windows Presentation Foundation.   DotNetBar for Silverlight Requires with Visual Studio 2010 or 2012 and Silverlight. Dưới đây là một số hình ảnh về các control trong DotnetBar.   Metro User Interface  controls with Metro Tiles, toolbars, slide panels, forms,

Jetpack Compose VS SwiftUI !VS Flutter

  Việc phát triển Android đã trở nên dễ dàng hơn khi các bản cập nhật liên tục đến. Sau bản cập nhật 2020.3.1, rất nhiều thứ đã thay đổi. Nhưng thay đổi chính mà tôi nghĩ hầu hết các nhà phát triển phải chờ đợi là Jetpack Compose cho ứng dụng sản xuất. Và Kotlin là lựa chọn duy nhất cho jetpack Compose, cũng là ngôn ngữ được ưu tiên. Để biết thêm chi tiết hoặc các thay đổi trên Jetpack Compose, bạn có thể truy cập vào https://developer.android.com/jetpack/compose Tương tự, IOS Development cũng cung cấp một tùy chọn để phát triển khai báo, SwiftUI. Trong IDE, không có thay đổi nào do điều này. Nhưng khái niệm gần giống với Jetpack Compose. Thay vì bảng phân cảnh, chúng tôi tạo giao diện người dùng bằng Swift. Để biết thêm chi tiết hoặc các thay đổi trên SwiftUI, hãy truy cập https://developer.apple.com/xcode/swiftui/ Hãy xem cách cả hai hoạt động bằng cách sử dụng một dự án demo. Tôi đã lấy một số ví dụ về số lần chạm tương tự của Flutter. 1. Android Jetpack Compose Chúng tôi có thể tạo

Announcing Flutter 2

  Phụ lục: Flutter on the web Flutter 2 on desktops, foldables, and embedded devices The growing Flutter ecosystem Dart: The secret sauce behind Flutter Flutter 2: Available now Hôm nay, chúng tôi sẽ công bố Flutter 2: một bản nâng cấp lớn cho Flutter cho phép các nhà phát triển tạo các ứng dụng đẹp, nhanh chóng và di động cho bất kỳ nền tảng nào. Với Flutter 2, bạn có thể sử dụng cùng một cơ sở mã để gửi các ứng dụng gốc cho năm hệ điều hành: IOS, Android, Windows, macOS và Linux; cũng như trải nghiệm web nhắm mục tiêu các trình duyệt như Chrome, Firefox, Safari hoặc Edge. Flutter thậm chí có thể được nhúng vào ô tô, TV và thiết bị gia dụng thông minh, mang đến trải nghiệm di động và lan tỏa nhất cho thế giới điện toán xung quanh. Mục tiêu của chúng tôi là thay đổi cơ bản cách các nhà phát triển nghĩ về việc xây dựng ứng dụng, bắt đầu không phải với nền tảng bạn đang nhắm mục tiêu mà là với trải nghiệm bạn muốn tạo. Flutter cho phép bạn tạo ra những trải nghiệm tuyệt đẹp trong đó thươ