Tạo ứng dụng Đổ xúc xắc có thể tương tác

1. Trước khi bắt đầu

Trong lớp học lập trình này, bạn sẽ tạo một ứng dụng Dice Roller (Đổ xúc xắc) có thể tương tác, cho phép người dùng nhấn vào thành phần kết hợp Button để đổ xúc xắc. Kết quả đổ xúc xắc sẽ xuất hiện với thành phần kết hợp Image trên màn hình.

Bạn sẽ sử dụng Jetpack Compose với Kotlin để tạo bố cục ứng dụng, sau đó viết logic nghiệp vụ để xử lý hoạt động xảy ra khi người dùng nhấn vào thành phần kết hợp Button.

Điều kiện tiên quyết

  • Có thể tạo và chạy một ứng dụng Compose cơ bản trong Android Studio.
  • Quen thuộc với việc sử dụng thành phần kết hợp Text trong ứng dụng.
  • Hiểu biết về cách trích xuất văn bản thành tài nguyên dạng chuỗi để dễ dàng dịch ứng dụng và sử dụng lại các chuỗi.
  • Kiến thức cơ bản về lập trình Kotlin.

Kiến thức bạn sẽ học được

  • Cách thêm thành phần kết hợp Button vào ứng dụng Android bằng Compose.
  • Cách thêm hành vi vào thành phần kết hợp Button trong ứng dụng Android bằng Compose.
  • Cách mở và chỉnh sửa Activity của một ứng dụng Android.

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

  • Một ứng dụng Android có thể tương tác có tên là Dice Roller (Đổ xúc xắc). Ứng dụng này cho phép người dùng đổ xúc xắc và hiển thị kết quả cho người dùng.

Bạn cần có

  • Máy tính đã cài đặt Android Studio.

Dưới đây là giao diện của ứng dụng khi bạn hoàn thành lớp học lập trình này:

3e9a9f44c6c84634.png

2. Thiết lập đường cơ sở

Tạo một dự án

  1. Trong Android Studio, hãy nhấp vào File > New > New Project (Tệp > Mới > Dự án mới).
  2. Trong hộp thoại New Project (Dự án mới), hãy chọn Empty Activity (Hoạt động trống) rồi nhấp vào Next (Tiếp theo).

39373040e14f9c59.png

  1. Trong trường Name (Tên), hãy nhập Dice Roller.
  2. Trong trường Minimum SDK (SDK tối thiểu), hãy chọn cấp độ API tối thiểu là 24 (Nougat) trong trình đơn, sau đó nhấp vào Finish (Hoàn tất).

8fd6db761068ca04.png

3. Tạo cơ sở hạ tầng bố cục

Xem trước dự án

Cách xem trước dự án:

  • Nhấp vào Build & Refresh (Tạo và làm mới) trong ngăn Split (Phân tách) hoặc Design (Thiết kế).

9f1e18365da2f79c.png

Bạn sẽ thấy một bản xem trước trong ngăn Design (Thiết kế). Đừng lo lắng nếu nó trông có vẻ nhỏ vì giao diện này sẽ thay đổi khi bạn sửa đổi bố cục.

b5c9dece74200185.png

Điều chỉnh lại cấu trúc mã mẫu

Bạn cần thay đổi một số mã đã tạo để giống với một ứng dụng đổ xúc xắc.

Bạn có thể thấy ảnh chụp màn hình khi ứng dụng hoàn tất có hình một con xúc xắc và một nút để đổ xúc xắc. Bạn sẽ xây dựng các hàm kết hợp để phản ánh cấu trúc này.

Điều chỉnh cấu trúc đoạn mã mẫu:

  1. Xoá hàm GreetingPreview().
  2. Tạo hàm DiceWithButtonAndImage() có chú thích @Composable.

Hàm kết hợp này đại diện cho các thành phần giao diện người dùng của bố cục, đồng thời giữ logic hiển thị hình ảnh và hành động nhấn vào nút.

  1. Xoá hàm Greeting(name: String, modifier: Modifier = Modifier).
  2. Tạo hàm DiceRollerApp() bằng các chú thích @Preview@Composable.

Vì ứng dụng này chỉ bao gồm một nút và một hình ảnh, hãy xem hàm kết hợp này như chính ứng dụng đó. Do vậy, hàm này có tên là DiceRollerApp().

MainActivity.kt

@Preview
@Composable
fun DiceRollerApp() {

}

@Composable
fun DiceWithButtonAndImage() {

}

