إنشاء مكوّنات العرض المخصّصة

تجربة طريقة ComposeAllowed
Jetpack Compose هي مجموعة أدوات واجهة المستخدم التي ننصح بها لنظام التشغيل Android. تعرَّف على كيفية استخدام التنسيقات في Compose.

يوفر Android نموذجًا متطورًا وقويًا مقسَّمًا إلى مكوّنات لإنشاء واجهة المستخدم، استنادًا إلى وفئات التخطيط الأساسية View و ViewGroup تتضمن المنصة مجموعة متنوعة من الفئات الفرعية التي تم إنشاؤها مسبقًا View وViewGroup، تُسمى التطبيقات المصغّرة على التوالي، والتي يمكنك استخدامها لإنشاء واجهة المستخدم الخاصة بك.

تشمل قائمة جزئية من التطبيقات المصغّرة المتاحة Button، TextView, EditText, ListView, CheckBox, RadioButton, Gallery, Spinner، والأهداف الخاصة AutoCompleteTextView, ImageSwitcher، TextSwitcher.

من بين التخطيطات المتاحة LinearLayout, FrameLayout, RelativeLayout, وغير ذلك لمزيد من الأمثلة، راجع التنسيقات الشائعة:

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

ويمنحك إنشاء فئات View الفرعية إمكانية تحكُّم دقيق في مظهر التطبيق لوظيفة عنصر الشاشة. لتقديم فكرة عن عنصر التحكم الذي تحصل عليه في طرق العرض المخصصة، إليك ما يلي: إليك بعض الأمثلة حول ما يمكنك فعله باستخدامها:

  • يمكنك إنشاء نوع View معروض مخصّص بالكامل، مثل "مجلد التحكم" مقبض، معروض باستخدام رسومات ثنائية الأبعاد، يشبه التحكم الإلكتروني التناظري.
  • يمكنك دمج مجموعة من مكوّنات View في مكوّن واحد جديد، ربما إنشاء شيء مثل مربع التحرير والسرد (مزيج من القائمة المنبثقة وحقل نص الإدخال المجاني)، عنصر تحكّم ثنائي اللوحة (جزء أيمن ويمين يحتوي على قائمة في كل قسم يمكنك إعادة تحديده) والعنصر في كل قائمة) وهكذا.
  • يمكنك إلغاء طريقة عرض مكوّن EditText على الشاشة. تشير رسالة الأشكال البيانية يستخدم نموذج تطبيق NotePad هذا الخيار لتحقيق تأثير جيد لإنشاء صفحة مفكرة مسطرة.
  • يمكنك تسجيل أحداث أخرى، مثل الضغطات على المفاتيح، والتعامل معها بطريقة مخصّصة، مثل وكذلك في اللعبة.

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

تم تحديد النهج الأساسي

إليك نظرة عامة شاملة على المعلومات التي تحتاج إلى معرفتها لإنشاء "View" الخاص بك. المكونات:

  1. يمكنك تمديد صف أو فئة فرعية حالية View من خلال صفك الخاص.
  2. تجاوز بعض الطرق من الفئة الفائقة. تبدأ طرق الفئة الفائقة المراد تجاوزها on - على سبيل المثال، onDraw(), onMeasure(), أو onKeyDown() هذا مماثل لفعاليات on في Activity أو ListActivity الذي تجاوز مراحل النشاط والعناصر الأخرى للوظائف.
  3. استخدِم فئة الإضافات الجديدة. وبعد الانتهاء، يمكنك استخدام فئة الإضافة الجديدة بدلاً من طريقة العرض التي استند إليها.

مكونات مخصصة بالكامل

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

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

لإنشاء مكوِّن مخصص بالكامل، ضع في اعتبارك ما يلي:

  • العرض الأكثر عمومية الذي يمكنك تمديده هو View، لذا تبدأ عادةً بتمديد. هذا لإنشاء المكون المميز الجديد.
  • ويمكنك توفير دالة إنشائية يمكنها أخذ السمات والمعلمات من XML، كما يمكنك مثل هذه السمات والمعلمات الخاصة بك، مثل لون ونطاق مقياس VU أو عرض الإبرة وتخميدها.
  • ربما تحتاج إلى إنشاء أدوات معالجة الأحداث، وعناصر الوصول إلى المواقع، والمعدِّلات الخاصة بك، بالإضافة إلى سلوك أكثر تعقيدًا في فئة المكونات.
  • أنت على الأرجح تريد إلغاء onMeasure() ومن المحتمل أيضًا أن تحتاج إلى تلغي onDraw() إذا كنت تريد أن يعرض المكون شيئًا ما. بينما يتمتع كلاهما ويكون الوضع التلقائي هو onDraw() التلقائي لا يفعل أي شيء، كما أن تضبط onMeasure() دائمًا الحجم 100x100، وهو ما قد لا تريده على الأرجح.
  • يمكنك أيضًا إلغاء طُرق on الأخرى، حسب الحاجة.

