أحرقت في سبتمبر 2007. كان سبتمبر 2017 ، أعادت Apple الموضة إلى الهامش ، مقدمة لـ iPhone X. ليس من المستغرب أن يقوم أصدقاؤنا من الصين ، دون التفكير مرتين ، بنسخ هذا التصميم من Apple (على الرغم من أن أول هامش صغير كان لا يزال في الهاتف الأساسي ، والذي لم يخلع). لكن ماذا نرى الآن؟ Huawei P20 و Asus Zenfone 5 و OnePlus 6 و Motorola One Power و Xiaomi Redmi 6 وغيرها من الشركات المصنعة المعروفة تقريبًا تنتج بالفعل أو تعلن عن الهواتف مع الانفجارات. كانت سامسونغ وجوجل آخر معاقل في هذا
السباق للنضال الضخم من أجل بدون إطار. أم لا؟ وفقًا للشائعات ، سيكون Google Pixel 3 XL أيضًا
مع هذا الهراء مع خط رقبة رشيق. حسنًا ، نحن كمطورين ، يمكننا فقط تحسين تطبيقاتهم لهذا الفصل بحيث يمكن للمستخدمين الاستمرار في استخدامها بشكل مريح. أطلب تفاصيل تحت القط.

أولاً ، نحتاج إلى معرفة ما إذا كان التطبيق يحتاج إلى أي تحسين على الإطلاق؟
إذا كان لديك تطبيق ملء الشاشة أو
windowActionBarOverlay = true
موجود في السمة ، فمن المحتمل أن تكون هناك حاجة إليه.
جميع التطبيقات تقريبًا بعيدة عن شاشة واحدة ، وقد لا تلاحظ كيف سيتم التخطيط على أحدها. خاصة إذا كان التطبيق يحتوي على رمز إرث ضخم. لذلك ، لا يزال عليك المرور عبر جميع الشاشات الرئيسية والتحقق مرة أخرى. دعونا نكتشف ما يجب القيام به لهذا الغرض.
1. إعداد جهاز اختبار / محاكي
من أجل اختبار التطبيق الخاص بك مع الانفجارات ، تحتاج (بفضل ، غطاء!) Android P. حاليًا ، يتوفر Android P Preview 5 للأجهزة التالية (بفضل Project Treble):
هاتف أساسي
جوجل Pixel 2 ؛
جوجل Pixel 2 XL ؛
جوجل بيكسل
جوجل بيكسل اكس ال
نوكيا 7 بلس ؛
OnePlus 6 ؛
Oppo R15 Pro ؛
سوني Xperia XZ2 ؛
Vivo X21UD ؛
Vivo X21 ؛
Xiaomi Mi Mix 2S.
لتثبيت Android P على جهازك ، ما عليك سوى النقر
هنا والنقر على "الحصول على إصدار تجريبي" لجهازك. الحصول عليه في الهواء أو دحرجه بنفسك - الخيار لك. يتم إرفاق التعليمات الموجودة على الموقع.
ولكن إذا كنت لا تستطيع أو لا تريد تثبيت Android P على الجهاز ، فلن يقوم أحد بإلغاء المحاكي. تعليمات الإعداد
هنا .
2. قم بتشغيل الانفجار نفسه برمجيًا (إذا لم يكن هناك أجهزة)
كل شيء بسيط هنا: انتقل إلى النظام -> خيارات المطور -> محاكاة شاشة بفتحة.
هناك 3 خيارات للاختيار من بينها:

تبدو كما يلي:
3. المشي من خلال الشاشات الرئيسية
بالطبع ، ستكون هذه الحالة مختلفة بالنسبة للجميع. شخص ما لديه منطق بسيط ، شخص ما ليس لديه. سأقدم بضعة أمثلة على الشاشات ذات التنسيق المتنقل التي وجدتها في طلبنا.
استكشف | الملف الشخصي |
---|
 |  |
الآن دعونا نرى ما هي طرق إزالة عيوب التخطيط.
دون رفع compileSdkVersion
بدءًا من 20 API ،
ظهرت فئة
WindowInsets ، وهي كائن
Rect يصف الأجزاء التي يمكن الوصول إليها والتي لا يمكن الوصول إليها من الشاشة. معًا ، ظهرت هذه الأساليب في طريقة العرض التي يمكننا استخدامها لمعالجة إحداثيات الأجزاء التي يتعذر الوصول إليها من الشاشة:
WindowInsets dispatchApplyWindowInsets(WindowInsets); WindowInsets onApplyWindowInsets(WindowInsets); void requestApplyInsets(); void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener);
التفاصيل حول كيفية استخدامها
هنا .
هناك طريقتان لاستخدام هذه الأساليب:
أ) ضع العلامة
android:fitsSystemWindows="true"
في التخطيط على التخطيط أو العرض ؛
ب) افعل ذلك من الكود:
layout.setFitsSystemWindows(true); layout.requestApplyInsets();
كان | أصبح |
---|
 |  |
