رخصة قيادة السيارة ، أو لماذا يجب أن تكون التطبيقات أحادية النشاط

الصورة


في AppsConf 2018 ، التي جرت في 8-9 أكتوبر ، قدمت عرضًا تقديميًا حول إنشاء تطبيقات Android في نشاط واحد. على الرغم من أن الموضوع معروف جيدًا ، إلا أن هناك العديد من الأحكام المسبقة المتعلقة بهذا الاختيار - الغرفة المزدحمة وعدد الأسئلة بعد الخطاب تؤكد ذلك. لكي لا أنتظر تسجيل الفيديو ، قررت أن أصنع مقالًا يحتوي على نسخة من الخطاب.



ما سأقوله


  1. لماذا ولماذا يجب أن أنتقل إلى نشاط واحد
  2. نهج عالمي لحل المهام التي اعتدت على حلها في العديد من الأنشطة
  3. أمثلة على المهام التجارية القياسية
  4. الاختناقات حيث يتم دعم التعليمات البرمجية عادةً بدلاً من القيام بكل شيء بصدق

لماذا النشاط المفرد صحيح؟


دورة الحياة



يعرف جميع مطوري Android مخطط البدء البارد للتطبيق. أولاً ، يتم استدعاء onCreate في فئة التطبيق ، ثم تدخل دورة حياة النشاط الأول في العمل.
إذا كان هناك العديد من الأنشطة في طلبنا (وكانت هناك غالبية هذه التطبيقات) ، فسيحدث ما يلي:


App.onCreate() ActivityA.onCreate() ActivityA.onStart() ActivityA.onResume() ActivityA.onPause() ActivityB.onCreate() ActivityB.onStart() ActivityB.onResume() ActivityA.onStop() 

هذا هو سجل بدء النشاط المجرد من ActivityA. السطر الفارغ هو اللحظة التي تم فيها إطلاق شاشة جديدة. للوهلة الأولى ، كل شيء على ما يرام. ولكن إذا انتقلنا إلى الوثائق ، فسيكون واضحًا: لضمان أن الشاشة مرئية للمستخدم وأنه يمكنه التفاعل معها ، فلا يمكن ذلك إلا بعد الاتصال على onResume على كل شاشة:


 App.onCreate() ActivityA.onCreate() ActivityA.onStart() ActivityA.onResume() <-------- ActivityA.onPause() ActivityB.onCreate() ActivityB.onStart() ActivityB.onResume() <-------- ActivityA.onStop() 

المشكلة هي أن مثل هذا السجل لا يساعد على فهم دورة حياة التطبيق. عندما لا يزال المستخدم في الداخل ، وعندما يكون قد انتقل بالفعل إلى تطبيق آخر أو قلل من تطبيقنا وما إلى ذلك. وهذا ضروري عندما نرغب في ربط منطق الأعمال بمنفذ LC للتطبيق ، على سبيل المثال ، الاحتفاظ باتصال مأخذ أثناء وجود المستخدم في التطبيق وإغلاقه عند الخروج


في تطبيق أحادي النشاط ، كل شيء بسيط - يصبح نشاط LC تطبيق LC. من السهل ربط كل ما تحتاجه لأي منطق بحالة التطبيق.


شاشات الإطلاق


كمستخدم ، غالبًا ما صادفت حقيقة أن مكالمة من دليل الهاتف (وهذا هو بوضوح إطلاق نشاط منفصل) لا تحدث بعد النقر على جهة اتصال. من غير الواضح ما الذي يرتبط به هذا ، لكن أولئك الذين حاولت الوصول إليهم دون جدوى قالوا إنهم تلقوا المكالمة وسمعوا صوت الخطوات. في الوقت نفسه ، كان هاتفي الذكي في جيبي منذ فترة طويلة.



تكمن المشكلة في أن بدء نشاط ما هو عملية غير متزامنة تمامًا! لا يوجد ضمان لبدء التشغيل الفوري ، والأسوأ من ذلك ، لا يمكننا التحكم في العملية. إطلاقا.


