تحتاج إلى أنواع مختلفة من المعلومات، مثل إمكانات الجهاز وحالة التطبيق، لتعديل تصميم تطبيقك. عرض النافذة وارتفاعها هما المعلومات الأكثر شيوعًا. بالإضافة إلى ذلك، يمكنك الرجوع إلى المعلومات التالية:
- وضعية النافذة
- دقة أجهزة التأشير
- نوع لوحة المفاتيح
- ما إذا كان الجهاز يتيح استخدام الكاميرا والميكروفون
- المسافة بين المستخدم وشاشة الجهاز
بما أنّ المعلومات يتم تعديلها بشكل ديناميكي، عليك مراقبتها وتفعيل إعادة الإنشاء عند حدوث أي تعديل.
تجرّد الدالة mediaQuery تفاصيل استرجاع المعلومات
وتتيح لك التركيز على تحديد الشرط الذي يؤدي إلى تشغيل تعديلات التصميم.
يغيّر المثال التالي التنسيق إلى TabletopLayout
عندما يكون وضع الجهاز القابل للطي هو وضع سطح الطاولة:
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
تفعيل وظيفة mediaQuery
لتفعيل الدالة mediaQuery، اضبط السمة isMediaQueryIntegrationEnabled للعنصر ComposeUiFlags على true:
class MyApplication : Application() { override fun onCreate() { ComposeUiFlags.isMediaQueryIntegrationEnabled = true super.onCreate() } }
تحديد شرط باستخدام مَعلمات
يمكنك تحديد شرط كدالة lambda يتم تقييمها ضمن UiMediaScope.
تقيّم الدالة mediaQuery الشرط وفقًا للحالة الحالية وإمكانات الجهاز.
تعرض الدالة قيمة منطقية،
وبالتالي يمكنك تحديد التنسيق باستخدام فروع شرطية
مثل تعبير if.
يوضّح الجدول 1 المَعلمات المتوفّرة في UiMediaScope.
| المَعلمة | نوع القيمة | الوصف |
|---|---|---|
windowWidth |
Dp |
عرض النافذة الحالية بوحدات dp. |
windowHeight |
Dp |
ارتفاع النافذة الحالية بوحدات dp |
windowPosture |
UiMediaScope.Posture |
الوضع الحالي لنافذة التطبيق. |
pointerPrecision |
UiMediaScope.PointerPrecision |
تمثّل هذه السمة أعلى دقة لأجهزة التأشير المتاحة. |
keyboardKind |
UiMediaScope.KeyboardKind |
نوع لوحة المفاتيح المتاحة أو المتصلة |
hasCamera |
Boolean |
تحديد ما إذا كانت الكاميرا متوافقة مع الجهاز. |
hasMicrophone |
Boolean |
تُستخدَم لتحديد ما إذا كان الميكروفون متوافقًا مع الجهاز. |
viewingDistance |
UiMediaScope.ViewingDistance |
تمثّل هذه السمة المسافة المعتادة بين المستخدم وشاشة الجهاز. |
يحلّ كائن UiMediaScope قيم المَعلمات.
تستخدم الدالة mediaQuery LocalUiMediaScope.current
للوصول إلى العنصر UiMediaScope،
الذي يمثّل إمكانات الجهاز الحالي وسياقه.
يتم تعديل هذا العنصر ديناميكيًا عند إجراء أي تغييرات،
مثلما يحدث عندما يغيّر المستخدم وضع الجهاز.
بعد ذلك، تقدّر الدالة mediaQuery تعبير lambda query باستخدام الكائن UiMediaScope المعدَّل وتعرض قيمة منطقية.
على سبيل المثال، يختار المقتطف التالي بين TabletopLayout
وFlatLayout استنادًا إلى قيمة المَعلمة windowPosture.
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
اتّخاذ قرار استنادًا إلى حجم النافذة
فئات أحجام النوافذ هي مجموعة من نقاط توقّف إطارات العرض المحدّدة مسبقًا
التي تساعدك في تصميم وتطوير واختبار التصميمات المتكيّفة.
يمكنك مقارنة المَعلمتَين اللتين تمثّلان حجم النافذة الحالي بالحدّ الأدنى المحدّد في فئات حجم النافذة.
يغيّر المثال التالي عدد اللوحات وفقًا لعرض النافذة.
يحتوي الصف WindowSizeClass على ثوابت لحدود فئات أحجام النوافذ (الشكل 1).
تقيّم الدالة derivedMediaQuery تعبير lambda query
وتضمّن النتيجة في derivedStateOf.
بما أنّ الدالتَين windowWidth وwindowHeight يمكن تعديلهما بشكل متكرّر،
استخدِم الدالة derivedMediaQuery بدلاً من الدالة mediaQuery
عند الإشارة إلى هاتين المَعلمتَين في دالة lambda query.
val narrowerThanMedium by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND.dp } val narrowerThanExpanded by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND.dp } when { narrowerThanMedium -> SinglePaneLayout() narrowerThanExpanded -> TwoPaneLayout() else -> ThreePaneLayout() }
تعديل التصميم وفقًا لوضع النافذة
تصف المَعلمة windowPosture وضع النافذة الحالي ككائن UiMediaScope.Posture.
يمكنك التحقّق من الوضع الحالي من خلال مقارنة المَعلمة بالقيم المحدّدة في الفئة UiMediaScope.Posture.
يغيّر المثال التالي التنسيق وفقًا لوضع النافذة:
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
التحقّق من دقة جهاز التأشير المتاح
يساعد جهاز التأشير العالي الدقة المستخدمين في التأشير على أحد عناصر واجهة المستخدم بدقة. تعتمد دقة جهاز التأشير على نوع الجهاز.
تصف المَعلمة pointerPrecision دقة أجهزة التأشير المتاحة، مثل الماوس والشاشة التي تعمل باللمس.
هناك أربع قيم محدّدة في الفئة UiMediaScope.PointerPrecision:
Fine وCoarse وBlunt وNone.
يشير الرمز None إلى عدم توفّر أي جهاز تأشير.
تتراوح الدقة من الأعلى إلى الأدنى بهذا الترتيب:
Fine وCoarse وBlunt.
إذا كانت هناك أجهزة تأشير متعدّدة متاحة وكانت دقتها مختلفة، يتم تحديد قيمة المَعلمة باستخدام الجهاز الذي يتمتّع بأعلى دقة.
على سبيل المثال، إذا كان هناك جهازان للتأشير، أحدهما Fine دقيق والآخر Blunt دقيق، تكون قيمة المَعلمة pointerPrecision هي Fine.
يوضّح المثال التالي زرًا أكبر حجمًا عندما يستخدم المستخدم جهاز تأشير بدقة منخفضة:
if (mediaQuery { pointerPrecision == UiMediaScope.PointerPrecision.Blunt }) { LargeSizeButton() } else { NormalSizeButton() }
التحقّق من نوع لوحة المفاتيح المتاح
تمثّل المَعلمة keyboardKind نوع لوحات المفاتيح المتاحة:
Physical وVirtual وNone.
إذا تم عرض لوحة مفاتيح على الشاشة وكانت لوحة مفاتيح خارجية متاحة في الوقت نفسه، سيتم تحديد قيمة المَعلمة على أنّها Physical.
في حال عدم رصد أي منهما، تكون قيمة المَعلمة هي None.
يعرض المثال التالي رسالة تقترح على المستخدمين توصيل لوحة مفاتيح
عند عدم رصد أي لوحة مفاتيح:
if (mediaQuery { keyboardKind == UiMediaScope.KeyboardKind.None }) { SuggestKeyboardConnect() }
التحقّق مما إذا كان الجهاز يتيح استخدام الكاميرا والميكروفون
لا تتوافق بعض الأجهزة مع الكاميرات أو الميكروفونات.
يمكنك التحقّق مما إذا كان الجهاز يتيح استخدام كاميرا وميكروفون
باستخدام المَعلمتَين hasCamera وhasMicrophone.
يوضّح المثال التالي أزرارًا يمكن استخدامها مع الكاميرا والميكروفون عندما يتيح الجهاز استخدامهما:
Row { OutlinedTextField(state = rememberTextFieldState()) // Show the MicButton when the device supports a microphone. if (mediaQuery { hasMicrophone }) { MicButton() } // Show the CameraButton when the device supports a camera. if (mediaQuery { hasCamera }) { CameraButton() } }
ضبط واجهة المستخدم حسب مسافة المشاهدة المقدَّرة
مسافة المشاهدة هي أحد العوامل التي تساعد في تحديد التصميم.
إذا كان المستخدم يستخدم التطبيق من مسافة بعيدة،
سيتوقّع أن يكون النص وعناصر واجهة المستخدم أكبر.
تقدّم المَعلمة viewingDistance تقديرًا لمسافة المشاهدة استنادًا إلى نوع الجهاز وسياق الاستخدام المعتاد.
هناك ثلاث قيم محدّدة في الفئة UiMediaScope.ViewingDistance:
Near وMedium وFar.
يشير الرمز Near إلى أنّ الشاشة في نطاق قريب،
ويشير الرمز Far إلى أنّه يتم عرض الجهاز من مسافة بعيدة.
يزيد المثال التالي حجم الخط عندما تكون مسافة المشاهدة
Far أو Medium:
val fontSize = when { mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Far } -> 20.sp mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Medium } -> 18.sp else -> 16.sp }
معاينة أحد عناصر واجهة المستخدم
يمكنك استدعاء الدالتَين mediaQuery وderivedMediaQuery في الدوال القابلة للإنشاء لمعاينة مكوّنات واجهة المستخدم.
يختار المقتطف التالي بين TabletopLayout
وFlatLayout استنادًا إلى قيمة المَعلمة windowPosture.
لمعاينة TabletopLayout، يجب أن تكون قيمة المَعلمة windowPosture هي
UiMediaScope.Posture.Tabletop.
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
تقيّم الدالتان mediaQuery وderivedMediaQuery تعبير lambda query المحدّد ضمن عنصر UiMediaScope، والذي يتم توفيره كـ LocalUiMediaScope.current.
يمكنك تجاهل هذه الإعدادات باتّباع الخطوات التالية:
- فعِّل وظيفة
mediaQuery. - حدِّد عنصرًا مخصّصًا ينفّذ واجهة
UiMediaScope. - اضبط العنصر المخصّص على
LocalUiMediaScopeباستخدام الدالةCompositionLocalProvider. - استدعِ العنصر القابل للإنشاء لمعاينته في رمز lambda الخاص بالمحتوى في الدالة
CompositionLocalProvider.
يمكنك معاينة TabletopLayout باستخدام المثال التالي:
@Preview @Composable fun PreviewLayoutForTabletop() { // Step 1: Enable the mediaQuery function ComposeUiFlags.isMediaQueryIntegrationEnabled = true val currentUiMediaScope = LocalUiMediaScope.current // Step 2: Define a custom object implementing the UiMediaScope interface. // The object overrides the windowPosture parameter. // The resolution of the remaining parameters is deferred to the currentUiMediaScope object. val uiMediaScope = remember(currentUiMediaScope) { object : UiMediaScope by currentUiMediaScope { override val windowPosture: UiMediaScope.Posture = UiMediaScope.Posture.Tabletop } } // Step 3: Set the object to the LocalUiMediaScope. CompositionLocalProvider(LocalUiMediaScope provides uiMediaScope) { // Step 4: Call the composable to preview. when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() } } }