Vì bạn đã xoá hàm Greeting() nên lệnh gọi đến Greeting("Android") trong phần thân hàm lambda DiceRollerTheme() sẽ được đánh dấu màu đỏ. Nguyên nhân là trình biên dịch không tìm thấy tham chiếu đến hàm đó nữa.

  1. Xoá toàn bộ mã bên trong hàm lambda setContent{} có trong phương thức onCreate().
  2. Ở phần thân hàm lambda setContent{}, hãy gọi hàm lambda DiceRollerTheme{}, sau đó bên trong hàm lambda DiceRollerTheme{}, hãy gọi hàm DiceRollerApp().

MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        DiceRollerTheme {
            DiceRollerApp()
        }
    }
}
  1. Trong hàm DiceRollerApp(), hãy gọi hàm DiceWithButtonAndImage().

MainActivity.kt

@Preview
@Composable
fun DiceRollerApp() {
    DiceWithButtonAndImage()
}

Thêm đối tượng sửa đổi (modifier)

Compose sử dụng đối tượng Modifier, là một tập hợp các phần tử trang trí hoặc chỉnh sửa hành vi của các phần tử giao diện người dùng trong Compose. Sử dụng các đối tượng này để tạo kiểu cho các thành phần giao diện người dùng của ứng dụng Dice Roller (Đổ xúc xắc).

Cách thêm đối tượng sửa đổi:

  1. Sửa đổi hàm DiceWithButtonAndImage() để chấp nhận đối số modifier thuộc kiểu Modifier và chỉ định giá trị mặc định là Modifier cho đối số này.

MainActivity.kt

@Composable 
fun DiceWithButtonAndImage(modifier: Modifier = Modifier) {
}

Đoạn mã trước có thể khiến bạn thắc mắc, vì vậy hãy xem chi tiết. Hàm này cho phép truyền tham số modifier. Giá trị mặc định của tham số modifier là một đối tượng Modifier, do đó = Modifier là một phần của chữ ký phương thức (method signature). Giá trị mặc định của tham số cho phép những mã gọi phương thức này trong tương lai quyết định có truyền giá trị cho tham số hay không. Nếu truyền đối tượng Modifier của riêng chúng, các mã đó có thể tuỳ chỉnh hành vi và tính năng trang trí của giao diện người dùng. Nếu các mã đó chọn không truyền Modifier, đối tượng này giả định giá trị sẽ là giá trị mặc định (chỉ là đối tượng Modifier). Bạn có thể áp dụng phương pháp này cho bất kỳ tham số nào. Để biết thêm thông tin về đối số mặc định, vui lòng xem phần Đối số mặc định.

  1. Giờ đây, khi thành phần kết hợp DiceWithButtonAndImage() đã có một tham số đối tượng sửa đổi, hãy truyền một đối tượng sửa đổi khi thành phần kết hợp được gọi. Vì chữ ký phương thức cho hàm DiceWithButtonAndImage() đã thay đổi nên đối tượng Modifier có thành phần trang trí mong muốn cần được truyền vào khi gọi lệnh. Lớp Modifier chịu trách nhiệm trang trí hoặc thêm hành vi vào một thành phần kết hợp trong hàm DiceRollerApp(). Trong trường hợp này, cần thêm một số thành phần trang trí quan trọng vào đối tượng Modifier được truyền đến hàm DiceWithButtonAndImage().

Bạn có thể thắc mắc vì sao lại cần truyền một đối số Modifier khi đã có một đối số mặc định. Lý do là vì các thành phần kết hợp có thể trải qua quá trình tái kết hợp, về cơ bản có nghĩa là đoạn mã trong phương thức @Composable sẽ thực thi lại. Nếu một đối tượng Modifier được tạo trong một đoạn mã, khả năng cao nó sẽ được tạo lại và điều đó không hiệu quả. Chúng tôi sẽ nói về quá trình tái kết hợp ở phần sau trong lớp học lập trình này.

MainActivity.kt

DiceWithButtonAndImage(modifier = Modifier)
  1. Liên kết phương thức fillMaxSize() vào đối tượng Modifier để bố cục lấp đầy toàn bộ màn hình.