في تطبيق النشاط الفردي ، بالعمل مع مدير الجزء ، يمكننا التحكم في العملية.
transaction.commit() - سيتم تبديل الشاشات بشكل غير متزامن ، مما يسمح لك بفتح أو إغلاق شاشات متعددة مرة واحدة.
transaction.commitNow() - لتبديل الشاشة بشكل متزامن ، إذا لم تكن بحاجة إلى إضافتها إلى المكدس.
fragmentManager.executePendingTransactions () `يسمح لك بتنفيذ جميع المعاملات التي تم إطلاقها مسبقًا الآن.


تحليل مكدس الشاشة


تخيل أن منطق الأعمال الخاص بتطبيقك يعتمد على العمق الحالي لكومة الشاشات (على سبيل المثال ، قيود التعشيش). أو ، في نهاية بعض العمليات ، تحتاج إلى العودة إلى شاشة معينة ، وإذا كانت هناك عدة شاشات متطابقة ، إلى الشاشة الأقرب إلى الجذر (بداية السلسلة).
كيف تحصل على مكدس نشاط؟ ما هي المعلمات التي يجب تحديدها عند بدء الشاشة؟



بالمناسبة ، عن سحر خيارات إطلاق النشاط:


  • يمكنك تحديد علامات الإطلاق في Intent (وكذلك مزجها معًا وتغييرها من أماكن مختلفة) ؛
  • يمكنك إضافة معلمات التشغيل في البيان ، لأنه يجب وصف جميع الأنشطة هناك ؛
  • أضف فلاتر Intent هنا للتعامل مع التشغيل الخارجي ؛
  • وأخيرًا فكر في المهام المتعددة ، عندما يمكن تشغيل الأنشطة في "مهام" مختلفة.

يخلق هذا معًا ارتباكًا ومشكلات في تصحيح الأخطاء في الدعم. لا يمكنك أبدًا التأكد على وجه الدقة من كيفية تشغيل الشاشة وكيف أثرت على المكدس.


في تطبيق أحادي النشاط ، يتم تبديل جميع الشاشات من خلال المعاملات الجزئية فقط. يمكنك تحليل مجموعة الشاشات الحالية والمعاملات المحفوظة.
في العرض التوضيحي لمكتبة Cicerone ، يمكنك مشاهدة كيفية عرض الحالة الحالية للمكدس في شريط الأدوات.


الصورة


ملاحظة: في الإصدار الأحدث ، منعت مكتبات الدعم الوصول إلى مجموعة الأجزاء داخل مدير الأجزاء ، ولكن إذا كنت تريد ذلك حقًا ، فيمكن دائمًا حل هذه المشكلة.


نشاط واحد فقط على الشاشة


في التطبيقات الحقيقية ، سنحتاج بالتأكيد إلى الجمع بين الشاشات "المنطقية" في نشاط واحد ، ثم لا يمكنك كتابة تطبيق حقيقي فقط على النشاط. دائمًا ما تكون ازدواجية النهج سيئة ، حيث يمكن حل نفس المشكلة بطرق مختلفة (في مكان ما ، يكون التخطيط مباشرة في النشاط ، وفي مكان ما ، يكون النشاط مجرد حاوية).


لا تحتفظ بالأنشطة


تسمح لك علامة الاختبار هذه حقًا بالعثور على بعض الأخطاء في التطبيق ، ولكن السلوك الذي يعيد إنتاجه لا يحدث أبدًا في الواقع! لا يحدث أن تظل عملية تقديم الطلب ، وفي هذه اللحظة يموت النشاط ، على الرغم من أنه غير نشط! يمكن أن تموت الأنشطة فقط مع عملية التقديم. إذا تم عرض التطبيق للمستخدم ، ولم يكن لدى النظام موارد كافية ، فسوف يموت كل شيء من حوله (التطبيقات والخدمات غير النشطة الأخرى ، وحتى المشغل) ، وسيعيش تطبيقك حتى النهاية المريرة ، وإذا كان يجب أن يموت ، فسيكون تمامًا.
يمكنك التحقق.


تراث


من الناحية التاريخية ، هناك قدر كبير من المنطق غير الضروري في النشاط الذي من المحتمل ألا يكون مفيدًا لك. على سبيل المثال ، كل ما تحتاجه للعمل مع loaders ، actionBar action menu وما إلى ذلك. هذا يجعل الفصل نفسه ضخمًا جدًا وثقيلًا.


الرسوم المتحركة


ربما يمكن لأي شخص عمل رسم متحرك بسيط عند التبديل بين النشاط. هنا من الجدير توضيح أنك بحاجة إلى إجراء خصم على عدم تزامن إطلاق النشاط ، والذي تحدثنا عنه سابقًا.
إذا كنت بحاجة إلى شيء أكثر إثارة للاهتمام ، يمكنك تذكر مثل هذه الأمثلة من الرسوم المتحركة الانتقالية التي تم إجراؤها على النشاط:


الصورة


ولكن هناك مشكلة كبيرة: تخصيص هذه الرسوم المتحركة يكاد يكون مستحيلاً. هذا من غير المحتمل أن يرضي المصممين والعملاء.


مع الشظايا ، كل شيء مختلف. يمكننا أن ننزل مباشرة إلى مستوى التسلسل الهرمي للعرض ونقوم بعمل أي رسم متحرك يمكنك تخيله! دليل مباشر هنا :


الصورة


إذا نظرت إلى شفرة المصدر ، فستجد أن هذا يتم على تخطيط منتظم. نعم ، الكود لائق هناك ، لكن الرسوم المتحركة صعبة دائمًا بما يكفي ، والحصول على مثل هذه الفرصة دائمًا ما يكون زائدًا. إذا كان لديك نشاطان تم تبديلهما ، فالتطبيق لا يحتوي على حاوية مشتركة حيث يمكنك إجراء مثل هذه التحولات.


تكوين التكوين على الطاير


لم تكن هذه النقطة في خطابي ، ولكنها مهمة أيضًا. إذا كانت لديك ميزة مع تبديل اللغة داخل التطبيق ، فسيكون من الصعب تطبيقه مع العديد من الأنشطة ، إذا كنت لا تحتاج ، من بين أمور أخرى ، إلى إعادة تشغيل التطبيق ، ولكن تبقى في نفس المكان الذي كان فيه المستخدم في وقت الاتصال بالوظيفة.


في تطبيق أحادي النشاط ، يكفي تغيير الإعدادات المحلية المثبتة في سياق التطبيق واستدعاء recreate() في النشاط ، وسيفعل بقية النظام كل شيء بنفسه.


في النهاية


لدى Google حل ملاحة ، تنص وثائقه صراحةً على أنه من المستحسن كتابة تطبيقات النشاط الفردي.


في هذه المرحلة ، آمل ألا يكون لديك شك في أن النهج الكلاسيكي مع العديد من الأنشطة يحتوي على عدد من أوجه القصور ، والتي من المعتاد أن تغض الطرف ، مختبئة وراء الاتجاه العام لاستياء Android.


إذا كان الأمر كذلك ، فلماذا لا يعد النشاط الفردي معيار تطوير بعد؟


هنا سأقتبس من صديقي العزيز:



عند بدء مشروع جدي جديد ، فإن أي قائد يخشى الخطأ ويتجنب القرارات الخطرة. هذا صحيح. لكني سأحاول تقديم خطة شاملة للانتقال إلى النشاط الفردي.


التبديل إلى نشاط واحد



إذا درست هذا التطبيق ، يمكنك أن تحدد من الرسوم المتحركة والسلوك المميز أنه مكتوب على العديد من الأنشطة. قد أكون مخطئًا ، وتم عمل كل شيء حتى على طرق العرض المخصصة ، ولكن هذا لن يؤثر على تفكيرنا.


الآن الانتباه! نفعل ذلك على هذا النحو:



أدخلنا تغييرين فقط: أضفنا فئة AppActivity واستبدلنا جميع الأنشطة بـ FlowFragment. خذ بعين الاعتبار كل تغيير بمزيد من التفاصيل.


ما هو AppActivity المسؤول عن:


  • يحتوي فقط على حاوية للشظايا
    • هي نقطة التهيئة لكائنات واجهة مستخدم النطاق (كان يتم ذلك في التطبيق ، وهو أمر خاطئ ، لأن ، على سبيل المثال ، كائنات الخدمة في تطبيقنا لا تحتاج بالتأكيد إلى مثل هذه الكائنات)
    • هو مزود تطبيق
    • يجلب كل فوائد النشاط المفرد.

ما هو FlowFragment :


  • يفعل نفس الشيء تمامًا مثل النشاط ، بدلاً من إنشائه.

التنقل الجديد


الاختلاف الرئيسي عن النهج القديم هو التنقل.



في السابق ، كان للمطور خيار: إطلاق نشاط جديد أو معاملة تجزئة في النشاط الحالي. لم يختف الاختيار ، لكن الأساليب تغيرت - الآن نحن بحاجة إلى أن نقرر ما إذا كان سيتم بدء تجزئة الجزء في AppActivity أو داخل FlowFragment الحالي.



وبالمثل مع معالجة زر العودة. في السابق ، كان النشاط يمرر الحدث إلى الجزء الحالي ، وإذا لم يقم بمعالجته ، فقد اتخذ القرار بنفسه. يقوم AppActivity الآن بتمرير الحدث إلى FlowFragment الحالي ، وهذا بدوره يمرره إلى الجزء الحالي.


نقل النتائج بين الشاشات


بالنسبة للمطورين عديمي الخبرة ، فإن مشكلة نقل البيانات بين الشاشات هي المشكلة الرئيسية للنهج الجديد ، لأنه في وقت سابق كان من الممكن استخدام وظيفة startActivityForResult ()!


ليست السنة الأولى ، تمت مناقشة العديد من الأساليب المعمارية لكتابة الطلبات. تبقى المهمة الرئيسية في الوقت نفسه هي فصل واجهة المستخدم وطبقة البيانات ومنطق الأعمال. من وجهة النظر هذه ، يكسر startActivityForResult () الشريعة ، حيث يتم نقل البيانات بين شاشات تطبيق واحد على جانب الكيان من طبقة واجهة المستخدم. أؤكد أنه تطبيق واحد فقط ، لأن لدينا طبقة بيانات مشتركة ونماذج مشتركة في نطاق عالمي ، وما إلى ذلك. نحن لا نستخدم هذه الفرص ونقود أنفسنا في إطار حزمة واحدة (التسلسل والحجم والمزيد).
نصيحتي : لا تستخدم startActivityForResult () داخل التطبيق! استخدمها فقط للغرض المقصود - لتشغيل التطبيقات الخارجية والحصول على نتائج منها.


فكيف لإطلاق شاشة مع اختيار شاشة أخرى؟ هناك ثلاثة خيارات:


  1. جزء الهدف
  2. Eventbus
  3. نموذج طائرة

TargetFragment - خيار "خارج الصندوق" ، ولكن نفس نقل البيانات على جانب طبقة واجهة المستخدم. خيار سيئ.


EventBus - إذا كان بإمكانك الاتفاق على فريق - والأهم من ذلك - التحكم في الترتيبات ، فيمكنك تنفيذ نقل البيانات بين الشاشات على ناقل البيانات العالمي. ولكن بما أن هذه خطوة خطيرة ، فإن الاستنتاج هو خيار سيئ.


نموذج رد الفعل - يشير هذا النهج إلى وجود الاستدعاءات وأكثر من ذلك. يقرر فريق كل مشروع كيفية تنفيذها. لكن هذا النهج هو الأمثل ، لأنه يوفر السيطرة على ما يحدث ولا يسمح باستخدام الرمز لأغراض أخرى. خيارنا!


الملخص


أنا أحب الأساليب الجديدة عندما تكون بسيطة ولها فوائد واضحة. آمل أن يكون هذا هو الحال في هذه الحالة. يتم وصف الفوائد في الجزء الأول ، ويجب أن تحكم على الصعوبة. يكفي استبدال كل النشاط بـ FlowFragment ، مع إبقاء كل المنطق دون تغيير. غيّر رمز التنقل قليلاً وفكر في العمل على نقل البيانات بين الشاشات ، إذا لم يتم ذلك بالفعل.


لإظهار بساطة النهج ، قمت بنفسي بتحويل التطبيق المفتوح إلى نشاط فردي ، واستغرق الأمر بضع ساعات فقط (بالطبع ، يجدر النظر في أن هذا ليس إرثًا قديمًا ، وكل شيء جيد إلى حد ما مع الهندسة المعمارية هناك).


ماذا حدث؟


دعونا نرى كيفية حل المشاكل القياسية في نهج جديد.


شريط التنقل السفلي و لوحة التنقل


باستخدام القاعدة البسيطة التي نستبدل بها كل الأنشطة بـ FlowFragment ، ستكون القائمة الجانبية الآن في بعض الأجزاء وتبديل الأجزاء المتداخلة فيها:



مماثلة مع BottomNavigationBar.
من المثير للاهتمام أكثر أنه يمكننا استثمار بعض FlowFragment في الآخرين ، حيث لا تزال هذه أجزاء عادية!



يمكن العثور على هذا الخيار في GitFox .


إن إمكانية الجمع بين بعض الأجزاء داخل أجزاء أخرى تجعل من الممكن إنشاء واجهة مستخدم ديناميكية للأجهزة المختلفة دون أي مشاكل: الأجهزة اللوحية + الهواتف الذكية.


نطاقات DI


إذا كان لديك تدفق لمشتريات المنتج من عدة شاشات ، وتحتاج إلى إظهار اسم المنتج على كل شاشة ، فمن المحتمل أنك وضعت هذا بالفعل في نشاط منفصل يخزن المنتج ويوفره على الشاشات.
سيكون الأمر نفسه مع FlowFragment - سيحتوي على مقياس DI مع نماذج لجميع الشاشات المتداخلة. يلغي هذا النهج التحكم المعقد في عمر النطاق من خلال ربطه بعمر FlowFragment.




إذا استخدمت الفلاتر في البيان لتشغيل شاشة معينة على الرابط العميق ، فقد تواجه مشاكل في بدء النشاط ، والذي كتبت عنه في الجزء الأول. في النهج الجديد ، تقع جميع الارتباطات العميقة في AppActivity.onNewIntent. علاوة على ذلك ، وفقًا للبيانات التي تم الحصول عليها ، هناك انتقال إلى الشاشة المطلوبة (أو سلسلة من الشاشات. أقترح النظر إلى هذه الوظيفة في Chicheron ).



الموت عملية


إذا تمت كتابة التطبيق في العديد من الأنشطة ، يجب أن تعلم أنه عند وفاة التطبيق ، وعند استعادة العملية ، سيكون المستخدم في آخر نشاط ، ولن تتم استعادة جميع الأنشطة السابقة إلا عند إعادتها إليه.



إذا لم تأخذ هذا في الاعتبار مسبقًا ، فقد تنشأ مشاكل. على سبيل المثال ، إذا كان النطاق المطلوب في آخر نشاط تم فتحه في السابق ، فلن يقوم أحد بإعادة إنشائه. ماذا تفعل أحضر هذا إلى فئة التطبيق؟ هل تفتح نقاط متعددة نطاقات؟


كل شيء أبسط مع الأجزاء ، حيث إنها داخل نشاط أو FlowFragment آخر ، وسيتم استعادة أي حاوية قبل إعادة إنشاء الجزء.



يمكننا مناقشة المهام العملية الأخرى في التعليقات ، وإلا فهناك احتمال أن تصبح المقالة ضخمة للغاية.


والآن الجزء الأكثر إثارة للاهتمام.


الاختناقات (عليك أن تتذكر وتفكر).


هنا يتم جمع أشياء مهمة يجب أن تفكر فيها في أي مشروع ، ولكن الجميع معتادون على "تمزيقهم" في المشاريع في العديد من الأنشطة التي تستحق التذكير وإخبار كيفية حلها بشكل صحيح في النهج الجديد. والأول في القائمة


تدوير الشاشة


هذه هي الحكاية الأكثر رعباً لأنين المعجبين الذين يعيد Android إنشاء النشاط عند تدوير الشاشة. طريقة الحل الأكثر شيوعًا هي إصلاح الاتجاه الرأسي. علاوة على ذلك ، لم يعد هذا الاقتراح من قبل المطورين ، ولكن من قبل المديرين الذين يخافون من عبارات مثل " الحفاظ على منعطف صعب للغاية ويكلف عدة مرات أكثر ."
لن نتجادل حول صحة مثل هذا القرار. شيء آخر مهم: تثبيت الدوران لا يعفي من موت النشاط! نظرًا لأن نفس العمليات تحدث مع العديد من الأحداث الأخرى: وضع الانقسام ، عندما يتم عرض العديد من التطبيقات على الشاشة ، وتوصيل شاشة خارجية ، وتغيير تكوين التطبيق بسرعة.


علاوة على ذلك ، يسمح لك تدوير الشاشة بالتحقق من "مرونة" التصميم الصحيحة ، وبالتالي ، في فريقنا في سانت بطرسبرغ ، لا نقوم بإيقاف التدوير في جميع مجموعات المبيعات ، حتى إذا لم يكن في إصدار الإصدار. ناهيك عن الأخطاء النموذجية التي ستظل موجودة أثناء التحقق.


تم بالفعل كتابة العديد من الحلول للتحول ، بدءًا من Moxy وتنتهي بتطبيقات MVVM المختلفة. لا تجعل الأمر أكثر صعوبة من أي شيء آخر.


النظر في حالة أخرى مثيرة للاهتمام.
تخيل تطبيق كتالوج المنتج. نقوم بذلك في نشاط واحد. في كل مكان يتم إصلاح الوضع الرأسي ، لكن العميل يريد ميزة عندما يتمكن المستخدم عند مشاهدته من مشاهدة الصور في الاتجاه الأفقي. كيف تدعم هذا؟


سيقدم شخص ما العكاز الأول :


 <activity android:name=".AppActivity" android:configChanges="orientation" /> 

 override fun onConfigurationChanged(newConfig: Configuration?) { if (newConfig?.orientation == Configuration.ORIENTATION_LANDSCAPE) { //ignore } else { super.onConfigurationChanged(newConfig) } } 

وبالتالي ، لا يمكننا استدعاء super.onConfigurationChanged(newConfig) ، ولكن super.onConfigurationChanged(newConfig) بأنفسنا وتدوير العرض الضروري فقط على الشاشة.
ولكن مع API 23 ، SuperNotCalledException المشروع مع SuperNotCalledException ، لذلك يعد خيارًا سيئًا .


البيانات أعلاه ارتكبت خطأ:
تم تصحيحي بشكل معقول في التعليقات التي تفيد بأن إضافة android: configChanges = “orientation | screenSize” يكفي ، ثم يمكنك الاتصال بـ super ولن يتم إعادة إنشاء النشاط عند التدوير. يفيد ذلك عندما تكون WebView أو الخريطة على الشاشة تستغرق وقتًا طويلاً في التهيئة ، وتريد تجنبها.
سيساعد هذا على حل الحالة الموضحة مع المعرض ، ولكن الرسالة الرئيسية لهذا القسم: لا تتجاهل إعادة النشاط ، فقد يحدث هذا في العديد من الحالات الأخرى.


قد يقترح شخص ما حلاً آخر:


 <activity android:name=".AppActivity" android:screenOrientation="portrait" /> <activity android:name=".RotateActivity" /> 

ولكن بهذه الطريقة نبتعد عن نهج النشاط الفردي لحل مشكلة بسيطة وحرمان أنفسنا من جميع مزايا النهج. هذا عكاز ، والعكاز دائمًا خيار سيئ .


هنا هو الحل الصحيح:


 <activity android:name=".AppActivity" android:configChanges="orientation" /> 

 override fun onResume() { super.onResume() activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR } override fun onPause() { super.onPause() activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } 

أي ، عندما يتم فتح الجزء ، يبدأ التطبيق في "الدوران" ، وعندما يعود ، يتم إصلاحه مرة أخرى. في تجربتي ، هذه هي الطريقة التي يعمل بها تطبيق AirBnB . إذا فتحت عرضًا لصور الإسكان ، فسيتم تنشيط معالجة الدوران ، ولكن في الاتجاه الأفقي ، يمكنك سحب الصورة لأسفل للخروج من المعرض. تحته ، ستكون الشاشة السابقة مرئية في الاتجاه الأفقي ، والتي لن تجدها عادةً ، لأنه فور مغادرة المعرض ستتحول الشاشة إلى صورة ويتم إصلاحها.



هذا هو المكان الذي يساعد فيه التحضير في الوقت المناسب لتدوير الشاشة.


شريط شفاف للحالة


يمكن أن يعمل النشاط فقط مع شريط النظام ، ولكن الآن لدينا واحد فقط ، لذلك يجب عليك تحديده دائمًا


 <item name="android:windowTranslucentStatus">true</item> 

ولكن في بعض الشاشات ، ليست هناك حاجة "للزحف" تحته ، وتحتاج إلى عرض كل المحتوى أدناه. يأتي العلم لإنقاذ


 android:fitsSystemWindows="true" 

مما يشير إلى التخطيط الذي يجب ألا ترسمه أسفل شريط النظام. ولكن إذا قمت بتحديده في تخطيط الجزء ، ثم حاولت عرض الجزء من خلال المعاملة في مدير الجزء ، فستصاب بخيبة أمل ... لن تعمل!
الجواب بسرعة جوجل
أوصي بشدة أن تتعرف على إجابة شاملة حقًا والعديد من الروابط المفيدة.
الحل السريع والعمل ( ولكن ليس الصحيح ) هو لف التخطيط في CoordinatorLayout


 <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> </android.support.design.widget.CoordinatorLayout> 

يساعد الحل الأفضل في معالجة لوحة المفاتيح.


تغيير التخطيط عندما تظهر لوحة المفاتيح


عندما تغادر لوحة المفاتيح ، يجب أن يتغير التخطيط بحيث لا تبقى العناصر المهمة لواجهة المستخدم بعيدة المنال. وإذا تمكنا في وقت سابق من تحديد أوضاع رد فعل مختلفة للوحة المفاتيح للأنشطة المختلفة ، فإننا الآن بحاجة إلى القيام بذلك في نشاط فردي. لذلك من الضروري استخدام


 android:windowSoftInputMode="adjustResize" 

إذا استخدمت النهج من القسم السابق لمعالجة شريط حالة شفاف ، فستجد خطأ مؤسفًا: إذا تم الزحف إلى جزء بنجاح تحت شريط الحالة ، فعند ظهور لوحة المفاتيح ، ستتقلص أعلى وأسفل ، حيث يعمل شريط الحالة ولوحة المفاتيح داخل النظام من خلال SystemWindows .


انتبه إلى العنوان



ماذا تفعل اقرأ الوثائق! Chris Banes WindowInsets .


WindowInsets


  • ( 51dp)
  • ( !)
  • .

WindowInsets!


Splash screen


- , Splash screen — , , , , Activity . .



, Single-Activity, Splash screen. , deep-link Splash screen .



, , , .


, . Single-Activity. - , , .
...
Intent, , ...
ما هي الخطوة التالية؟ :


  • , «». «», . , !
  • , …

, . ? — «» «» .


ماذا تفعل , .


Activity!
, : , — .
— , ( Activity), .


Activity — . Activity, . .



الخلاصة


() , Activity, Android-. , .


: Google . — , , Activity .


, , , ! شكرا لك!

Source: https://habr.com/ru/post/ar426617/


All Articles