באמצעות Jetpack Compose for XR, אפשר ליצור באופן דקלרטיבי את ממשק המשתמש המרחבי ואת הפריסה שלו באמצעות מושגים מוכרים של Compose, כמו שורות ועמודות. כך תוכלו להרחיב את ממשק המשתמש הקיים של Android למרחב תלת-ממדי או ליצור אפליקציות תלת-ממדיות חדשות לגמרי.
אם אתם מפתחים אפליקציה קיימת מבוססת-תצוגות של Android, יש לכם כמה אפשרויות פיתוח. אפשר להשתמש בממשקי API לתאימות הדדית, להשתמש ב-Compose וב-Views יחד או לעבוד ישירות עם ספריית SceneCore. מידע נוסף זמין במדריך לעבודה עם תצוגות.
מידע על מרחבים משניים ורכיבים במרחב
כשכותבים אפליקציה ל-Android XR, חשוב להבין את המושגים מרחב משנה ורכיבים מרחבי.
מידע על תת-מרחב
כשמפתחים לאנדרואיד XR, צריך להוסיף מרחב משנה לאפליקציה או לפריסה. מרחב משנה הוא מחיצה של מרחב תלת-ממדי באפליקציה, שבה אפשר למקם תוכן תלת-ממדי, ליצור פריסות תלת-ממדיות ולהוסיף עומק לתוכן דו-ממדי. המערכת תיצור מרחב משנה רק כשהמיקום הפיזי של המשתתפים יופעל. במרחב הבית או במכשירים שאינם XR, המערכת מתעלמת מכל קוד במרחב המשנה הזה.
יש שתי דרכים ליצור מרחב משנה:
setSubspaceContent
: הפונקציה הזו יוצרת מרחבים משניים ברמת האפליקציה. אפשר להפעיל את הפונקציה הזו ב-MainActivity באותו אופן שבו משתמשים ב-setContent
. המרחב המשנה ברמת האפליקציה לא מוגבל בגובה, ברוחב ובעומק, וכך הוא מספק למעשה קנבס אינסופי לתוכן מרחבי.Subspace
: אפשר למקם את הרכיב הזה בכל מקום בהיררכיית ממשק המשתמש של האפליקציה, וכך לשמור על פריסות לממשק משתמש דו-ממדי ומרחבי בלי לאבד את ההקשר בין הקבצים. כך קל יותר לשתף דברים כמו ארכיטקטורת אפליקציה קיימת בין XR לבין גורמי צורה אחרים, בלי שתצטרכו להעביר את המצב דרך כל עץ ממשק המשתמש או לתכנן מחדש את הארכיטקטורה של האפליקציה.
מידע נוסף זמין במאמר הוספת מרחב משנה לאפליקציה.
מידע על רכיבים במרחב
רכיבים שניתנים ליצירה במרחב משנה: אפשר להציג את הרכיבים האלה רק במרחב משנה.
צריך להוסיף את התגים האלה בתוך Subspace
או setSubspaceContent
לפני שממקמים אותם בפריסה דו-ממדית. SubspaceModifier
מאפשר להוסיף מאפיינים כמו עומק, סטייה ומיקום לרכיבים הניתנים לקישור במרחב המשנה.
- הערה לגבי מודификаторים של מרחבים משניים: חשוב לשים לב לסדר של ממשקי ה-API של
SubspaceModifier
.- שינוי המיקום חייב להופיע קודם בשרשרת המשתנים
- האפשרות להזיז את התמונה ולשנות את הגודל שלה חייבת להופיע בסוף
- צריך להחיל את הסיבוב לפני השינוי של קנה המידה
רכיבים אחרים במרחב תלת-ממדי לא צריכים להיקרא בתוך מרחבים משניים. הם מורכבים מרכיבים דו-ממדיים רגילים שמקובצים בתוך מאגר מרחבי. אפשר להשתמש ברכיבים האלה בפריסות דו-ממדיות או תלת-ממדיות, אם הם מוגדרים בשתיהן. אם התכונה 'מיקום במרחב' לא מופעלת, המערכת תתעלם מהתכונות הממוקמות במרחב שלהם והן יחזרו לגרסאות הדו-ממדיות שלהן.
יצירת לוח מרחבי
SpatialPanel
הוא מרחבים משניים שניתנים ליצירה, שמאפשרים להציג תוכן של אפליקציות. לדוגמה, אפשר להציג הפעלת וידאו, תמונות סטילס או כל תוכן אחר בחלונית מרחבית.
אפשר להשתמש ב-SubspaceModifier
כדי לשנות את הגודל, ההתנהגות והמיקום של הלוח המרחבי, כפי שמתואר בדוגמה הבאה.
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
)
}
}
נקודות עיקריות לגבי הקוד
- הערה לגבי מודификаторים של מרחבים משניים: חשוב לשים לב לסדר של ממשקי ה-API של
SubspaceModifier
.- ההיסט חייב להופיע קודם בשרשרת המשתנים המשתנים.
- משתני אופן (modifiers) שניתן להזיז ולשנות את הגודל שלהם חייבים להופיע בסוף.
- צריך להחיל את הסיבוב לפני השינוי של הגודל.
- מאחר שממשקי ה-API של
SpatialPanel
הם רכיבים שניתנים ליצירה במרחב משנה, צריך לבצע קריאה אליהם בתוךSubspace
אוsetSubspaceContent
. קריאה אליהן מחוץ למרחב משנה תגרום להשלכת חריגה. - מאפשרים למשתמש לשנות את הגודל או להזיז את החלונית על ידי הוספת
SubspaceModifier
של.movable
או.resizable
. - הנחיות לעיצוב של חלוניות מרחבי – מידע על הגודל והמיקום. מידע ספציפי יותר על הטמעת קוד זמין במאמרי העזרה שלנו.
יצירת כלי ניווט במסלול
רכיב מסלול הוא רכיב של ממשק משתמש מרחבי. הוא מיועד להתחבר לחלונית מרחבית תואמת, ומכיל פריטים של ניווט ופעולות לפי הקשר שקשורים לחלונית המרחבית הזו. לדוגמה, אם יצרתם חלונית מרחבית כדי להציג תוכן וידאו, תוכלו להוסיף אמצעי בקרה להפעלת וידאו בתוך כלי ניווט.
כפי שמוצג בדוגמה הבאה, צריך להפעיל את ה-orbiter בתוך SpatialPanel
כדי לעטוף את אמצעי הבקרה של המשתמש, כמו ניווט. הפעולה הזו מחלצת אותם מהפריסה הדו-ממדית ומצרפת אותם לחלונית המרחבית בהתאם להגדרה שלכם.
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
)
}
}
}
}
נקודות עיקריות לגבי הקוד
- הערה לגבי מודификаторים של מרחבים משניים: חשוב לשים לב לסדר של ממשקי ה-API של
SubspaceModifier
.- שינוי המיקום חייב להופיע קודם בשרשרת המשתנים
- האפשרות להזיז את התמונה ולשנות את הגודל שלה חייבת להופיע בסוף
- צריך להחיל את הסיבוב לפני השינוי של קנה המידה
- מאחר שרכיבי Orbiter הם רכיבים מרחביים של ממשק המשתמש, אפשר לעשות שימוש חוזר בקוד בפריסות 2D או 3D. בפריסה דו-ממדית, האפליקציה תיצור רק את התוכן בתוך ה-Orbiter ותתעלם מה-Orbiter עצמו.
- הנחיות לעיצוב – מידע נוסף על שימוש ב-Orbiters ועל עיצוב שלהם.
הוספת כמה פאנלים מרחביים לפריסה מרחבית
אפשר ליצור כמה לוחות מרחבי ולהציב אותם בתוך SpatialLayout
באמצעות SpatialRow
, SpatialColumn
, SpatialBox
ו-SpatialLayoutSpacer
.
בדוגמת הקוד הבאה מוסבר איך עושים את זה.
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
)
}
}
נקודות עיקריות לגבי הקוד
SpatialRow
, SpatialColumn
, SpatialBox
ו-SpatialLayoutSpacer
הם רכיבים שאפשר לשלב במרחב משנה, וצריך למקם אותם במרחב משנה.- משתמשים ב-
SubspaceModifier
כדי להתאים אישית את הפריסה. - בפריסות עם כמה פאנלים בשורה, מומלץ להגדיר רדיוס עקומה של 825dp באמצעות
SubspaceModifier
כדי שהפאנלים יקיפו את המשתמש. פרטים נוספים זמינים בהנחיות העיצוב שלנו.
שימוש בנפח כדי למקם אובייקט תלת-ממדי בפריסה
כדי להציב אובייקט תלת-ממדי בפריסה, צריך להשתמש במרחב משנה שאפשר ליצור ממנו אובייקטים שנקרא נפח אחסון. דוגמה לכך מופיעה בהמשך.
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
}
}
}
}
}
נקודות עיקריות לגבי הקוד
- הערה לגבי מודификаторי מרחבים משניים: חשוב לשים לב לסדר של ממשקי ה-API של
SubspaceModifier
.- שינוי המיקום חייב להופיע קודם בשרשרת המשתנים
- האפשרות להזיז את התמונה ולשנות את הגודל שלה חייבת להופיע בסוף
- צריך להחיל את הסיבוב לפני השינוי של קנה המידה
- במאמר הוספת תוכן תלת-ממדי מוסבר איך טוענים תוכן תלת-ממדי בנפח אחסון.
הוספת רכיבים אחרים של ממשק משתמש מרחבי
אפשר למקם רכיבי ממשק משתמש מרחבי בכל מקום בהיררכיית ממשק המשתמש של האפליקציה. אפשר לעשות שימוש חוזר ברכיבים האלה בממשק המשתמש הדו-מימדי, והמאפיינים המרחביים שלהם יהיו גלויים רק כשהיכולות המרחביות מופעלות. כך תוכלו להוסיף הרשאות גישה לתפריטים, לתיבת דו-שיח ולרכיבים אחרים בלי לכתוב את הקוד פעמיים. כדאי לעיין בדוגמאות הבאות לממשק משתמש מרחבי כדי להבין טוב יותר איך משתמשים ברכיבים האלה.
רכיב UI |
כשהמיקום מופעל |
בסביבה דו-ממדית |
---|---|---|
|
החלונית תזוז מעט לאחור ב-z-depth כדי להציג תיבת דו-שיח מוגבהת |
מעבר לתצוגה דו-ממדית |
|
החלונית תזוז מעט לאחור ב-z-depth כדי להציג חלון קופץ מוגבה |
המערכת חוזרת לתצוגה דו-ממדית |
|
אפשר להגדיר את |
תוכניות ללא תצוגה מרחבית. |
SpatialDialog
זו דוגמה לתיבת דו-שיח שנפתחת לאחר עיכוב קצר. כשמשתמשים ב-SpatialDialog
, תיבת הדו-שיח מופיעה באותו עומק z כמו החלונית המרחבית, והחלונית מוסטת לאחור ב-125dp כשהמיקום המרחבי מופעל.
אפשר להשתמש ב-SpatialDialog
גם כשהמיקום במרחב לא מופעל, והוא יחזור לגרסה הדו-ממדית שלו: 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")
}
}
}
}
}
נקודות עיקריות לגבי הקוד
- זו דוגמה ל-
SpatialDialog
. השימוש ב-SpatialPopUp
וב-SpatialElevation
דומה מאוד. פרטים נוספים זמינים בהפניית ה-API.
יצירת לוחות ופלטפורמות בהתאמה אישית
כדי ליצור לוחות בהתאמה אישית שלא נתמכים ב-Compose for XR, אפשר לעבוד ישירות עם PanelEntities
ועם תרשים הסצינה באמצעות ממשקי ה-API של SceneCore
.