Phương thức này chỉ định các thành phần cần lấp đầy không gian có sẵn. Trước đó trong lớp học lập trình này, bạn đã thấy ảnh chụp màn hình giao diện người dùng cuối cùng của ứng dụng Dice Roller (Đổ xúc xắc). Một điều đáng chú ý là con xúc xắc và nút được căn giữa trên màn hình. Phương thức wrapContentSize() chỉ định không gian có sẵn tối thiểu phải bằng các thành phần bên trong nó. Tuy nhiên, vì phương thức fillMaxSize() được sử dụng, nên nếu các thành phần bên trong bố cục nhỏ hơn không gian có sẵn, thì đối tượng Alignment có thể được truyền đến phương thức wrapContentSize() chỉ định cách các thành phần cần căn chỉnh trong không gian còn trống.

MainActivity.kt

DiceWithButtonAndImage(modifier = Modifier
    .fillMaxSize()
)
  1. Liên kết phương thức wrapContentSize() vào đối tượng Modifier rồi truyền Alignment.Center làm đối số để căn giữa các thành phần. Alignment.Center chỉ định một thành phần căn giữa cả dọc và ngang.

MainActivity.kt

DiceWithButtonAndImage(modifier = Modifier
    .fillMaxSize()
    .wrapContentSize(Alignment.Center)
)

4. Tạo bố cục dọc

Trong Compose, bố cục dọc được tạo bằng hàm Column().

Hàm Column() là một bố cục thành phần kết hợp có thể đặt các phần tử con theo trình tự dọc. Trong thiết kế ứng dụng dự kiến, bạn có thể thấy hình ảnh xúc xắc hiện theo chiều dọc phía trên nút đổ xúc xắc:

7d70bb14948e3cc1.png

Cách tạo bố cục dọc:

  1. Trong hàm DiceWithButtonAndImage(), hãy thêm một hàm Column().
  1. Truyền đối số modifier từ chữ ký phương thức DiceWithButtonAndImage() vào đối số đối tượng sửa đổi của Column().

Đối số modifier đảm bảo các thành phần kết hợp trong hàm Column() tuân thủ những ràng buộc được gọi trên thực thể modifier.

  1. Truyền một đối số horizontalAlignment vào hàm Column() rồi đặt đối số đó thành giá trị Alignment.CenterHorizontally.

Điều này đảm bảo rằng các phần tử con trong cột được căn giữa trên màn hình thiết bị so với chiều rộng.

MainActivity.kt