Extend onDraw() وonmeasure()

توفّر الطريقة onDraw() Canvas التي يمكنك تنفيذ أي شيء تريده: الرسومات ثنائية الأبعاد، أو مكونات قياسية أو مخصصة أخرى، أو النصوص ذات النمط، أو أي شيء آخر يخطر على بالك.

onMeasure() يشارك أكثر قليلاً. onMeasure() جزء مهم من عقد العرض بين المكوِّن وحاويةه. يجب أن يكون onMeasure() يتم تجاوزها للإبلاغ بكفاءة ودقة عن قياسات الأجزاء المضمّنة فيها. هذا هو جعلت هذه المتطلبات أكثر تعقيدًا بعض الشيء بسبب متطلبات الحد التي تفرضها المؤسسة الرئيسية، والتي يتم تمريرها إلى onMeasure()—ومن خلال مطلب استدعاء setMeasuredDimension() بالعرض والارتفاع اللذين تم قياسهما بعد الحساب. إذا لم يتم استدعاء هذه الطريقة من طريقة onMeasure() تم تجاوزها، فإنها إلى حدوث استثناء في وقت القياس.

على مستوى عالٍ، يبدو تنفيذ onMeasure() على النحو التالي:

  • يتم استدعاء طريقة onMeasure() التي تم تجاوزها باستخدام العرض والارتفاع والمواصفات، والتي يتم التعامل معها كمتطلبات للقيود المفروضة على العرض والارتفاع القياسات التي تنتجها. widthMeasureSpec وheightMeasureSpec المَعلَمتان هما رمزا أعداد صحيحة يمثّلان الأبعاد. إن الإشارة الكاملة إلى نوع القيود التي يمكن أن تتطلبها هذه المواصفات في الوثائق المرجعية تحت View.onMeasure(int, int) وتشرح هذه المستندات المرجعية أيضًا عملية القياس بالكامل.
  • تحسب طريقة onMeasure() الخاصة بالمكوّن قيمة عرض القياس وارتفاعه، والتي تكون مطلوبة لعرض المكوِّن. يجب أن يحاول الالتزام بالمواصفات التي تم تمريرها على الرغم من أنه يمكن أن يتجاوزها. في هذه الحالة، يمكن للآباء اختيار ما يجب القيام به، بما في ذلك والاقتصاص أو التمرير أو طرح استثناء أو طلب إعادة المحاولة من onMeasure() وربما بمواصفات قياس مختلفة.
  • عند حساب العرض والارتفاع، يمكنك استدعاء دالة الرسم طريقة setMeasuredDimension(int width, int height) مع العملية المحسوبة القياسات. ويؤدي عدم تنفيذ هذا الإجراء إلى الحصول على استثناء.

في ما يلي ملخّص للطرق العادية الأخرى التي يستدعيها إطار العمل لعدد المشاهدات:

