Phát triển giao diện người dùng bằng Jetpack Compose cho XR

Với Jetpack Compose cho XR, bạn có thể tạo giao diện người dùng không gian và bố cục theo cách khai báo bằng các khái niệm quen thuộc của Compose, chẳng hạn như hàng và cột. Điều này cho phép bạn mở rộng giao diện người dùng Android hiện có vào không gian 3D hoặc xây dựng các ứng dụng 3D sống động hoàn toàn mới.

Nếu đang tạo không gian cho một ứng dụng hiện có dựa trên Khung hiển thị Android, bạn có một số tuỳ chọn phát triển. Bạn có thể sử dụng các API có khả năng tương tác, sử dụng Compose và Khung hiển thị cùng nhau hoặc làm việc trực tiếp với thư viện SceneCore. Hãy xem hướng dẫn về cách làm việc với thành phần hiển thị để biết thêm thông tin chi tiết.

Giới thiệu về không gian con và thành phần không gian

Khi viết ứng dụng cho Android XR, bạn cần nắm được các khái niệm về không gian conthành phần không gian.

Giới thiệu về không gian con

Khi phát triển cho Android XR, bạn cần thêm một không gian con vào ứng dụng hoặc bố cục. Không gian con là một phân vùng của không gian 3D trong ứng dụng, nơi bạn có thể đặt nội dung 3D, tạo bố cục 3D và thêm chiều sâu vào nội dung 2D. Không gian con chỉ được kết xuất khi bạn bật tính năng không gian. Trong Không gian nhà hoặc trên các thiết bị không phải XR, mọi mã trong không gian con đó sẽ bị bỏ qua.

Có hai cách để tạo không gian con:

  • setSubspaceContent: Hàm này tạo một không gian con cấp ứng dụng. Bạn có thể gọi phương thức này trong MainActivity giống như cách bạn sử dụng setContent. Không gian con cấp ứng dụng không giới hạn chiều cao, chiều rộng và chiều sâu, về cơ bản cung cấp một canvas vô hạn cho nội dung không gian.
  • Subspace: Bạn có thể đặt thành phần kết hợp này ở bất kỳ vị trí nào trong hệ phân cấp giao diện người dùng của ứng dụng, cho phép bạn duy trì bố cục cho giao diện người dùng 2D và không gian mà không làm mất ngữ cảnh giữa các tệp. Điều này giúp bạn dễ dàng chia sẻ những thứ như cấu trúc ứng dụng hiện có giữa XR và các hệ số hình dạng khác mà không cần chuyển trạng thái lên trên toàn bộ cây giao diện người dùng hoặc thiết kế lại ứng dụng.

Để biết thêm thông tin, hãy đọc bài viết về cách thêm không gian con vào ứng dụng.

Giới thiệu về thành phần không gian

Thành phần kết hợp không gian con: Các thành phần này chỉ có thể hiển thị trong không gian con. Các thành phần này phải được bao bọc trong Subspace hoặc setSubspaceContent trước khi được đặt trong bố cục 2D. SubspaceModifier cho phép bạn thêm các thuộc tính như chiều sâu, độ dời và vị trí vào các thành phần kết hợp không gian con.

  • Lưu ý về đối tượng sửa đổi không gian con: Hãy chú ý đến thứ tự của các API SubspaceModifier.
    • Trước tiên, độ lệch phải xảy ra trong chuỗi đối tượng sửa đổi
    • Tính năng di chuyển và đổi kích thước phải xuất hiện sau cùng
    • Phải áp dụng chế độ xoay trước khi điều chỉnh theo tỷ lệ

Các thành phần không gian khác không yêu cầu được gọi bên trong một không gian con. Các lớp này bao gồm các phần tử 2D thông thường được gói trong một vùng chứa không gian. Bạn có thể sử dụng các phần tử này trong bố cục 2D hoặc 3D nếu xác định cho cả hai. Khi bạn không bật tính năng không gian hoá, các tính năng không gian hoá của chúng sẽ bị bỏ qua và chúng sẽ quay lại các đối tác 2D.