fun DiceWithButtonAndImage(modifier: Modifier = Modifier) {
    Column (
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {}
}

5. Thêm nút

  1. Trong tệp strings.xml, hãy thêm một chuỗi và đặt thành giá trị Roll.

res/values/strings.xml

<string name="roll">Roll</string>
  1. Trong phần thân hàm lambda của Column(), hãy thêm một hàm Button().
  1. Trong tệp MainActivity.kt, hãy thêm hàm Text() vào Button() trong nội dung hàm lambda.
  2. Truyền mã tài nguyên chuỗi của chuỗi roll vào hàm stringResource() và truyền kết quả đến hàm kết hợp Text.

MainActivity.kt

Column(
    modifier = modifier,
    horizontalAlignment = Alignment.CenterHorizontally
) {
    Button(onClick = { /*TODO*/ }) {
        Text(stringResource(R.string.roll))
    }
}

6. Thêm hình ảnh

Một thành phần thiết yếu khác của ứng dụng là hình ảnh xúc xắc, hiển thị kết quả khi người dùng nhấn vào nút Roll (Đổ xúc xắc). Việc thêm hình ảnh bằng thành phần kết hợp Image đòi hỏi cần có tài nguyên hình ảnh. Vì vậy, trước tiên, bạn phải tải một số hình ảnh được cung cấp cho ứng dụng này xuống.

Tải hình ảnh xúc xắc xuống

  1. Mở URL này để tải tệp zip chứa hình ảnh xúc xắc xuống máy tính của bạn, sau đó chờ tải xuống hoàn tất.

Xác định tệp trên máy tính của bạn. Tệp này có thể nằm trong thư mục Downloads (Tải xuống) của bạn.

  1. Giải nén tệp zip để tạo thư mục dice_images mới chứa sáu tệp hình ảnh xúc xắc có giá trị xúc xắc từ 1 đến 6.

Thêm hình ảnh xúc xắc vào ứng dụng

  1. Trong Android Studio, hãy nhấp vào View > Tool Windows > Resource Manager (Xem > Cửa sổ công cụ > Trình quản lý tài nguyên).
  2. Nhấp vào + > Import Drawables (Nhập đối tượng có thể vẽ) để mở một trình duyệt tệp.

12f17d0b37dd97d2.png

  1. Tìm và chọn thư mục chứa 6 hình ảnh xúc xắc rồi tiếp tục tải chúng lên.

Các hình ảnh đã tải lên sẽ xuất hiện như sau.

4f66c8187a2c58e2.png

  1. Nhấp vào Next (Tiếp theo).

688772df9c792264.png

Hộp thoại Import Drawables (Nhập đối tượng có thể vẽ) sẽ xuất hiện và cho biết vị trí các tệp tài nguyên nằm trong cấu trúc tệp.

  1. Nhấp vào Import (Nhập) để xác nhận rằng bạn muốn nhập 6 hình ảnh.

Các hình ảnh đó sẽ xuất hiện trong ngăn Resource Manager (Trình quản lý tài nguyên).

c2f08e5311f9a111.png

Bạn làm tốt lắm! Ở nhiệm vụ tiếp theo, bạn sẽ dùng các hình ảnh này trong ứng dụng của mình.

Thêm một thành phần kết hợp Image

Hình ảnh xúc xắc phải xuất hiện phía trên nút Roll (Đổ xúc xắc). Compose vốn đặt các thành phần giao diện người dùng theo tuần tự. Hay nói cách khác, bất kỳ thành phần kết hợp nào được khai báo trước sẽ hiển thị trước. Điều này có nghĩa là thành phần khai báo đầu tiên sẽ hiển thị ở trên hoặc phía trước, tiếp theo đó là thành phần kết hợp được khai báo sau. Các thành phần kết hợp bên trong một thành phần Column sẽ xuất hiện bên trên/dưới nhau trên thiết bị. Trong ứng dụng này, bạn sẽ dùng Column để sắp xếp các Thành phấn kết hợp theo chiều dọc, do đó bất kỳ thành phần kết hợp nào được khai báo trước trong hàm Column() cũng sẽ hiển thị trước thành phần kết hợp được khai báo sau nó trong cùng một hàm Column().

Cách thêm một thành phần kết hợp Image:

  1. Trong nội dung hàm Column(), hãy tạo một hàm Image() trước hàm Button().

MainActivity.kt

Column(
    modifier = modifier,
    horizontalAlignment = Alignment.CenterHorizontally
) {
    Image()
    Button(onClick = { /*TODO*/ }) {
      Text(stringResource(R.string.roll))
    }
}
  1. Truyền vào hàm Image() một đối số painter, sau đó chỉ định giá trị painterResource chấp nhận đối số mã tài nguyên có thể vẽ. Lúc này, hãy truyền mã tài nguyên sau: đối số R.drawable.dice_1.

MainActivity.kt

Image(
    painter = painterResource(R.drawable.dice_1)
)
  1. Bất cứ khi nào tạo Hình ảnh trong ứng dụng của mình, bạn cũng phải cung cấp "mô tả nội dung". Mô tả nội dung là một phần quan trọng trong quá trình phát triển Android. Chúng đính kèm nội dung mô tả vào các thành phần giao diện người dùng tương ứng để tăng khả năng tiếp cận. Để biết thêm thông tin về phần mô tả nội dung, vui lòng xem Mô tả từng thành phần trên giao diện người dùng. Bạn có thể truyền phần mô tả nội dung vào hình ảnh dưới dạng tham số.

MainActivity.kt

Image(
    painter = painterResource(R.drawable.dice_1),
    contentDescription = "1"
)

Hiện đã có tất cả các thành phần giao diện người dùng cần thiết. Nhưng ButtonImage đang hơi gần nhau.

54b27140071ac2fa.png

  1. Để khắc phục vấn đề đó, hãy thêm một thành phần kết hợp Spacer giữa các thành phần kết hợp ImageButton. Spacer lấy Modifier làm tham số. Trong trường hợp này, Image nằm phía trên Button nên cần có một khoảng trống theo chiều dọc giữa chúng. Do đó, bạn có thể đặt chiều cao của Modifier để áp dụng cho Spacer. Hãy thử đặt chiều cao là 16.dp. Thông thường, kích thước dp tăng theo từng bậc 4.dp.

MainActivity.kt

Spacer(modifier = Modifier.height(16.dp))
  1. Trong ngăn Preview (Xem trước), hãy nhấp vào Build & Refresh (Tạo và làm mới).

Bạn sẽ thấy nội dung tương tự như hình ảnh sau:

73eea4c166f7e9d2.png

7. Tạo logic dice-roll (đổ xúc xắc)

Giờ đây, khi đã có tất cả các thành phần kết hợp cần thiết, bạn hãy chỉnh sửa ứng dụng để khi chỉ cần nhấn nút, xúc xắc sẽ được gieo.

Tạo Nút (Button) tương tác

  1. Trong hàm DiceWithButtonAndImage() trước hàm Column(), hãy tạo một biến result và đặt biến đó bằng giá trị 1.
  2. Hãy xem thành phần kết hợp Button. Bạn sẽ thấy nó đang được truyền tham số onClick, được đặt thành một cặp dấu ngoặc nhọn với chú thích /*TODO*/ bên trong. Trong trường hợp này, dấu ngoặc nhọn đại diện cho hàm lambda, phần bên trong dấu ngoặc nhọn là nội dung hàm lambda. Khi một hàm được truyền làm đối số, hàm này còn được gọi là "lệnh gọi lại".

MainActivity.kt

Button(onClick = { /*TODO*/ })

Hàm lambda là một hằng hàm. Hàm này giống như mọi hàm khác nhưng thay vì được khai báo riêng bằng từ khoá fun, hàm này được viết cùng dòng và truyền dưới dạng một biểu thức. Nút thành phần kết hợp Button dự kiến sẽ truyền một hàm làm tham số onClick. Đây là nơi hoàn hảo để sử dụng hàm lambda và bạn sẽ viết phần thân hàm lambda trong mục này.

  1. Ở hàm Button(), hãy xoá bình luận /*TODO*/ khỏi giá trị trong phần thân hàm lambda của tham số onClick.
  2. Kết quả đổ xúc xắc là ngẫu nhiên. Để thể hiện điều đó trong mã, bạn cần sử dụng cú pháp chính xác để tạo một số ngẫu nhiên. Trong Kotlin, bạn có thể sử dụng phương thức random() trên một dãy số. Trong nội dung hàm lambda onClick, hãy đặt biến result thành một dải ô từ 1 đến 6, sau đó gọi phương thức random() trên dải ô đó. Lưu ý trong Kotlin, các dải ô được chỉ định bằng 2 dấu chấm giữa số đầu tiên và số cuối cùng trong dải ô.

MainActivity.kt

fun DiceWithButtonAndImage(modifier: Modifier = Modifier) {
    var result = 1
    Column(
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Image(
            painter = painterResource(R.drawable.dice_1),
            contentDescription = "1"
        )
        Spacer(modifier = Modifier.height(16.dp))
        Button(onClick = { result = (1..6).random() }) {
            Text(stringResource(R.string.roll))
        }
    }
}

Nút này hiện có thể nhấn được, nhưng việc nhấn nút không gây ra bất kỳ thay đổi nào về hình ảnh, vì bạn vẫn cần tạo chức năng đó.

Thêm điều kiện vào ứng dụng đổ xúc xắc

Trong phần trước, bạn đã tạo một biến result và mã hoá cứng nó thành giá trị 1. Tóm lại, giá trị của biến result được đặt lại khi bạn nhấn vào nút Roll (Đổ xúc xắc) và xác định hình ảnh nào sẽ hiển thị.

Các thành phần kết hợp không có trạng thái theo mặc định, nghĩa là chúng không lưu giữ giá trị và có thể được hệ thống kết hợp lại bất kỳ lúc nào, dẫn đến việc giá trị bị đặt lại. Tuy nhiên, Compose cung cấp một phương thức thuận tiện để tránh điều này. Hàm kết hợp có thể lưu trữ đối tượng trong bộ nhớ bằng cách sử dụng thành phần kết hợp remember.

  1. Đặt biến result thành một thành phần kết hợp remember.

Thành phần kết hợp remember yêu cầu phải truyền một hàm.

  1. Trong phần thân của thành phần kết hợp remember, hãy truyền vào một hàm mutableStateOf(), sau đó truyền cho hàm một đối số 1.

Hàm mutableStateOf() trả về một đối tượng có thể quan sát. Bạn sẽ tìm hiểu thêm về các đối tượng có thể quan sát nhưng về cơ bản, điều này có nghĩa là khi giá trị của biến result thay đổi, hệ thống sẽ kích hoạt một quá trình tái kết hợp phản ánh giá trị của kết quả và giao diện người dùng được làm mới.

MainActivity.kt

var result by remember { mutableStateOf(1) }

Giờ đây, khi người dùng nhấn vào nút này, biến result sẽ được cập nhật bằng giá trị của số ngẫu nhiên.

Biến result hiện có thể được dùng để xác định hình ảnh nào sẽ hiển thị.

  1. Sau khi tạo thực thể của biến result, hãy tạo một biến imageResource không thể thay đổi và đặt biến này thành biểu thức when chấp nhận biến result, sau đó đặt từng kết quả khả thi thành đối tượng có thể vẽ của nó.

MainActivity.kt

val imageResource = when (result) {
    1 -> R.drawable.dice_1
    2 -> R.drawable.dice_2
    3 -> R.drawable.dice_3
    4 -> R.drawable.dice_4
    5 -> R.drawable.dice_5
    else -> R.drawable.dice_6
}
  1. Thay đổi mã được truyền đến tham số painterResource của thành phần kết hợp Image từ đối tượng có thể vẽ R.drawable.dice_1 thành biến imageResource.
  2. Thay đổi tham số contentDescription của thành phần kết hợp Image để phản ánh giá trị biến result bằng cách truyền đổi biến result thành một chuỗi bằng toString() và truyền biến đó dưới dạng contentDescription.

MainActivity.kt

Image(
   painter = painterResource(imageResource),
   contentDescription = result.toString()
)
  1. Chạy ứng dụng của bạn.

Ứng dụng Dice Roller (Đổ xúc xắc) của bạn hiện đã sẵn sàng hoạt động!

3e9a9f44c6c84634.png

8. Lấy mã giải pháp

Để tải xuống mã cho lớp học lập trình đã kết thúc, bạn có thể sử dụng lệnh git này:

$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-dice-roller.git

Ngoài ra, bạn có thể tải kho lưu trữ xuống dưới dạng tệp zip, sau đó giải nén và mở trong Android Studio.

Nếu bạn muốn xem mã giải pháp, hãy xem mã đó trên GitHub.

  1. Chuyển đến trang kho lưu trữ GitHub được cung cấp cho dự án.
  2. Xác minh rằng tên nhánh khớp với tên nhánh được chỉ định trong lớp học lập trình. Ví dụ: trong ảnh chụp màn hình sau đây, tên nhánh là main.

1e4c0d2c081a8fd2.png

  1. Trên trang GitHub cho dự án này, nhấp vào nút Code (Mã). Thao tác này sẽ khiến một cửa sổ bật lên.

1debcf330fd04c7b.png

  1. Trong cửa sổ bật lên, nhấp vào nút Download ZIP (Tải tệp ZIP xuống) để lưu dự án vào máy tính. Chờ quá trình tải xuống hoàn tất.
  2. Xác định vị trí của tệp trên máy tính (thường nằm trong thư mục Downloads (Tệp đã tải xuống)).
  3. Nhấp đúp vào tệp ZIP để giải nén. Thao tác này sẽ tạo một thư mục mới chứa các tệp dự án.

Mở dự án trong Android Studio

  1. Khởi động Android Studio.
  2. Trong cửa sổ Welcome to Android Studio (Chào mừng bạn đến với Android Studio), hãy nhấp vào Open (Mở).

d8e9dbdeafe9038a.png

Lưu ý: Nếu Android Studio đã mở thì chuyển sang chọn tuỳ chọn File (Tệp) > Open (Mở) trong trình đơn.

8d1fda7396afe8e5.png

  1. Trong trình duyệt tệp, hãy chuyển đến vị trí của thư mục dự án chưa giải nén (thường nằm trong thư mục Downloads (Tệp đã tải xuống)).
  2. Nhấp đúp vào thư mục dự án đó.
  3. Chờ Android Studio mở dự án.
  4. Nhấp vào nút Run (Chạy) 8de56cba7583251f.png để tạo bản dựng và chạy ứng dụng. Đảm bảo ứng dụng được xây dựng như mong đợi.

9. Kết luận

Bạn đã tạo một ứng dụng Dice Roller (Đổ xúc xắc) tương tác dành cho Android bằng Compose!

Tóm tắt

  • Xác định các hàm kết hợp.
  • Tạo bố cục bằng Thành phần kếp hợp.
  • Tạo một nút bằng thành phần kết hợp Button.
  • Nhập tài nguyên drawable.
  • Hiển thị hình ảnh bằng thành phần kết hợp Image.
  • Tạo giao diện người dùng tương tác bằng thành phần kết hợp.
  • Sử dụng thành phần kết hợp remember để lưu trữ đối tượng trong Thành phần kết hợp vào bộ nhớ.
  • Làm mới giao diện người dùng bằng hàm mutableStateOf() để quan sát.

Tìm hiểu thêm