باستخدام Jetpack Compose لتطبيقات الواقع المعزّز، يمكنك إنشاء واجهة المستخدم المكانية و التنسيق بشكل تعريفي باستخدام مفاهيم Compose المألوفة، مثل الصفوف والأعمدة. يتيح لك ذلك توسيع واجهة مستخدم Android الحالية إلى مساحة ثلاثية الأبعاد أو إنشاء تطبيقات ثلاثية الأبعاد immersive جديدة تمامًا.
إذا كنت بصدد إضافة ميزة العرض المكاني إلى تطبيق حالي يستند إلى Android Views، تتوفّر لك عدة خيارات تطوير. يمكنك استخدام واجهات برمجة التطبيقات للتشغيل التفاعلي أو استخدام Compose وViews معًا أو العمل مباشرةً مع مكتبة SceneCore. يمكنك الاطّلاع على دليل العمل مع المشاهدات للحصول على مزيد من التفاصيل.
لمحة عن المساحات الفرعية والمكونات المخصّصة للعرض في مساحات ثلاثية الأبعاد
عند كتابة تطبيقك لنظام Android XR، من المهم فهم مفاهيم المساحات الفرعية والمكوّنات المكانية.
لمحة عن المساحة الفرعية
عند تطوير تطبيقات لنظام Android XR، ستحتاج إلى إضافة مساحة فرعية إلى تطبيقك أو تنسيقه. المساحة الفرعية هي قسم من المساحة الثلاثية الأبعاد داخل تطبيقك يمكنك فيه وضع محتوى ثلاثي الأبعاد وإنشاء تصاميم ثلاثية الأبعاد وإضافة عمق إلى المحتوى ثنائي الأبعاد. لا يتم عرض المساحات الفرعية إلا عند تفعيل ميزة "الصوت المكاني". في "المساحة الرئيسية" أو على الأجهزة غير المزوّدة بتقنية الواقع المعزّز، يتم تجاهل أي رمز ضمن هذه المساحة الفرعية.
تتوفّر طريقتان لإنشاء مساحة فرعية:
setSubspaceContent
: تنشئ هذه الدالة مساحة فرعية على مستوى التطبيق. يمكن استدعاء هذا الإجراء في MainActivity بالطريقة نفسها التي تستخدم بهاsetContent
. إنّ المساحة الفرعية على مستوى التطبيق غير محدودة من حيث الارتفاع والعرض والعمق، ما يوفر في الأساس لوحة فنية غير محدودة للمحتوى المكاني.Subspace
: يمكن وضع هذا المكوّن القابل للتجميع في أي مكان ضمن التسلسل الهرمي لواجهة المستخدم في تطبيقك، ما يتيح لك الاحتفاظ بتنسيقات لواجهة المستخدم ثنائية الأبعاد وواجهة المستخدم المكانية بدون فقدان السياق بين الملفات. يسهّل ذلك مشاركة عناصر مثل بنية التطبيق الحالية بين الواقع المعزّز وأشكال الأجهزة الأخرى بدون الحاجة إلى رفع الحالة من خلال شجرة واجهة المستخدم بالكامل أو إعادة هندسة تطبيقك.
لمزيد من المعلومات، اطّلِع على مقالة إضافة مساحة فرعية إلى تطبيقك.
لمحة عن المكونات المكانية
العناصر القابلة للتجميع في مساحة فرعية: لا يمكن عرض هذه العناصر إلا في مساحة فرعية.
يجب وضعها بين Subspace
أو setSubspaceContent
قبل
وضعها في تنسيق ثنائي الأبعاد. يتيح لك SubspaceModifier
إضافة
سمات مثل العمق والإزاحة والموضع إلى العناصر القابلة للتجميع في مساحة فرعية.
- ملاحظة حول عوامل تعديل المساحة الفرعية: انتبه جيدًا لترتيب
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
)
}
}
النقاط الرئيسية حول الرمز
- ملاحظة حول عوامل تعديل المساحة الفرعية: انتبه جيدًا لترتيب واجهات برمجة التطبيقات
SubspaceModifier
.- يجب أن يظهر البادئة أولاً في سلسلة المُعدِّلات.
- يجب أن تظهر المُعدِّلات القابلة للنقل وتغيير الحجم في آخر السلسلة.
- يجب تطبيق التدوير قبل التكبير/التصغير.
- بما أنّ واجهات برمجة تطبيقات
SpatialPanel
هي عناصر قابلة للتجميع في مساحة فرعية، يجب طلبها داخلSubspace
أوsetSubspaceContent
. سيؤدي استدعاؤها خارج مساحة فرعية إلى طرح استثناء. - اسمح للمستخدم بتغيير حجم اللوحة أو نقلها من خلال إضافة
.movable
أو.resizable
SubspaceModifier
. - اطّلِع على إرشادات تصميم اللوحة المكانية للحصول على تفاصيل عن الحجم والموضع. يمكنك الاطّلاع على المستندات المرجعية للحصول على مزيد من التفاصيل حول تنفيذ الرمز.
إنشاء مدار
المسار هو مكوّن لواجهة مستخدِم مكانية. تم تصميمه ليتم إرفاقه بوحة مكانية مقابلة، ويحتوي على عناصر تنقّل وإجراءات مستندة إلى السياق مرتبطة بهذه اللوحة المكانية. على سبيل المثال، إذا أنشأت لوحة مكانية لعرض محتوى فيديو، يمكنك إضافة عناصر التحكّم في تشغيل الفيديو داخل مسار مداري.
كما هو موضّح في المثال التالي، يمكنك استدعاء عنصر 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
)
}
}
}
}
النقاط الرئيسية حول الرمز
- ملاحظة حول مُعدِّلات المساحات الفرعية: انتبِه جيدًا لترتيب واجهات برمجة تطبيقات
SubspaceModifier
.- يجب أن يظهر المُعَوِّض أولاً في سلسلة المُعدِّلات.
- يجب أن تكون العناصر القابلة للنقل وتغيير الحجم هي الأخيرة.
- يجب تطبيق التدوير قبل التكبير/التصغير.
- بما أنّ العناصر الدوّارة هي مكونات لواجهة المستخدم المكانية، يمكن إعادة استخدام الرمز البرمجي في تنسيقات ثنائية أو ثلاثية الأبعاد. في التنسيق ثنائي الأبعاد، يعرض تطبيقك المحتوى داخل الإطار فقط ويغضّ الطرف عن الإطار نفسه.
- اطّلِع على إرشادات التصميم للحصول على مزيد من المعلومات عن كيفية استخدام المدارات وتصميمها.
إضافة عدة لوحات مكانية إلى تنسيق مكاني
يمكنك إنشاء عدة لوحات مكانية ووضعها ضمن
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
}
}
}
}
}
النقاط الرئيسية حول الرمز
- ملاحظة حول مُعدِّلات المساحات الفرعية: انتبِه جيدًا لترتيب واجهات برمجة تطبيقات
SubspaceModifier
.- يجب أن يظهر المُعَوِّض أولاً في سلسلة المُعدِّلات.
- يجب أن تكون العناصر القابلة للنقل وتغيير الحجم هي الأخيرة.
- يجب تطبيق التدوير قبل التكبير/التصغير.
- اطّلِع على مقالة إضافة محتوى ثلاثي الأبعاد للتعرّف بشكل أفضل على كيفية تحميل محتوى ثلاثي الأبعاد في مجلّد.
إضافة مكونات أخرى لواجهة المستخدم المكانية
يمكن وضع مكوّنات واجهة المستخدم المكانية في أيّ مكان في التسلسل الهرمي لواجهة المستخدم في تطبيقك. يمكن إعادة استخدام هذه العناصر في واجهة المستخدم ثنائية الأبعاد، ولن تكون سماتها المكانية مرئية إلا عند تفعيل الإمكانات المكانية. يتيح لك ذلك إضافة تأثير التمويه إلى القوائم وملفات الحوار والمكونات الأخرى بدون الحاجة إلى كتابة الرمز البرمجي مرتين. اطّلِع على الأمثلة التالية على واجهة المستخدم المكانية لفهم كيفية استخدام هذه العناصر بشكل أفضل.
مكوّن واجهة المستخدم |
عند تفعيل ميزة "الصوت المكاني" |
في بيئة ثنائية الأبعاد |
---|---|---|
|
سيتم دفع اللوحة للخلف قليلاً في العمق z لعرض مربّع حوار مرتفع |
الرجوع إلى العرض الثنائي الأبعاد |
|
سيتم دفع اللوحة للخلف قليلاً في العمق (z) لعرض نافذة منبثقة مرتفعة. |
يعود إلى |
|
يمكن ضبط |
عروض بدون ارتفاع مكاني |
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
سيكون متشابهًا جدًا. اطّلِع على مرجع واجهة برمجة التطبيقات للحصول على مزيد من التفاصيل.
إنشاء لوحات وتنسيقات مخصّصة
لإنشاء لوحات مخصّصة غير متوافقة مع Compose for XR، يمكنك العمل
مباشرةً مع PanelEntities
ورسم المشهد باستخدام واجهات برمجة التطبيقات
SceneCore
.
انظر أيضًا
- إضافة نماذج ثلاثية الأبعاد
- تطوير واجهة مستخدم لتجربة الواقع المعزّز باستخدام طرق العرض
- Material Design للواقع المعزّز