تحتاج إلى أنواع مختلفة من المعلومات، مثل إمكانات الجهاز وحالة التطبيق، لتحديث تخطيط تطبيقك. عرض النافذة وارتفاعها هما المعلومات الأكثر استخدامًا. إضافةً إلى ذلك، يمكنك الرجوع إلى المعلومات التالية:
- وضع النافذة
- دقة أجهزة التأشير
- نوع لوحة المفاتيح
- ما إذا كان الجهاز يتيح استخدام الكاميرا والميكروفون
- المسافة بين المستخدم وشاشة الجهاز
بما أنّه يتم تعديل المعلومات بشكل ديناميكي،
عليك مراقبتها وبدء إعادة الإنشاء عند حدوث أي تعديل.
تستخرج الدالة 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() } } }