XR için Jetpack Compose ile kullanıcı arayüzü geliştirme

XR için Jetpack Compose ile satır ve sütun gibi bilinen Compose kavramlarını kullanarak uzamsal kullanıcı arayüzünüzü ve düzeninizi açık bir şekilde oluşturabilirsiniz. Bu sayede mevcut Android kullanıcı arayüzünüzü 3D alana genişletebilir veya tamamen yeni, sürükleyici 3D uygulamalar oluşturabilirsiniz.

Mevcut bir Android Views tabanlı uygulamayı mekansallaştırıyorsanız birkaç geliştirme seçeneğiniz vardır. Birlikte çalışabilirlik API'lerini, Compose ve Views'ı birlikte kullanabilir veya doğrudan SceneCore kitaplığıyla çalışabilirsiniz. Daha fazla bilgi için görüntülemelerle çalışma kılavuzumuzu inceleyin.

Alt alanlar ve uzamsal bileşenler hakkında

Android XR için uygulamanızı yazarken alt alan ve uzamsallaştırılmış bileşenler kavramlarını anlamanız önemlidir.

Alt alan hakkında

Android XR için geliştirirken uygulamanıza veya düzeninize bir alt alan eklemeniz gerekir. Alt alan, uygulamanızda 3D içerik yerleştirebileceğiniz, 3D düzenler oluşturabileceğiniz ve aksi takdirde 2D olan içeriğe derinlik ekleyebileceğiniz 3D alanın bir bölümüdür. Alt alan yalnızca uzamsallaştırma etkinleştirildiğinde oluşturulur. Ana alanda veya XR olmayan cihazlarda, bu alt alan içindeki tüm kodlar yoksayılır.

Alt alan oluşturmanın iki yolu vardır:

  • setSubspaceContent(): Bu işlev, uygulama düzeyinde bir alt alan oluşturur. Bu, ana etkinliğinizde setContent()'u kullandığınız şekilde çağrılabilir. Uygulama düzeyinde alt uzay, yükseklik, genişlik ve derinlik açısından sınırsızdır. Bu sayede, uzamsal içerik için sonsuz bir tuval sağlar.
  • Subspace: Bu bileşen, uygulamanızın kullanıcı arayüzü hiyerarşisinin herhangi bir yerine yerleştirilebilir. Böylece, dosyalar arasında bağlamı kaybetmeden 2D ve mekansal kullanıcı arayüzü için düzenleri koruyabilirsiniz. Bu sayede, kullanıcı arayüzü ağacınızın tamamında durumu kaldırmak veya uygulamanızı yeniden tasarlamak zorunda kalmadan mevcut uygulama mimarisi gibi öğeleri XR ile diğer form faktörleri arasında paylaşabilirsiniz.

Daha fazla bilgi için Uygulamanıza alt alan adı ekleme başlıklı makaleyi inceleyin.

Mekansal bileşenler hakkında

Alt alan bileşenleri: Bu bileşenler yalnızca bir alt alanda oluşturulabilir. 2D bir düzene yerleştirilmeden önce Subspace veya setSubspaceContent içine alınmalıdır. SubspaceModifier, alt alan bileşimlerinize derinlik, ofset ve konumlandırma gibi özellikler eklemenize olanak tanır.

Diğer uzamsal bileşenlerin bir alt uzayda çağrılması gerekmez. Bunlar, bir mekansal kapsayıcıya yerleştirilmiş geleneksel 2D öğelerden oluşur. Bu öğeler, her ikisi için de tanımlanmışsa 2D veya 3D düzenlerde kullanılabilir. Mekansallaştırma etkinleştirilmediğinde, bu öğelerin mekansallaştırılmış özellikleri yoksayılır ve 2D karşılıklarına geri dönerler.

Mekansal panel oluşturma

SpatialPanel, uygulama içeriğini görüntülemenizi sağlayan bir alt alan bileşimidir. Örneğin, video oynatma, hareketsiz resimler veya diğer içerikleri bir mekansal panelde görüntüleyebilirsiniz.

Mekansal kullanıcı arayüzü paneli örneği

Aşağıdaki örnekte gösterildiği gibi, SubspaceModifier simgesini kullanarak mekansal panelin boyutunu, davranışını ve konumunu değiştirebilirsiniz.

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

Kodla ilgili önemli noktalar

Yörünge aracı oluşturma

Yörünge, mekansal bir kullanıcı arayüzü bileşenidir. İlgili bir mekansal panele, düzene veya başka bir öğeye eklenecek şekilde tasarlanmıştır. Yörüngeleyiciler genellikle sabitlendiği öğeyle ilgili gezinme ve bağlamsal işlem öğeleri içerir. Örneğin, video içeriği görüntülemek için bir uzamsal panel oluşturduysanız bir yörünge aracının içine video oynatma kontrolleri ekleyebilirsiniz.

Yörünge aracı örneği

Aşağıdaki örnekte gösterildiği gibi, gezinme gibi kullanıcı denetimlerini sarmalamak için SpatialPanel içinde 2D düzenin içine bir yörünge çağrısı yapın. Bu işlem, öğeleri 2D düzeninizden ayıklayıp yapılandırmanıza göre mekansal panele ekler.

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

Kodla ilgili önemli noktalar

  • Yörünge bileşenleri, mekansal kullanıcı arayüzü bileşenleri olduğundan kod 2D veya 3D düzenlerde yeniden kullanılabilir. 2D düzende uygulamanız yalnızca yörünge aracının içindeki içeriği oluşturur ve yörünge aracının kendisini yoksayar.
  • Yörünge araçlarının nasıl kullanılacağı ve tasarlanacağı hakkında daha fazla bilgi için tasarım yönergelerimize göz atın.

