كيف يبدو النص الخاص بك؟

الأصدقاء ، عظيم كل الجمعة. نريد أن نطلعكم على ترجمة لمقال أعد خصيصًا لطلاب الدورة التدريبية "Android-developer. دورة متقدمة . " هل لديك قراءة جيدة.



كيفية التصريح على غرار النص على الروبوت.


فيرجينيا بولت التوضيح

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


ماذا ومتى تستخدم؟

توضح هذه المقالة الطرق المختلفة لتعريف النص بالنص التعريفي (أي عند تحديد الأنماط في ملف XML) ، تتناول نطاق كل أولوية وأولوية لها.

ليرة تركية ؛ د.


يجب أن تقرأ المنشور بالكامل ، ولكن إليك ملخص.

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


التسلسل الهرمي لطرق تصميم النص

أود أن أقترح الإجراء التالي للتصميم:

  1. قم بتعيين أي نمط تطبيق في textViewStyle كنمط افتراضي للموضوع الخاص بك.
  2. قم بتثبيت مجموعة (صغير) من TextAppearance التي TextAppearance تطبيقك (أو استخدمها / TextAppearance من أنماط MaterialComponent) ، وقم بالإشارة إليها مباشرة من طريقة العرض الخاصة بك
  3. قم بإنشاء style عن طريق تعيين سمات غير مدعومة بواسطة TextAppearance (والتي ستحدد بنفسها واحدة من TextAppearance الخاصة بك).
  4. أداء أي التصميم الفريد مباشرة في التخطيط.

عرض بعض الاسلوب


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

ماذا يحدث تحت الغطاء عندما ترتدي المنظر؟ إذا سبق لك أن كتبت طريقة العرض المخصصة الخاصة بك ، فمن المحتمل أن ترى الدعوة إلى context.obtainStyledAttributes (AttributeSet ، int [] ، int ، int) . وبالتالي ، ينتقل نظام العرض في Android إلى السمات المحددة في التخطيط. في الواقع ، يمكن اعتبار المعلمة AttributeSet بمثابة خريطة لمعلمات XML التي تحددها في تخطيطك. إذا عيّنت AttributeSet النمط ، فسيتم قراءة النمط أولاً ، ثم يتم تطبيق السمات المحددة مباشرة في العرض عليه. وبالتالي ، نأتي إلى القاعدة الأولى للأولوية.

عرض → النمط

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

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

TextAppearance


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

 TypedArray a = theme.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TextViewAppearance, defStyleAttr, defStyleRes); TypedArray appearance = null; int ap = a.getResourceId(com.android.internal.R.styleable.TextViewAppearance_textAppearance, -1); a.recycle(); if (ap != -1) { appearance = theme.obtainStyledAttributes(ap, com.android.internal.R.styleable.TextAppearance); } if (appearance != null) { readTextAppearance(context, appearance, attributes, false); appearance.recycle(); } // a little later a = theme.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes); readTextAppearance(context, a, attributes, true); 

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

عرض → نمط → TextAppearance

نظرًا لأن مظهر النص محددًا أولاً ، فإن أي سمات محددة إما مباشرة في العرض أو في النمط ستتخطاها.

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

obtainStyledAttributes(ap, android.R.styleable.TextAppearance);

نظرنا إلى إصدار receiveStyledAttributes مع 4 وسيطات ، وهذا الإصدار ذو الوسيطة مختلف قليلاً عنه. إنها تنظر إلى النمط المحدد (كما هو محدد بواسطة id المعلمة الأول) وتصفيته فقط وفقًا للسمات في النمط الذي يظهر في المعلمة الثانية ، صفيف attrs . android.R.styleable.TextAppearance styleable لذلك يحدد نطاق TextAppearance . بالنظر إلى هذا التعريف ، نرى أن TextAppearance يدعم العديد من TextAppearance ، ولكن ليس كلها ، التي يدعمها TextView .

 <attr name="textColor" /> <attr name="textSize" /> <attr name="textStyle" /> <attr name="typeface" /> <attr name="fontFamily" /> <attr name="textColorHighlight" /> <attr name="textColorHint" /> <attr name="textColorLink" /> <attr name="textAllCaps" format="boolean" /> <attr name="shadowColor" format="color" /> <attr name="shadowDx" format="float" /> <attr name="shadowDy" format="float" /> <attr name="shadowRadius" format="float" /> <attr name="elegantTextHeight" format="boolean" /> <attr name="letterSpacing" format="float" /> <attr name="fontFeatureSettings" format="string" /> 

سمات التصميم المدعومة من TextAppearance

