الهندسة في Sprout: إنشاء منتقي شهري على Android

نشرت: 2020-06-26

ملاحظة: استندت هذه المقالة إلى إصدار "المكونات المادية " 1.2.0-beta01 اعتبارًا من 1 يونيو 2020 .

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

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

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

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

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

مقدمة

قدم إصدار Android Material Components 1.1.0 مكونًا جديدًا لواجهة مستخدم منتقي التاريخ. إحدى الإضافات الترحيبية لهذا MaterialDatePicker الجديد عبر AppCompat CalendarView هي القدرة على تحديد نطاق من التواريخ باستخدام إما طريقة عرض التقويم أو حقل إدخال النص.

لم يكن AppCompat CalendarView القديم مرنًا جدًا. كان مكونًا جيدًا لحالة الاستخدام المحدود التي كان من المفترض حلها ؛ أي تحديد تاريخ واحد والحد الأدنى والأقصى للتواريخ الاختيارية لتحديد نطاق زمني مسموح به.

تم تصميم MaterialDatePicker الجديدة بمزيد من المرونة للسماح باستخدام وظائف السلوك الموسعة. إنه يعمل من خلال سلسلة من الواجهات التي يمكن للمرء تنفيذها لتعديل وتعديل سلوك المنتقي.

يتم تعديل السلوك هذا في وقت التشغيل من خلال مجموعة من وظائف نمط Builder في فئة MaterialDatePicker.Builder .

هذا يعني أننا قادرون على توسيع السلوك الأساسي لـ MaterialDatePicker هذا من خلال مكونات واجهة قابلة للإنشاء.

ملاحظة: في حين أن هناك عددًا من المكونات المختلفة التي يستخدمها MaterialDatePicker ، سنغطي في هذه المقالة مكون تحديد التاريخ فقط.

منتقي النطاق الزمني

كان فريق Sprout Social Android في طور إنشاء قسم تقارير التحليلات.

سيسمح هذا القسم الجديد لمستخدمينا بتحديد مجموعة من الفلاتر ومجموعة من النطاقات الزمنية التي سيغطيها التقرير.

يأتي MaterialDatePicker مع بعض المكونات المبنية مسبقًا والتي يمكننا الاستفادة منها لإنجاز حالة الاستخدام الخاصة بنا.

بالنسبة للحالة الأكثر شيوعًا لدينا ، وهي السماح للمستخدم بتحديد نطاق من التواريخ ، فإن MaterialDatePicker المبنية مسبقًا ستكون كافية:

من خلال كتلة الشفرة هذه ، نحصل على منتقي التاريخ الذي يسمح للمستخدمين بتحديد نطاق زمني.

منتقي التاريخ الشهري

يعد Twitter Trends Report أحد تقارير Sprout Social التي تتضمن تحديدًا فريدًا للتاريخ.

يختلف هذا التقرير عن الآخرين في أنه بدلاً من السماح بأي نوع من النطاق الزمني ، فإنه يفرض تحديدًا لشهر واحد ، مما يعني أنه يمكن للمستخدم تحديد مارس 2020 فقط مقابل 3 مارس إلى 16 مارس 2020.

يتعامل تطبيق الويب الخاص بنا مع هذا باستخدام حقل نموذج منسدلة:

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

سلوك اختيار التاريخ

تستفيد MaterialDatePicker من محدد التاريخ كالواجهة المستخدمة لمنطق التحديد الخاص DateSelector .

من جافادوك:

"واجهة لمستخدمي {@link MaterialCalendar<S>} للتحكم في كيفية عرض التقويم وإرجاع التحديدات ..."

ستلاحظ أن MaterialDatePicker.Builder.dateRangePicker() تُرجع مثيل منشئ RangeDateSelector ، والذي استخدمناه في المثال أعلاه.

هذه الفئة عبارة عن محدد تم إنشاؤه مسبقًا والذي يقوم بتنفيذ محدد DateSelector .

العصف الذهني لسلوك اختيار التاريخ الشهري

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

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

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

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

كان الحل الذي قررناه هو تمديد RangeDateSelector ثم تجاوز سلوك تحديد اليوم للاختيار التلقائي للشهر بأكمله بدلاً من ذلك.

لحسن الحظ ، هناك وظيفة يمكننا تجاوزها من الواجهة DateSelector تسمى: select(selection: Long) .

سيتم استدعاء هذه الوظيفة عندما يختار المستخدم يومًا في المنتقي ، مع مرور اليوم المحدد بالمللي ثانية بالتوقيت العالمي المنسق من الحقبة.

تنفيذ سلوك اختيار التاريخ الشهري

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

سيكون المنطق الأساسي كما يلي:

  1. يختار المستخدم اليوم.
  2. يتم استدعاء وظيفة select() مع اليوم المحدد في جزء من الثانية بالتوقيت العالمي المنسق الطويل من الحقبة.
  3. ابحث عن اليوم الأول والأخير من الشهر من اليوم المحدد الذي فاتنا.
  4. قم بإجراء مكالمة إلى super.select(1st of month) & super.select(last day of month)
  5. يجب أن يعمل السلوك الأصل من RangeDateSelector كما هو متوقع ، وحدد الشهر كنطاق تاريخ.

ضع كل شيء معا

الآن بعد أن أصبح لدينا محدد الشهر المخصص لدينا ، يمكننا إعداد MonthRangeDateSelector MaterialDatePicker الخاص بنا.

لنأخذ المثال إلى أبعد من ذلك ، يمكننا معالجة نتيجة الاختيار على النحو التالي:

ستبدو النتيجة كما يلي:

مسكتك

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

كانت المكونات الأساسية المستخدمة لبناء MonthRangeDateSelector بنا هي فئة RangeDateSelector وواجهة DateSelector . قام إصدار المكتبة المستخدم في هذه المقالة (1.2.0-beta01) بتقييد رؤية هذين الملفين ، لتثبيط توسيعهما أو تنفيذهما.

نتيجة لذلك ، على الرغم من أننا قد نجحنا في تجميع MonthRangeDateSelector الجديد الخاص بنا بنجاح ، فقد أظهر المترجم تحذيرًا مخيفًا للغاية لثنينا عن القيام بذلك:

تتمثل إحدى طرق إخفاء تحذير المترجم في إضافة @Suppress("RestrictedApi") مثل:

توضح هذه التجربة كيف أنه على الرغم من أن مكتبة المكونات المادية قد قدمت بعض المكونات الجديدة الرائعة لمجتمع مطوري Android ، إلا أنها لا تزال قيد التقدم.

جزء كبير من هذه المكتبة هو الانفتاح على التعليقات من مجتمع Android! بعد اكتشاف قيود رؤية هذا المكون ، فتحت مشكلة في مشروع Github ، وفتحت حتى العلاقات العامة لمعالجتها على الفور.

تولد حلقة التعليقات المفتوحة هذه بين فريق المكونات المادية ومجتمع Android تعاونًا رائعًا ونتائج للجميع.

استنتاج

يحتوي MaterialDatePicker الجديد على بعض الوظائف الرائعة خارج الصندوق والتي من المحتمل أن تغطي معظم حالات استخدام تحديد التاريخ.

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

شكر خاص

أود تسليط الضوء على بعض الأشخاص الذين ساعدوا الأقران في مراجعة هذه المقالة:

  • نيك روت (جيثب)
  • مايك ولفسون (جيثب)
  • ريان فيليبس (ينكدين)
  • لوكاس مويلرز (جيثب)
  • ميت باتيل (ينكدين)