قم بترقية compileSdkVersion إلى الإصدار 28
في المستقبل القريب سيكون عليك التبديل إلى هذا الإصدار ، فلماذا لا تستعد لهذا الآن؟ ولكن كن حذرًا إذا كانت لديك اختبارات وحدة في مشروعك (وآمل أن يكون لديك اختبارات) ، فقد تم نقل حزمة JUnit. يوصف كيفية توصيله
هنا .
إذن ، ما هي الخيارات التي يوفرها لنا Android P الآن؟
A. WindowManager.LayoutParams لديه 3 أعلام جديدة:
كيفية التقديم؟
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
ب. إذا لم يكن الخيار A مناسبًا لك وتحتاج إلى مراعاة موقع القصاصة المشؤومة (على سبيل المثال ، يتم عرض شيء ما مباشرة في شريط الحالة ، مثل رسالة الاتصال في Telegram) ، في هذه الحالة ، سيساعدك فصل
DisplayCutout الجديد.
النظر في أساليبها:
معهم يمكنك بالفعل القيام بكل ما يكفي للخيال. هل تريد - تحريك
margin
في الكود عليهم.
OnApplyWindowInsetsListener
تريد ،
OnApplyWindowInsetsListener
معها في
OnApplyWindowInsetsListener
وقم
consumeDisplayCutout()
. ربما تحتاج إلى تلاعبات أكثر تعقيدًا. سأعطي مثالاً بسيطًا عن كيفية الإشارة إلى الانفجار.
class SampleFragment() : Fragment() { private lateinit var root: ViewGroup override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.sample_fragment, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) root = view.findViewById(R.id.root) addArrowsToCutout() } private fun addArrowsToCutout() { // , attach window, null' val cutoutList = root.rootWindowInsets?.displayCutout?.boundingRects cutoutList?.forEach { addArrow(context!!.getDrawable(R.drawable.left), it.left.toFloat(), it.top + (it.bottom - it.top).toFloat() / 2, ::calculateLeftArrow) addArrow(context!!.getDrawable(R.drawable.right), it.right.toFloat(), it.top + (it.bottom - it.top).toFloat() / 2, ::calculateRightArrow) addArrow(context!!.getDrawable(R.drawable.top), it.left + (it.right - it.left).toFloat() / 2, it.top.toFloat(), ::calculateTopArrow) addArrow(context!!.getDrawable(R.drawable.bottom), it.left + (it.right - it.left).toFloat() / 2, it.bottom.toFloat(), ::calculateBottomArrow) } } private fun addArrow(arrowIcon: Drawable, x: Float, y: Float, calculation: (View, Float, Float) -> Unit) { val arrowView = ImageView(context) arrowView.setImageDrawable(arrowIcon) arrowView.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) root.addView(arrowView) arrowView.post { calculation(arrowView, x, y) } } private fun calculateLeftArrow(arrowView: View, x: Float, y: Float) { arrowView.x = x - arrowView.width arrowView.y = y - arrowView.height / 2 } private fun calculateRightArrow(arrowView: View, x: Float, y: Float) { arrowView.x = x arrowView.y = y - arrowView.height / 2 } private fun calculateTopArrow(arrowView: View, x: Float, y: Float) { arrowView.x = x - arrowView.width / 2 arrowView.y = y - arrowView.height } private fun calculateBottomArrow(arrowView: View, x: Float, y: Float) { arrowView.x = x - arrowView.width / 2 arrowView.y = y } }
صورة
أفقي
لذا ، كما نرى ، فإن الهامش سيجلب لنا بعض الإزعاج ويجعلنا نقوم بإيماءات إضافية / معالجة إضافية. من حيث المبدأ ، تم حل كل شيء. الشيء الرئيسي هو البدء في إزالة أوجه القصور في التخطيط في أقرب وقت ممكن من أجل الحصول على ما يكفي من الوقت للتحضير. تعامل بنجاح مع تعديلاتك. لا يجوز لشركة Google كسر لعبها!