Tạo bảng điều khiển không gian

SpatialPanel là một thành phần kết hợp không gian con cho phép bạn hiển thị nội dung ứng dụng. Ví dụ: bạn có thể hiển thị chế độ phát video, hình ảnh tĩnh hoặc bất kỳ nội dung nào khác trong bảng điều khiển không gian.

Ví dụ về bảng điều khiển giao diện người dùng không gian

Bạn có thể sử dụng SubspaceModifier để thay đổi kích thước, hành vi và vị trí của bảng điều khiển không gian, như trong ví dụ sau.

Subspace {
   SpatialPanel(
        SubspaceModifier
           .height(824.dp)
           .width(1400.dp)
           .movable()
           .resizable()
           ) {
          SpatialPanelContent()
      }
}

// 2D content placed within the spatial panel
@Composable
fun SpatialPanelContent(){
    Box(
        Modifier
            .background(color = Color.Black)
            .height(500.dp)
            .width(500.dp),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = "Spatial Panel",
            color = Color.White,
            fontSize = 25.sp
        )
    }
}

Các điểm chính về mã

  • Lưu ý về đối tượng sửa đổi không gian con: Hãy chú ý đến thứ tự của các API SubspaceModifier.
    • Trước tiên, độ dời phải xảy ra trong một chuỗi đối tượng sửa đổi.
    • Các đối tượng sửa đổi có thể di chuyển và đổi kích thước phải xuất hiện sau cùng.
    • Bạn phải áp dụng chế độ xoay trước khi điều chỉnh tỷ lệ.
  • Vì các API SpatialPanel là các thành phần kết hợp không gian con, nên bạn phải gọi các API này bên trong Subspace hoặc setSubspaceContent. Việc gọi các phương thức này bên ngoài một không gian con sẽ gửi một ngoại lệ.
  • Cho phép người dùng đổi kích thước hoặc di chuyển bảng điều khiển bằng cách thêm .movable hoặc .resizable SubspaceModifier.
  • Hãy xem hướng dẫn thiết kế bảng điều khiển không gian để biết thông tin chi tiết về cách định cỡ và định vị. Hãy xem tài liệu tham khảo của chúng tôi để biết thêm thông tin chi tiết về cách triển khai mã.

Tạo tàu vũ trụ bay quanh quỹ đạo

Tàu bay quỹ đạo là một thành phần giao diện người dùng không gian. Thành phần này được thiết kế để đính kèm vào một bảng điều khiển không gian tương ứng và chứa các mục thao tác điều hướng và theo ngữ cảnh liên quan đến bảng điều khiển không gian đó. Ví dụ: nếu đã tạo một bảng điều khiển không gian để hiển thị nội dung video, bạn có thể thêm các nút điều khiển phát video bên trong một vệ tinh nhân tạo.

Ví dụ về tàu vũ trụ bay quanh quỹ đạo

Như trong ví dụ sau, hãy gọi một vệ tinh nhân tạo bên trong SpatialPanel để gói các thành phần điều khiển của người dùng như điều hướng. Thao tác này sẽ trích xuất các thành phần đó từ bố cục 2D và đính kèm các thành phần đó vào bảng điều khiển không gian theo cấu hình của bạn.

setContent {
    Subspace {
        SpatialPanel(
            SubspaceModifier
                .height(824.dp)
                .width(1400.dp)
                .movable()
                .resizable()
        ) {
            SpatialPanelContent()
            OrbiterExample()
        }
    }
}

//2D content inside Orbiter
@Composable
fun OrbiterExample() {
    Orbiter(
        position = OrbiterEdge.Bottom,
        offset = 96.dp,
        alignment = Alignment.CenterHorizontally
    ) {
        Surface(Modifier.clip(CircleShape)) {
            Row(
                Modifier
                    .background(color = Color.Black)
                    .height(100.dp)
                    .width(600.dp),
                horizontalArrangement = Arrangement.Center,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(
                    text = "Orbiter",
                    color = Color.White,
                    fontSize = 50.sp
                )
            }
        }
    }
}

