XR için Jetpack Compose ile, satırlar ve sütunlar gibi tanıdık Compose kavramlarını kullanarak uzamsal kullanıcı arayüzünüzü ve düzeninizi bildirimsel olarak oluşturabilirsiniz. Bu sayede, mevcut Android kullanıcı arayüzünüzü 3D alana genişletebilir veya tamamen yeni, etkileyici 3D uygulamalar oluşturabilirsiniz.
Mevcut bir Android Views tabanlı uygulamayı uzamsallaştırıyorsanız çeşitli geliştirme seçenekleriniz vardır. Birlikte çalışabilirlik API'lerini kullanabilir, Compose ve Views'u birlikte kullanabilir veya doğrudan SceneCore kitaplığıyla çalışabilirsiniz. Daha fazla bilgi için görünümlerle çalışma kılavuzumuzu inceleyin.
Alt alanlar ve uzamsallaştırılmış bileşenler hakkında
Android XR için uygulamanızı yazarken alt uzay ve uzamsallaştırılmış bileşenler kavramlarını anlamanız önemlidir.
Alt alan hakkında
Android XR için geliştirme yaparken uygulamanıza veya düzene Subspace
eklemeniz gerekir. Alt alan, uygulamanızdaki 3D alanın bir bölümüdür. Bu bölümde 3D içerik yerleştirebilir, 3D düzenler oluşturabilir ve aksi takdirde 2D olacak içeriklere derinlik katabilirsiniz. Bir alt alan yalnızca uzamsallaştırma etkinleştirildiğinde oluşturulur. Evrensel Alan'da veya XR olmayan cihazlarda, bu alt uzaydaki tüm kodlar yoksayılır.
Alt alan oluşturmanın iki yolu vardır:
Subspace
: Bu composable, uygulamanızın kullanıcı arayüzü hiyerarşisinde herhangi bir yere yerleştirilebilir. Böylece, dosyalar arasındaki bağlamı kaybetmeden 2D ve uzamsal kullanıcı arayüzü düzenlerini koruyabilirsiniz. Bu sayede, durumunuzu tüm kullanıcı arayüzü ağınızda yükseltmenize veya uygulamanızın mimarisini yeniden tasarlamanıza gerek kalmadan, XR ile diğer form faktörleri arasında mevcut uygulama mimarisi gibi öğeleri paylaşmak kolaylaşır.ApplicationSubspace
: Bu işlev yalnızca uygulama düzeyinde alt alan oluşturur ve uygulamanızın uzamsal kullanıcı arayüzü hiyerarşisinde en üst düzeye yerleştirilmelidir.ApplicationSubspace
, isteğe bağlıVolumeConstraints
ile uzamsal içerik oluşturur.Subspace
'ın aksine,ApplicationSubspace
başka birSubspace
veyaApplicationSubspace
içine yerleştirilemez.
Daha fazla bilgi için Uygulamanıza alt alan ekleme başlıklı makaleyi inceleyin.
Uzamsallaştırılmış bileşenler hakkında
Alt alan composable'ları: Bu bileşenler yalnızca bir alt alanda oluşturulabilir.
2D düzene yerleştirilmeden önce Subspace
veya setSubspaceContent()
içine alınmaları gerekir. SubspaceModifier
, alt alan composable'larınıza derinlik, dengeleme ve konumlandırma gibi özellikler eklemenize olanak tanır.
Diğer uzamsallaştırılmış bileşenlerin bir alt uzay içinde çağrılması gerekmez. Bunlar, uzamsal bir 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. Uzamsallaştırma etkinleştirilmediğinde, uzamsallaştırılmış özellikleri yoksayılır ve 2D karşılıklarına geri dönerler.
Uzamsal panel oluşturma
SpatialPanel
, uygulama içeriğini görüntülemenize olanak tanıyan, birleştirilebilir bir alt alan bileşenidir. Örneğin, video oynatma, sabit resimler veya başka herhangi bir içeriği bir uzamsal panelde görüntüleyebilirsiniz.
Aşağıdaki örnekte gösterildiği gibi, SubspaceModifier
kullanarak uzamsal panelin boyutunu, davranışını ve konumunu değiştirebilirsiniz.
Subspace { SpatialPanel( SubspaceModifier .height(824.dp) .width(1400.dp) .movable() .resizable() ) { SpatialPanelContent() } }
@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
SpatialPanel
API'leri alt alan composable'ları olduğundan bunlarıSubspace
içinde çağırmanız gerekir. Alt alan dışında çağrıldıklarında istisna oluştururlar.SpatialPanel
boyutları,SubspaceModifier
üzerindekiheight
vewidth
özellikleri kullanılarak ayarlanmıştır. Bu spesifikasyonların atlanması, panelin boyutunun içeriğinin ölçüleriyle belirlenmesine olanak tanır.movable
veyaresizable
değiştiricilerini ekleyerek kullanıcının paneli yeniden boyutlandırmasına veya taşımasına izin verin.- Boyutlandırma ve konumlandırma ile ilgili ayrıntılar için uzamsal panel tasarım yönergelerimizi inceleyin. Kod uygulamasıyla ilgili daha fazla bilgi için referans dokümanlarımızı inceleyin.
Taşınabilir alt alan değiştiricinin işleyiş şekli
Bir kullanıcı paneli kendisinden uzaklaştırdığında, varsayılan olarak taşınabilir bir alt alan değiştirici, paneli ana alanda sistem tarafından yeniden boyutlandırılan panellere benzer şekilde ölçeklendirir. Tüm çocuk içerikleri bu davranışı devralır. Bu özelliği devre dışı bırakmak için scaleWithDistance
parametresini false
olarak ayarlayın.
Yörünge aracı oluşturma
Orbiter, uzamsal bir kullanıcı arayüzü bileşenidir. İlgili bir mekansal panele, düzene veya başka bir öğeye eklenmek üzere tasarlanmıştır. Bir yörünge öğesi genellikle bağlı olduğu öğeyle ilgili gezinme ve bağlamsal işlem öğeleri içerir. Örneğin, video içeriğini göstermek için bir uzamsal panel oluşturduysanız bir orbiter'ın içine video oynatma kontrolleri ekleyebilirsiniz.
Aşağıdaki örnekte gösterildiği gibi, gezinme gibi kullanıcı kontrollerini sarmak için 2D düzendeki bir orbiter'ı SpatialPanel
içinde çağırın. Bu işlem, öğeleri 2D düzeninizden çıkarır ve yapılandırmanıza göre uzamsal panele ekler.
Subspace { SpatialPanel( SubspaceModifier .height(824.dp) .width(1400.dp) .movable() .resizable() ) { SpatialPanelContent() OrbiterExample() } }
@Composable fun OrbiterExample() { Orbiter( position = ContentEdge.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üngeler, uzamsal kullanıcı arayüzü bileşenleri olduğundan kod, 2D veya 3D düzenlerde yeniden kullanılabilir. 2D düzende uygulamanız yalnızca orbiter'ın içindeki içeriği oluşturur ve orbiter'ı yoksayar.
- Yörüngeleri kullanma ve tasarlama hakkında daha fazla bilgi için tasarım rehberimize göz atın.
Uzamsal düzene birden fazla uzamsal panel ekleme
SpatialRow
, SpatialColumn
, SpatialBox
ve SpatialLayoutSpacer
kullanarak birden fazla mekansal panel oluşturabilir ve bunları mekansal bir düzende yerleştirebilirsiniz.
Aşağıdaki kod örneğinde bu işlemin 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
SpatialRow
,SpatialColumn
,SpatialBox
veSpatialLayoutSpacer
, alt alan composable'larıdır ve bir alt alan içinde yerleştirilmelidir.- Düzeninizi özelleştirmek için
SubspaceModifier
simgesini kullanın. - Arka arkaya birden fazla panel içeren düzenlerde, panellerin kullanıcınızı sarmalaması için
SubspaceModifier
kullanarak 825 dp eğrilik yarıçapı ayarlamanızı öneririz. Ayrıntılar için tasarım yönergelerimize bakın.
Düzeninize 3D nesne yerleştirmek için hacim kullanma
Düzeninize 3D nesne yerleştirmek için hacim adı verilen bir alt alan composable'ı kullanmanız gerekir. Bunu nasıl yapabileceğinize dair bir örneği aşağıda bulabilirsiniz.
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, ) } } }
@OptIn(ExperimentalSubspaceVolumeApi::class) @Composable fun ObjectInAVolume(show3DObject: Boolean) {
Ek bilgiler
- Bir hacimdeki 3D içeriği nasıl yükleyeceğinizi daha iyi anlamak için Uygulamanıza 3D modeller ekleme başlıklı makaleyi inceleyin.
Resim veya video içeriği için yüzey ekleme
SpatialExternalSurface
, uygulamanızın resim veya video gibi içerik çizebileceği Surface
öğesini oluşturan ve yöneten, birleştirilebilir bir alt uzaydır. SpatialExternalSurface
, stereoskopik veya monoskopik içeriği destekler.
Bu örnekte, Media3 Exoplayer ve SpatialExternalSurface
kullanılarak yan yana stereo video yükleme işlemi gösterilmektedir:
@OptIn(ExperimentalComposeApi::class) @Composable fun SpatialExternalSurfaceContent() { val context = LocalContext.current Subspace { SpatialExternalSurface( modifier = SubspaceModifier .width(1200.dp) // Default width is 400.dp if no width modifier is specified .height(676.dp), // Default height is 400.dp if no height modifier is specified // Use StereoMode.Mono, StereoMode.SideBySide, or StereoMode.TopBottom, depending // upon which type of content you are rendering: monoscopic content, side-by-side stereo // content, or top-bottom stereo content stereoMode = StereoMode.SideBySide, ) { val exoPlayer = remember { ExoPlayer.Builder(context).build() } val videoUri = Uri.Builder() .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) // Represents a side-by-side stereo video, where each frame contains a pair of // video frames arranged side-by-side. The frame on the left represents the left // eye view, and the frame on the right represents the right eye view. .path("sbs_video.mp4") .build() val mediaItem = MediaItem.fromUri(videoUri) // onSurfaceCreated is invoked only one time, when the Surface is created onSurfaceCreated { surface -> exoPlayer.setVideoSurface(surface) exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() exoPlayer.play() } // onSurfaceDestroyed is invoked when the SpatialExternalSurface composable and its // associated Surface are destroyed onSurfaceDestroyed { exoPlayer.release() } } } }
Kodla ilgili önemli noktalar
- Hangi tür içeriği oluşturduğunuza bağlı olarak
StereoMode
değeriniMono
,SideBySide
veyaTopBottom
olarak ayarlayın:Mono
: Resim veya video karesi, her iki göze de gösterilen tek ve aynı resimden oluşur.SideBySide
: Resim veya video karesi, yan yana düzenlenmiş bir çift resim ya da video karesi içerir. Soldaki resim veya kare, sol göz görünümünü; sağdaki resim veya kare ise sağ göz görünümünü temsil eder.TopBottom
: Resim veya video karesi, dikey olarak üst üste yerleştirilmiş bir çift resim ya da video karesi içerir. Üstteki resim veya kare sol göz görünümünü, alttaki resim veya kare ise sağ göz görünümünü temsil eder.
SpatialExternalSurface
yalnızca dikdörtgen yüzeyleri destekler.- Bu
Surface
, giriş etkinliklerini yakalamaz. StereoMode
değişikliklerini uygulama oluşturma veya video kod çözme ile senkronize etmek mümkün değildir.- Bu composable, diğer panellerin önünde oluşturulamaz. Bu nedenle, düzende başka paneller varsa taşınabilir değiştiriciler kullanmamalısınız.
DRM korumalı video içeriği için yüzey ekleme
SpatialExternalSurface
, DRM ile korunan video akışlarının oynatılmasını da destekler. Bunu etkinleştirmek için korumalı grafik arabelleklerine işlenen güvenli bir yüzey oluşturmanız gerekir. Bu, içeriğin ekran kaydının alınmasını veya güvenli olmayan sistem bileşenleri tarafından erişilmesini engeller.
Güvenli bir yüzey oluşturmak için SpatialExternalSurface
composable'da surfaceProtection
parametresini SurfaceProtection.Protected
olarak ayarlayın.
Ayrıca, lisans sunucusundan lisans alımını işlemek için Media3 Exoplayer'ı uygun DRM bilgileriyle yapılandırmanız gerekir.
Aşağıdaki örnekte, DRM ile korunan bir video akışını oynatmak için SpatialExternalSurface
ve ExoPlayer
öğelerinin nasıl yapılandırılacağı gösterilmektedir:
@OptIn(ExperimentalComposeApi::class) @Composable fun DrmSpatialVideoPlayer() { val context = LocalContext.current Subspace { SpatialExternalSurface( modifier = SubspaceModifier .width(1200.dp) .height(676.dp), stereoMode = StereoMode.SideBySide, surfaceProtection = SurfaceProtection.Protected ) { val exoPlayer = remember { ExoPlayer.Builder(context).build() } // Define the URI for your DRM-protected content and license server. val videoUri = "https://your-content-provider.com/video.mpd" val drmLicenseUrl = "https://your-license-server.com/license" // Build a MediaItem with the necessary DRM configuration. val mediaItem = MediaItem.Builder() .setUri(videoUri) .setDrmConfiguration( MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID) .setLicenseUri(drmLicenseUrl) .build() ) .build() onSurfaceCreated { surface -> // The created surface is secure and can be used by the player. exoPlayer.setVideoSurface(surface) exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() exoPlayer.play() } onSurfaceDestroyed { exoPlayer.release() } } } }
Kodla ilgili önemli noktalar
- Korumalı Yüzey:
surfaceProtection = SurfaceProtection.Protected
SpatialExternalSurface
ayarınınSpatialExternalSurface
olarak belirlenmesi, temel alınanSurface
öğesinin DRM içeriğine uygun güvenli arabelleklerle desteklenmesi için gereklidir. - DRM Yapılandırması:
MediaItem
öğesini DRM şeması (örneğin,C.WIDEVINE_UUID
) ve lisans sunucunuzun URI'si ile yapılandırmanız gerekir. ExoPlayer, DRM oturumunu yönetmek için bu bilgileri kullanır. - Güvenli İçerik: Korunan bir yüzeyde oluşturma işlemi yapılırken video içeriği, içerik lisanslama koşullarını karşılamaya yardımcı olan güvenli bir yolda kod çözülerek görüntülenir. Bu, içeriğin ekran görüntülerinde görünmesini de engeller.
Diğer uzamsal kullanıcı arayüzü bileşenlerini ekleme
Uzamsal kullanıcı arayüzü bileşenleri, uygulamanızın kullanıcı arayüzü hiyerarşisinde herhangi bir yere yerleştirilebilir. Bu öğeler 2D kullanıcı arayüzünüzde yeniden kullanılabilir ve mekansal özellikleri yalnızca mekansal özellikler etkinleştirildiğinde görünür. Bu sayede, kodunuzu iki kez yazmanıza gerek 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 uzamsal kullanıcı arayüzü örneklerine göz atın.
Kullanıcı arayüzü bileşeni |
Uzamsallaştırma etkinleştirildiğinde |
2D ortamda |
---|---|---|
|
Panel, yükseltilmiş bir iletişim kutusu göstermek için z derinliğinde biraz geriye itilir. |
2D'ye geri döner |
|
Panel, yükseltilmiş bir pop-up göstermek için z derinliğinde biraz geriye itilir. |
2 boyutlu |
|
|
Mekansal yükseklik içermeyen gösterimler. |
SpatialDialog
Bu, kısa bir gecikmenin ardından açılan iletişim kutusuna bir örnektir. SpatialDialog
kullanıldığında iletişim kutusu, uzamsal panel ile 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) { delay(3000) showDialog = true } 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
- Bu,
SpatialDialog
örneğidir.SpatialPopup
veSpatialElevation
kullanımı çok benzerdir. Daha fazla bilgi için API referansımıza bakın.
Özel paneller ve düzenler oluşturma
XR için Compose tarafından desteklenmeyen özel paneller oluşturmak üzere PanelEntity
örnekleriyle ve sahne grafiğiyle doğrudan SceneCore
API'lerini kullanarak çalışabilirsiniz.
Yörünge uydularını uzamsal düzenlere ve diğer öğelere sabitleme
Bir yörüngeyi Compose'da belirtilen herhangi bir öğeye sabitleyebilirsiniz. Bu, SpatialRow
, SpatialColumn
veya SpatialBox
gibi kullanıcı arayüzü öğelerinin uzamsal düzeninde bir yörünge öğesi bildirmeyi içerir. Yörünge aracı, üst öğeyi, beyan ettiğiniz yere en yakın olacak şekilde sabitler.
Yörünge aracının davranışı, onu nerede bildirdiğinize göre belirlenir:
SpatialPanel
ile sarmalanmış bir 2D düzende (önceki kod snippet'inde gösterildiği gibi) yörünge aracı, buSpatialPanel
öğesine sabitlenir.Subspace
içinde, yörünge aracı en yakın üst öğeye bağlanır. Bu öğe, yörünge aracının bildirildiği uzamsal düzendir.
Aşağıdaki örnekte, bir uyduyu uzamsal bir satıra nasıl sabitleyeceğiniz gösterilmektedir:
Subspace { SpatialRow { Orbiter( position = ContentEdge.Top, offset = 8.dp, offsetType = OrbiterOffsetType.InnerEdge, shape = SpatialRoundedCornerShape(size = CornerSize(50)) ) { Text( "Hello World!", style = MaterialTheme.typography.titleMedium, 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
- Bir yörüngeyi 2D düzenin dışında bildirdiğinizde yörünge, en yakın üst öğe varlığına sabitlenir. Bu durumda, yörünge aracı, bildirildiği
SpatialRow
öğesinin üst kısmına sabitlenir. SpatialRow
,SpatialColumn
,SpatialBox
gibi uzamsal düzenlerin tümü, kendileriyle ilişkili içeriksiz öğeler içerir. Bu nedenle, uzamsal düzende belirtilen bir yörünge aracı bu düzene sabitlenir.
Ayrıca bkz.
- Uygulamanıza 3D modeller ekleme
- Android Views tabanlı uygulamalar için kullanıcı arayüzü geliştirme
- XR için Materyal Tasarım'ı uygulama