الفئة الطرق الوصف
الإنشاء الشركات المصنِّعة هناك شكل من أشكال الدالة الإنشائية يتم استدعاؤه عند إنشاء طريقة العرض من التعليمة البرمجية ونموذج يتم استدعاؤه عند تضخيم العرض من ملف تخطيط. النموذج الثاني في تحليل وتطبيق السمات المحددة في ملف التخطيط.
onFinishInflate() يتم استدعاؤه بعد رؤية كل العناصر المرئية وكل عناصرها الثانوية من ملف XML.
التنسيق onMeasure(int, int) تم استدعاء هذا الإجراء لتحديد متطلبات الحجم لطريقة العرض هذه وجميع عناصرها الثانوية.
onLayout(boolean, int, int, int, int) يتم استدعاء هذا الإجراء عندما يجب أن تحدِّد طريقة العرض هذه حجمًا وموضعًا لكل عناصرها الثانوية.
onSizeChanged(int, int, int, int) يتم استدعاء هذا الإجراء عند تغيير حجم طريقة العرض هذه.
رسم onDraw(Canvas) يتم استدعاء عندما يجب أن تعرض طريقة العرض المحتوى.
معالجة الأحداث onKeyDown(int, KeyEvent) يتم استدعاء عند وقوع حدث رئيسي.
onKeyUp(int, KeyEvent) يتم استدعاء هذا الإجراء عند وقوع حدث رئيسي.
onTrackballEvent(MotionEvent) يتم استدعاء عند حدوث حدث حركة كرة تعقب.
onTouchEvent(MotionEvent) يتم استدعاء هذا الإجراء عند حدوث حركة شاشة تعمل باللمس.
التركيز onFocusChanged(boolean, int, Rect) يتم استدعاء هذا الإجراء عند زيادة التركيز أو فقدانه في المشاهدة.
onWindowFocusChanged(boolean) يتم استدعاء عندما تكتسب النافذة التي تحتوي على طريقة العرض التركيز أو تفقد التركيز.
جارٍ الإرفاق onAttachedToWindow() يتم استدعاء هذا الإجراء عند تثبيت طبقة العرض بنافذة.
onDetachedFromWindow() يتم استدعاء هذا الإجراء عند فصل العرض عن نافذته.
onWindowVisibilityChanged(int) يتم استدعاء هذه الوظيفة عند تغيير مستوى رؤية النافذة التي تحتوي على طريقة العرض.

عناصر التحكم المركبة

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

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

لإنشاء مكون مركب، قم بما يلي:

  • كما هي الحال في Activity، يجب استخدام أسلوب البيان (المستند إلى XML) لإنشاء المكونات المضمنة أو دمجها آليًا من التعليمات البرمجية الخاصة بك. تشير رسالة الأشكال البيانية نقطة البداية المعتادة هي Layout من نوع ما، لذا أنشئ فئة تُوسّع نطاق Layout في حالة مربع التحرير والسرد، يمكنك استخدام LinearLayout مع الاتجاه الأفقي. يمكنك تضمين التخطيطات الأخرى بالداخل، بحيث يمكن تحويل ومعقدة بشكل عشوائي.
  • في الدالة الإنشائية للفئة الجديدة، خذ أي معلمات تتوقعها الفئة الفائقة وقم بتمريرها وصولاً إلى الدالة الإنشائية للفئة الفائقة أولاً. بعد ذلك، يمكنك إعداد طرق العرض الأخرى لاستخدام داخل المكون الجديد. هذا هو المكان الذي تنشئ فيه الحقل EditText القائمة المنبثقة. يمكنك تقديم السمات والمعلمات الخاصة بك في XML الذي يمكن للدالة الإنشائية السحب والاستخدام.
  • يمكنك اختياريًا إنشاء أدوات معالجة الأحداث للأحداث التي قد تنشئها طرق العرض المتضمّنة. من الأمثلة على ذلك المستمع إلى عنصر قائمة النقر على أداة استماع لتحديث محتويات EditText في حال اختيار قائمة.
  • يمكنك اختياريًا إنشاء مواقعك الإلكترونية باستخدام أدوات ربط ومفاتيح تعديل. على سبيل المثال، دع يتم ضبط قيمة EditText مبدئيًا في المكوِّن وطلب البحث عن محتواه عند احتاجت.
  • يمكنك اختياريًا إلغاء onDraw() وonMeasure(). لا يكون هذا عادةً ضروريًا عندما توسيع Layout، لأنّ التنسيق يتضمّن سلوكًا تلقائيًا يعمل على الأرجح بشكلٍ جيد.
  • يمكنك اختياريًا إلغاء طُرق on الأخرى، مثل onKeyDown()، لاختيار طرق معيّنة مثلاً. القيم الافتراضية من القائمة المنبثقة لمربع التحرير والسرد عند النقر على مفتاح معين.

هناك مزايا لاستخدام Layout كأساس لعنصر تحكم مخصص، بما في ذلك ما يلي:

  • يمكنك تحديد التنسيق باستخدام ملفات XML التعريفية، كما هو الحال مع شاشة النشاط، أو يمكنك إنشاء طرق عرض آليًا ودمجها في التنسيق من الرمز البرمجي.
  • الطريقتان onDraw() وonMeasure()، بالإضافة إلى معظم الطرق الأخرى تشتمل طرق on على سلوك مناسب، لذا لا حاجة إلى تجاوزها.
  • يمكنك سريعًا إنشاء طرق عرض معقدة بشكل عشوائي وإعادة استخدامها كما لو كانت مكون واحد.