Các điểm chính về mã

  • Lưu ý về Đối tượng sửa đổi không gian con: Hãy chú ý đến thứ tự của các API SubspaceModifier.
    • Trước tiên, độ lệch phải xảy ra trong chuỗi đối tượng sửa đổi
    • Tính năng di chuyển và đổi kích thước phải xuất hiện sau cùng
    • Phải áp dụng chế độ xoay trước khi điều chỉnh theo tỷ lệ
  • Vì vệ tinh là các thành phần giao diện người dùng không gian, nên mã có thể được sử dụng lại trong bố cục 2D hoặc 3D. Trong bố cục 2D, ứng dụng của bạn chỉ hiển thị nội dung bên trong vệ tinh và bỏ qua chính vệ tinh đó.
  • Hãy xem hướng dẫn thiết kế của chúng tôi để biết thêm thông tin về cách sử dụng và thiết kế vệ tinh bay vòng quanh.

Thêm nhiều bảng điều khiển không gian vào bố cục không gian

Bạn có thể tạo nhiều bảng điều khiển không gian và đặt các bảng điều khiển đó trong một SpatialLayout bằng cách sử dụng SpatialRow, SpatialColumn, SpatialBoxSpatialLayoutSpacer.

Ví dụ về nhiều bảng không gian trong bố cục không gian

Mã ví dụ sau đây cho thấy cách thực hiện việc này.

Subspace {
    SpatialRow {
        SpatialColumn {
            SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) {
                SpatialPanelContent("Top Left")
            }
            SpatialPanel(SubspaceModifier.height(200.dp).width(400.dp)) {
                SpatialPanelContent("Middle Left")
            }
            SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) {
                SpatialPanelContent("Bottom Left")
            }
        }
        SpatialColumn {
            SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) {
                SpatialPanelContent("Top Right")
            }
            SpatialPanel(SubspaceModifier.height(200.dp).width(400.dp)) {
                SpatialPanelContent("Middle Right")
            }
            SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) {
                SpatialPanelContent("Bottom Right")
            }
        }
    }
}

@Composable
fun SpatialPanelContent(text: String) {
    Column(
        Modifier
            .background(color = Color.Black)
            .fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = "Panel",
            color = Color.White,
            fontSize = 15.sp
        )
        Text(
            text = text,
            color = Color.White,
            fontSize = 25.sp,
            fontWeight = FontWeight.Bold
        )
    }
}

Các điểm chính về mã

  • SpatialRow, SpatialColumn, SpatialBoxSpatialLayoutSpacer đều là các thành phần kết hợp không gian con và phải được đặt trong một không gian con.
  • Sử dụng SubspaceModifier để tuỳ chỉnh bố cục.
  • Đối với bố cục có nhiều bảng điều khiển trong một hàng, bạn nên đặt bán kính cong là 825 dp bằng cách sử dụng SubspaceModifier để các bảng điều khiển bao quanh người dùng. Hãy xem hướng dẫn thiết kế của chúng tôi để biết thông tin chi tiết.

Sử dụng phương tiện để đặt đối tượng 3D trong bố cục

Để đặt một đối tượng 3D trong bố cục, bạn cần sử dụng một thành phần kết hợp không gian con có tên là khối lượng. Sau đây là ví dụ về cách thực hiện.

Ví dụ về đối tượng 3D trong bố cục

Subspace {
    SpatialPanel(
        SubspaceModifier.height(1500.dp).width(1500.dp)
            .resizable().movable()
    ) {
        ObjectInAVolume(true)
            Box(
                Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    text = "Welcome",
                    fontSize = 50.sp,
                )
            }
        }
    }
}