فيما يلي بعض سمات TextView التي لم يتم تضمينها في TextAppearance : lineHeight[Multiplier|Extra] lines و breakStrategy و hyphenationFrequency . يعمل TextAppearance على مستوى الحرف ، وليس على مستوى الفقرة ، لذلك لا يتم دعم السمات التي تؤثر على التخطيط بأكمله.

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

افتراضات معقولة


عندما نظرنا إلى كيفية حل عرض Android للسمات ( context.obtainStyledAttributes ) ، قمنا بالفعل بتبسيطها قليلاً. تقوم بالاتصال بـ theme.obtainStyledAttributes (باستخدام Theme Context الحالي 'a). عند التحقق من الارتباط ، يتم عرض ترتيب الأولوية الذي درسناه سابقًا ، ويشار إلى مكانين آخرين بأنه يبحث عن حل السمات: النمط الافتراضي للعرض والموضوع.

عند تحديد القيمة النهائية لسمة معينة ، تدخل أربعة معلمات إدخال في الاعتبار:

  1. أي قيم سمة في مجموعة السمات هذه.
  2. مورد النمط المحدد في AttributeSet (المسمى "النمط").
  3. النمط الافتراضي المحدد بواسطة defStyleAttr و defstyleres
  4. القيم الأساسية في هذا الموضوع.

ترتيب أولوية التصميم من وثائق الموضوع

سنعود إلى السمات ، لكن دعونا نلقي نظرة على الأنماط الافتراضية أولاً. ما هو هذا النمط الافتراضي؟ للإجابة على هذا السؤال ، أعتقد أنه سيكون من المفيد أخذ خروج صغير من TextView وإلقاء نظرة على Button بسيط. عندما تقوم بإدخال < Button > في التخطيط الخاص بك ، فإنه يبدو مثل هذا.


زر قياسي

لماذا؟ إذا نظرت إلى الكود المصدري لـ Button ، فسترى أنه ضئيل إلى حد ما:

 public class Button extends TextView { public Button(Context context) { this(context, null); } public Button(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.buttonStyle); } public Button(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public CharSequence getAccessibilityClassName() { return Button.class.getName(); } @Override public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) { if (getPointerIcon() == null && isClickable() && isEnabled()) { return PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_HAND); } return super.onResolvePointerIcon(event, pointerIndex); } } 

هذا كل شئ! هنا هو الفصل بأكمله (لا تعليق). يمكنك التحقق من ذلك بنفسك هنا . سوف انتظر إذن ، من أين تأتي الخلفية ، الحروف الكبيرة ، التموج ، وما إلى ذلك؟ ربما تكون قد فاتتك ، ولكن سيتم تعريفها جميعًا في المنشئ باستخدام وسيطين ؛ واحد يسمى عندما يتم أخذ التخطيط من XML. هذه هي المعلمة الأخيرة التي تعرّف defaultStyleAttr في com.android.internal.R.attr.buttonStyle . هذا هو النمط الافتراضي ، والذي هو في الأساس نقطة مرجعية غير مباشرة ، مما يسمح لك بتحديد النمط الافتراضي. لا يشير مباشرة إلى النمط ، لكنه يسمح لك بالإشارة إلى أحد تلك المحددات في الموضوع الخاص بك والتي سوف يتحقق عند حل السمات. وهذا هو بالضبط ما تفعله كل المظاهر التي ترثها عادة لتوفير مظهر وأسلوب الحاجيات القياسية. على سبيل المثال ، إذا نظرت إلى موضوع المادة ، @style/Widget.Material.Light.Button ، وهذا النمط هو الذي يوفر جميع السمات التي theme.obtainStyledAttributes إذا لم تحدد أي شيء آخر.

عودة إلى TextView ، فإنه يوفر أيضًا نمطًا افتراضيًا: textViewStyle . قد يكون هذا مناسبًا للغاية إذا كنت تريد تطبيق بعض الأنماط على كل TextView في التطبيق الخاص بك. افترض أنك تريد ضبط تباعد الأسطر الافتراضي على 1.2. يمكنك القيام بذلك باستخدام style/TextAppearance ومحاولة تطبيقه أثناء مراجعة الكود (أو ربما مع وجود قاعدة مخصصة أنيقة في Lint) ، ولكن عليك أن تكون متيقظًا وتأكد من أنك تجند أعضاء جدد في الفريق. ، كن حذرا مع إعادة البناء ، الخ