تعديل نوع عرض حالي

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

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

استورِد نموذج NotePad إلى "استوديو Android" إذا لم يسبق لك فعل ذلك أو اطّلِع على المصدر باستخدام الرابط المقدم. وعلى وجه التحديد، يمكنك الاطّلاع على تعريف LinedEditText. في NoteEditor.java الملف.

إليك بعض الأشياء التي يجب مراعاتها في هذا الملف:

  1. التعريف

    يتم تحديد الفئة بالسطر التالي:
    public static class LinedEditText extends EditText

    يتم تعريف LinedEditText كفئة داخلية ضمن NoteEditor نشاط، ولكنه متاح للجميع بحيث يمكن الوصول إليه على هيئة NoteEditor.LinedEditText من خارج الصف NoteEditor.

    إضافةً إلى ذلك، قيمة LinedEditText هي static، ما يعني أنّها لا تنشئ ما يُعرف باسم "الأساليب الاصطناعية" تسمح له بالوصول إلى البيانات من الفئة الأصل. هذا يعني أنه يعمل كفئة منفصلة وليس كشيء مرتبط ارتباطًا وثيقًا بـ NoteEditor. تعد هذه طريقة أنظف لإنشاء فئات داخلية إذا لم تكن بحاجة إلى الوصول إلى الحالة من الفئة الخارجية. تُبقي الفئة التي تم إنشاؤها صغيرة الحجم وتسمح باستخدامها بسهولة من الصفوف.

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

  2. إعداد الصف

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

  3. الطرق التي تم إلغاؤها

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

    في هذا النموذج، يتيح إلغاء طريقة onDraw() رسم الخطوط الزرقاء على لوحة عرض EditText. يتم تمرير اللوحة إلى الجزء الذي تم تجاوزه طريقة onDraw(). يتم استدعاء طريقة super.onDraw() قبل نهاية الطريقة. يجب استدعاء طريقة الطبقة الفائقة. في هذه الحالة، استحضرها في النهاية بعد في رسم الخطوط التي تريد تضمينها.

  4. المكوِّن المخصّص

    لديك الآن المكون المخصص، ولكن كيف يمكنك استخدامه؟ في مثال NotePad، بشكل مباشر من التخطيط التعريفي، لذا انظر إلى note_editor.xml في res/layout المجلد:

    <view xmlns:android="http://schemas.android.com/apk/res/android"
        class="com.example.android.notepad.NoteEditor$LinedEditText"
        android:id="@+id/note"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:padding="5dp"
        android:scrollbars="vertical"
        android:fadingEdge="vertical"
        android:gravity="top"
        android:textSize="22sp"
        android:capitalize="sentences"
    />
    

    يتم إنشاء المكوِّن المخصص كطريقة عرض عامة في XML، ويتم تحديد الفئة باستخدام الحزمة الكاملة. تتم الإشارة إلى الفئة الداخلية التي تحددها باستخدام NoteEditor$LinedEditText، وهي طريقة عادية للإشارة إلى البيانات الداخلية دروسًا في لغة البرمجة Java.

    إذا لم يتم تعريف مكوّن طريقة العرض المخصّصة كفئة داخلية، يمكنك التعريف بطريقة العرض. باسم عنصر XML واستثناء السمة class. بالنسبة مثال:

    <com.example.android.notepad.LinedEditText
      id="@+id/note"
      ... />
    

    يُرجى العلم أنّ الفئة LinedEditText أصبحت الآن ملف صف منفصل. عندما تم دمج الفئة في الفئة NoteEditor، ولا يمكن استخدام هذه الطريقة.

    السمات والمعلمات الأخرى في التعريف هي تلك التي يتم تمريرها إلى على النحو المنشود، ثم تم تمريرها إلى الدالة الإنشائية EditText، وهما المعلَمات نفسها التي تستخدمها لملف شخصي EditText. من الممكن إضافة المعلمات الخاصة بك أيضًا.

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

ويمكن للمكوِّن الأكثر تطورًا إلغاء المزيد من طُرق on وتقديم بطرق مساعدة خاصة، ما يؤدي إلى تخصيص خصائصه وسلوكه إلى حد كبير. الحد الوحيد هو خيالك وما تحتاج إلى المكون للقيام به.