Mekansal bir düzene birden fazla mekansal panel ekleme

SpatialRow, SpatialColumn, SpatialBox ve SpatialLayoutSpacer simgesini kullanarak birden fazla mekansal panel oluşturabilir ve bunları bir mekansal düzene yerleştirebilirsiniz.

Mekansal düzende birden fazla mekansal panel örneği

Aşağıdaki kod örneğinde bunun nasıl yapılacağı gösterilmektedir.

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

Kodla ilgili önemli noktalar

Düzeninize 3D nesne yerleştirmek için bir birim kullanın

3D bir nesneyi düzeninize yerleştirmek için hacim adı verilen bir alt alan bileşimi kullanmanız gerekir. Aşağıda bunu nasıl yapacağınıza dair bir örnek verilmiştir.

Bir düzendeki 3D nesne örneği

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

Kodla ilgili önemli noktalar

Diğer mekansal kullanıcı arayüzü bileşenlerini ekleme

Mekansal kullanıcı arayüzü bileşenleri, uygulamanızın kullanıcı arayüzü hiyerarşisinin herhangi bir yerine yerleştirilebilir. Bu öğeler 2D kullanıcı arayüzünüzde yeniden kullanılabilir ve bu öğelerin uzamsal özellikleri yalnızca uzamsal özellikler etkinleştirildiğinde görünür. Bu sayede, kodunuzu iki kez yazmak zorunda kalmadan menülere, iletişim kutularına ve diğer bileşenlere yükseklik ekleyebilirsiniz. Bu öğeleri nasıl kullanacağınızı daha iyi anlamak için aşağıdaki mekansal kullanıcı arayüzü örneklerine göz atın.

Kullanıcı Arayüzü Bileşeni

Uzamsallaştırma etkinleştirildiğinde

2D ortamda

SpatialDialog

Panel, yükseltilmiş bir iletişim kutusu görüntülemek için z-derinliğinde biraz geriye itilir.

2D'ye Dialog geri döner.

SpatialPopUp

Panel, yükseltilmiş bir pop-up görüntülemek için z-derinliğinde biraz geriye itilir.

2D PopUp olarak geri döner.

SpatialElevation

SpatialElevationLevel, yükseklik eklemek için ayarlanabilir.

Mekansal yükseklik bilgisi içermeyen programlar.

SpatialDialog

Bu, kısa bir gecikme sonrasında açılan bir iletişim kutusu örneğidir. SpatialDialog kullanıldığında iletişim kutusu, uzamsal panelle aynı z-derinliğinde görünür ve uzamsallaştırma etkinleştirildiğinde panel 125 dp geriye itilir. SpatialDialog, uzamsallaştırma etkin olmadığında da kullanılabilir. Bu durumda SpatialDialog, 2D karşılığı olan Dialog'ye geri döner.

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

Kodla ilgili önemli noktalar

Özel paneller ve düzenler oluşturma

XR için Compose tarafından desteklenmeyen özel paneller oluşturmak istiyorsanız SceneCore API'lerini kullanarak doğrudan PanelEntities ve sahne grafiğiyle çalışabilirsiniz.

Yörüngeleri mekansal düzenlere ve diğer öğelere sabitleme

Bir yörünge aracını, Oluştur'da tanımlanan herhangi bir öğeye sabitleyebilirsiniz. Bu, SpatialRow, SpatialColumn veya SpatialBox gibi kullanıcı arayüzü öğelerinin bulunduğu bir uzamsal düzende bir yörünge aracının tanımlanmasını içerir. Yörünge, belirttiğiniz yere en yakın üst öğeye sabitlenir.

Yörünge aracının davranışı, onu nerede beyan ettiğinize göre belirlenir:

  • SpatialPanel içine sarmalanmış 2D bir düzende (önceki kod snippet'inde gösterildiği gibi), yörünge aracı bu SpatialPanel'e sabitlenir.
  • Subspace içinde, yörünge aracı en yakın üst öğeye sabitlenir. Bu öğe, yörünge aracının tanımlandığı uzamsal düzendir.

Aşağıdaki örnekte, bir yörünge aracının bir uzamsal satıra nasıl sabitleneceği gösterilmektedir:

Subspace {
    SpatialRow {
        Orbiter(
            position = OrbiterEdge.Top,
            offset = EdgeOffset.inner(8.dp),
            shape = SpatialRoundedCornerShape(size = CornerSize(50))
        ) {
            Text(
                "Hello World!",
                style = MaterialTheme.typography.titleLarge,
                modifier = Modifier
                    .background(Color.White)
                    .padding(16.dp)
            )
        }
        SpatialPanel(
            SubspaceModifier
                .height(824.dp)
                .width(1400.dp)
        ) {
            Box(
                modifier = Modifier
                    .background(Color.Red)
            )
        }
        SpatialPanel(
            SubspaceModifier
                .height(824.dp)
                .width(1400.dp)
        ) {
            Box(
                modifier = Modifier
                    .background(Color.Blue)
            )
        }
    }
}

Kodla ilgili önemli noktalar

  • 2D düzenin dışında bir yörüngeci tanımladığınızda yörüngeci, en yakın üst öğesine sabitlenir. Bu durumda, yörünge aracı, tanımlandığı SpatialRow öğesinin üst kısmına sabitlenir.
  • SpatialRow, SpatialColumn, SpatialBox gibi tüm mekansal düzenlerin kendileriyle ilişkili içeriksiz varlıkları vardır. Bu nedenle, bir uzamsal düzende tanımlanan yörünge aracı, söz konusu düzene sabitlenir.

Ayrıca bkz.