TextView الطريقة الأفضل في تحديد النمط الافتراضي الخاص بك لجميع TextView في التطبيق ، وتحديد السلوك المطلوب. يمكنك القيام بذلك عن طريق تعيين النمط الخاص بك لـ textViewStyle ، الموروث من النظام الأساسي أو من MaterialComponents/AppCompat بشكل افتراضي.

 <style name="Theme.MyApp" parent="@style/Theme.MaterialComponents.Light"> ... <item name="android:textViewStyle">@style/Widget.MyApp.TextView</item></style> <style name="Widget.MyApp.TextView" parent="@android:style/Widget.Material.TextView"> <item name="android:textAppearance">@style/TextAppearance.MyApp.Body</item> <item name="android:lineSpacingMultiplier">@dimen/text_line_spacing</item> </style> 

مع وضع ذلك في الاعتبار ، تأخذ قاعدة أولوياتنا الشكل:

عرض -> نمط -> النمط الافتراضي -> TextAppearance

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

إذا ورثت عنصر واجهة المستخدم ولم تحدد النمط الافتراضي الخاص بك ، فتأكد من استخدام نمط الفئة الأصل الافتراضي في المنشئات (لا تتجاوز 0). على سبيل المثال ، إذا كنت ترث من AppCompatTextView وتكتب المنشئ الخاص بك باستخدام وسيطات ، تأكد من اجتياز android.R.attr.textViewStyle defaultStyleAttr ( كما هو هنا ) ، وإلا فسوف تفقد سلوك الفئة الأصل.

المواضيع


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

سيكون أحد الأمثلة عند محاولة تغيير الخط خلال التطبيق. يمكنك استخدام إحدى الطرق الموضحة أعلاه ، ولكن ضبط أنماط / مظهر النص يدويًا في كل مكان سيكون رتيباً وغير آمن ، ولن تعمل الأنماط الافتراضية إلا على مستوى عنصر واجهة المستخدم ؛ يمكن android:buttonStyle الفرعية تجاوز هذا السلوك ، على سبيل المثال ، تحدد الأزرار android:buttonStyle خاص بها android:buttonStyle ، والذي لن android:textViewStyle . بدلاً من ذلك ، يمكنك تحديد الخط في النسق الخاص بك:

 <style name="Theme.MyApp" parent="@style/Theme.MaterialComponents.Light"> ... <item name="android:fontFamily">@font/space_mono</item> </style> 

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

عرض → نمط → النمط الافتراضي → موضوع → TextAppearance

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

تذكر هذه الأولوية. في مثالنا مع وجود خط للتطبيق بالكامل ، يمكنك توقع Toolbar يلتقط Toolbar هذا الخط ، حيث أنه يحتوي على العنوان ، وهو TextView . ومع ذلك ، تحدد فئة شريط الأدوات نفسها نمطًا افتراضيًا يحتوي على titleTextAppearance ، والذي يحدد android:fontFamily ، android:fontFamily مباشرةً في رأس TextView ، متجاوزًا قيمة مستوى السمة. يمكن أن تكون أنماط مستوى الموضوع مفيدة ، ولكن من السهل تجاوزها ، لذلك تأكد من تطبيقها بشكل صحيح.

المكافأة: قضايا لم تحل


تم TextView هذه المقالة بالكامل للتصميم التعريفي للنص على مستوى العرض ، أي كيفية TextView بالكامل أثناء التعبئة. أي نمط يتم تطبيقه بعد التعبئة (على سبيل المثال ، textView.setTextColor(…) ) سيتجاوز التصميم التعريفي. TextView يدعم أيضا أنماط أصغر من خلال Span . لن أخوض في هذا الموضوع ، كما هو موضح بالتفصيل في المقالات التي كتبها فلورينا مونتينيسكو .

تصميم نص رائع مع Spans
يمتد إلى أسفل يمتد

سوف أذكر ذلك للتأكد من اكتماله ، لأضع في اعتبارك أن تصميم البرامج ومراحلها ستكون على رأس قائمة الأولويات:

Span → Setters → View → Style → النمط الافتراضي → Theme → TextAppearance

اختر طريقتك


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

هل لديك نص التصميم الجميل!

نحن ندعو الجميع إلى ندوة مجانية على الإنترنت والتي في إطارها سنتعرف على إطار عمل DI Dagger 2: سنقوم بدراسة كيفية قيام Dagger2 بإنشاء الكود ، وسنتعامل مع التعليقات التوضيحية JSR 330 وتصميمات Dagger2 ، وسنتعلم كيفية استخدام Dagger2 في تطبيق متعدد الوحدات وننظر في Dagger Android Injector.

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


All Articles