@Composable
fun ObjectInAVolume(show3DObject: Boolean) {
    val xrCoreSession = checkNotNull(LocalSession.current)
    val scope = rememberCoroutineScope()
    if (show3DObject) {
        Subspace {
            Volume(
                modifier = SubspaceModifier
                    .offset(volumeXOffset, volumeYOffset, volumeZOffset) //
Relative position
                    .scale(1.2f) // Scale to 120% of the size

            ) { parent ->
                scope.launch {
                   // Load your 3D Object here
                }
            }
        }
    }
}

Các điểm chính về mã

  • Lưu ý về Đối tượng sửa đổi không gian con: Hãy chú ý đến thứ tự của các API SubspaceModifier.
    • Trước tiên, độ dời phải xảy ra trong chuỗi đối tượng sửa đổi
    • Tính năng di chuyển và đổi kích thước phải xuất hiện sau cùng
    • Phải áp dụng chế độ xoay trước khi điều chỉnh theo tỷ lệ
  • Hãy xem phần Thêm nội dung 3D để hiểu rõ hơn về cách tải nội dung 3D trong một phương tiện.

Thêm các thành phần giao diện người dùng không gian khác

Bạn có thể đặt các thành phần giao diện người dùng không gian ở bất kỳ vị trí nào trong hệ phân cấp giao diện người dùng của ứng dụng. Bạn có thể sử dụng lại các phần tử này trong giao diện người dùng 2D và các thuộc tính không gian của chúng sẽ chỉ hiển thị khi bạn bật các tính năng không gian. Điều này cho phép bạn thêm độ cao vào trình đơn, hộp thoại và các thành phần khác mà không cần viết mã hai lần. Hãy xem các ví dụ sau về giao diện người dùng không gian để hiểu rõ hơn về cách sử dụng các thành phần này.

Thành phần giao diện người dùng

Khi tính năng không gian được bật

Trong môi trường 2D

SpatialDialog

Bảng điều khiển sẽ đẩy nhẹ về sau theo chiều sâu z để hiển thị hộp thoại nâng cao

Quay lại chế độ 2D Dialog.

SpatialPopUp

Bảng điều khiển sẽ đẩy nhẹ về sau trong chiều sâu z để hiển thị một cửa sổ bật lên nâng cao

Quay lại PopUp 2D.

SpatialElevation

Bạn có thể đặt SpatialElevationLevel để thêm độ cao.

Chương trình không có độ cao không gian.

SpatialDialog

Đây là ví dụ về một hộp thoại mở ra sau một khoảng thời gian trễ ngắn. Khi sử dụng SpatialDialog, hộp thoại sẽ xuất hiện ở cùng độ sâu z với bảng điều khiển không gian và bảng điều khiển sẽ được đẩy lùi 125 dp khi bật tính năng không gian. Bạn vẫn có thể sử dụng SpatialDialog khi không bật tính năng không gian và quay lại phiên bản 2D: Dialog.

@Composable
fun DelayedDialog() {
   var showDialog by remember { mutableStateOf(false) }
   LaunchedEffect(Unit) {
       Handler(Looper.getMainLooper()).postDelayed({
           showDialog = true
       }, 3000)
   }
   if (showDialog) {
       SpatialDialog (
           onDismissRequest = { showDialog = false },
           SpatialDialogProperties(
               dismissOnBackPress = true)
       ){
           Box(Modifier
               .height(150.dp)
               .width(150.dp)
           ) {
               Button(onClick = { showDialog = false }) {
                   Text("OK")
               }
           }
       }
   }
}

Các điểm chính về mã

Tạo bảng điều khiển và bố cục tuỳ chỉnh

Để tạo các bảng điều khiển tuỳ chỉnh mà Compose for XR không hỗ trợ, bạn có thể làm việc trực tiếp với PanelEntities và biểu đồ cảnh bằng cách sử dụng các API SceneCore.

Xem thêm