ثيمات التطبيق في Jetpack Compose
- الجزء الأول: القوائم باستخدام LazyColumn في Jetpack Compose
- الجزء الثاني: ثيمات التطبيق في Jetpack Compose
تعد الثيمات جزءًا أساسيًا من هوية أي تطبيق لأنها توفر تجربة مستخدم فريدة، سأشرح في هذه التدوينة كيف تحقق هذا الهدف باستخدام Jetpack Compose وهي مجموعة أدوات جديدة لبناء عناصر واجهة المستخدم في أندرويد.
بناءً على تجربتي مع Compose، فهو يساعد بشكل ملحوظ على تقليل وقت تطوير واجهات المستخدم، ويمكّننا من استخدام عناصر واجهات المستخدم المعرّفة من قِبل Material Design من خلال APIs عامة وجاهزة للاستخدام.
سيكون تركيزنا في هذه التدوينة على “MaterialTheme” والتي تحتوي على نظم الألوان، والثيم الليلي والنهاري، ونظم الكتابة والخطوط، ونظم الأشكال.
في حال أردتم قراءة هذه التدوينة باللغة الإنجليزية، فهي موجودة على هذا الرابط.
الخطوة 4: الثيم الأساسي
الثيم الأساسي هو الثيم الافتراضي لجميع تطبيقات أندرويد، ويمكن تخصيص مدخلاته لمنح تطبيقك تجربة فريدة خاصة به.
في الثيم الأساسي، لدينا الألوان الافتراضية وتتكون من لون أساسي وهو البنفسجي، ولون ثانوي وهو التركوازي، مع درجات مختلفة لكل من الثيم الليلي/الداكن والنهاري/الفاتح.
الصورة أدناه من Material Design توضّح الألوان الافتراضية في الثيم الأساسي.
ومن ناحية النصوص فالخط الافتراضي هو خط Roboto، كما يظهر في الصورة أدناه من Material Design.
أما في الأشكال فلدينا أشكال شبه دائرية الزوايا بمقدار 4 dp، كما هو موضّح في الصورة أدناه حسب Material Design
في الثيم الأساسي هناك نوعان من الثيمات الليلي/الداكن والنهاري/الفاتح، وفي كلاهما تختلف حدة الألوان.
انظر إلى الصورة أدناه من Material Design لرؤية الألوان الافتراضية الثيم الليلي و الثيم النهاري:
ملاحظة: الآن، بعد الإعلان عن Material You، تغيّر الثيم الأساسي من ألوان ثابتة إلى ألوان ديناميكية مؤثرة بشكل كبير على تجربة مستخدمي ومطوري أندرويد، ويجب التنويه على أن معظم ما ورد أعلاه لا ينطبق على Material You.
كما نرى أدناه، ثيم تطبيق النباتات هو الثيم لأساسي، وسنعمل خلال هذه التدوينة على تغيير ذلك.
الخطوة 5: نظام الألوان
في جميع التطبيقات لدينا نظام لونيّ يتكون من مجموعة ألوان متناغمة تعطي التطبيق مظهرًا مميزًا. يتكون نظام الألوان من لون أساسي، ولون ثانوي، وألوان أخرى لخلفيات الأسطح في بعض العناصر والخلفية العامة للتطبيق، ولون لتوضيح الخطأ.
في الثيم النهاري/الفاتح تكون الألوان واضحة ومشرقة، وفي الثيم الليلي/الداكن تكون الألوان هادئة ومريحة لتقليل إجهاد العين.
لمساعدتكم على اختيار الألوان والدرجات المناسبة لتطبيقكم استخدموا هذه الأداة من Material Design تولّد الدرجات المعينة لكل ثيم حسب الألوان المختارة.
val teal700 = Color(0xFF00796B)
يستخدم Jetpack Compose أكواد الألوان الست عشرية (Hexadecimal) لتعريف الألوان، لكن نستبدل علامة المربع # بـ 0x يعرف الـ complier أن هذه القيمة هي قيمة لون معين.
بعد ذلك تأتي خانتين مسؤولتين عن مقدار شفافية اللون في السطر البرمجي أعلاه استخدمنا FF وهذا يعني لون معتم شفافيته 100٪.
بعد ذلك تأتي ستة أرقام وهي أكواد الألوان الست عشرية مكونة من رقمين لكل من الأحمر ثم الأخضر ثم الأزرق.
هذا رابط مفيد لتدوينة ديفيد والش فيها جدول لكل رمز شفافية مع النسبة المئوية المقابلة له، حيث يُستبدل رمز “FF” بأي رمز مذكور في الجدول بناءً على الشفافية المطلوبة.
فلنبدأ الآن بتخصيص ثيم تطبيق النباتات الذي عملنا عليه سابقاً في الجزء الأول، لنبدأ بتغيير الألوان أولاً. سوف نستخدم في الغالب درجات مختلفة من اللون الأخضر.
Color.kt
اذهب إلى مجلّد theme تحت اسم تطبيقك في أندرويد ستوديو، ثم افتح ملف color.kt واضف هذين السطرين لتعريف هذين اللونين في تطبيقنا:
val teal700 = Color(0xFF00796b)
val tealDark = Color(0xFF004c40)
بعد القيام بذلك، لن يتغير شيء من الألوان في تطبيقنا لأننا ما زلنا نشير إلى الألوان القديمة المعرفّة مسبقًا، ولتغيير ذلك، نحتاج إلى تعديل ملف theme.kt.
الخطوة 6: الثيمات المختلفة
بالنسبة لثيم تطبيقنا، سنعرّف لون أخضر داكن كلون بديل أساسي (primary variant color)، ولون أخضر أفتح منه بدرجتين كلون أساسي (primary color).
دعونا نلقي نظرة على مجموعة الألوان في ملف theme.kt.
Theme.kt
هناك مجموعتان مختلفتان من الألوان الداكنة والألوان الفاتحة، وتم تعيين قيم الباراميترات في كليهما على القيم الافتراضية التي ذكرناها في الثيم الأساسي.
في Jetpack Compose يمكننا استخدام ألوان محددة مسبقًا تشمل الأسود، والرمادي الداكن، والرمادي، والرمادي الفاتح، والأبيض، والأحمر، والأخضر، والأزرق، والأصفر، والسماوي، والأرجواني واللون الشفاف/بلا لون.
بالنسبة لمجموعة الألوان:
- سيتم استخدام اللون الأساسي (primary color) لشريط عنوان التطبيق (app bar).
- سيتم استخدام اللون البديل الأساسي (primary variant) لشريط الحالة (status bar).
- سيتم استخدام لون الخلفية (background color) لخلفية التطبيق ككل.
- سيتم استخدام لون السطح (surface color) لبطاقات النباتات.
- سيتم استخدام لون “على اللون الأساسي” (onPrimary color) للنص المكتوب على أي عنصر يستخدم اللون الأساسي.
private val DarkColorPalette = darkColors(
primary = teal700,
primaryVariant = tealDark,
background = Color.DarkGray,
surface = Color.DarkGray,
onPrimary = Color.White,
)
private val LightColorPalette = lightColors(
primary = teal700,
primaryVariant = tealDark,
onPrimary = Color.White,
)
يمكنك ملاحظة دالة (function) باسم تطبيقك أسفل تعريف مجموعتيّ الألوان الداكنة والفاتحة، تأخذ هذه الوظيفة باراميترين -يمكن تغييرهما وتخصيصهما بشكل أكبر -.
الباراميتر الأول يُسمّى “darkTheme” من نوع Boolean لقراءة ما إذا كان تم تفعيل الثيم الليلي/الداكن في نظام أندرويد، أما الباراميتر الثاني فيأخذ دالة قابلة للتكوين تُسمى “content” تمثّل محتوى التطبيق.
داخل هذه الدالة، قمنا بتعريف لون التطبيق حسب قراءة قيمة الـ darkTheme فإذا كانت القيمة true نعين الألوان على مجموعة الألوان الداكنة، وإذا كانت false نعينها على مجموعة الألوان الفاتحة، وتغيير هذه القيم يفرض إعادة تكوين لهذه الدالة بجميع مايحويها حسب المعطيات الجديدة الممرّرة لها.
بعد ذلك، يمكننا رؤية MaterialTheme() وهوا API عام جزء من Jetpack Compose، وهو مسؤول عن ثيم التطبيق بالكامل، ويأخذ قيم الألوان والنصوص والأشكال والمحتوى كباراميترات.
أما بالنسبة للمحتوى content، فهو محدد في ملف الـ MainActivity.kt.
MainActivity.kt
بقي خطوة واحدة قبل تشغيل تطبيقنا، وهي ضبط لون شريط الحالة ليأخذ لأخذ اللون البديل الأساسي -الذي حددناه سابقًا- عن طريق إضافة هذا السطر داخل دالة الثيم في ملف MainActivity.kt:
CosmeticsPlantsTheme {
window.statusBarColor = MaterialTheme.colors.primaryVariant.toArgb()
…
}
والآن نشغل التطبيق ونرى التغييرات الحاصلة، مظهر تطبيقنا سيكون كالتالي
الخطوة 7: نظام النصوص
ملاحظة: موقع مطوري أندرويد الرسمي يصرّح أن Jetpack Compose يدعم الخطوط التي تأتي بصيغة ttf. ولا يدعم الخطوط القابلة للتنزيل (downloadable fonts).
إضافة الخطوط إلى تطبيقك
من خلال مدير الموارد (resource manager)
اذهب إلى مدير الموارد (resource manager) في أندرويد ستوديو، ثم اضغط على الثلاث نقاط في أعلى اليسار واختر الخط Font.
بعد ذلك, سيتم فتح مساحة أو tab للخط، بعدها اضغط على زر الإضافة (+) لإضافة المزيد من الخطوط. ستظهر قائمة بالخطوط لاختيار الخطوط من هناك.
ابحث عن اسم الخط الأول “caveat” وتأكد من تغيير خيار الخط إلى “إضافة خط إلى التطبيق” (Add font to project) لأن الخطوط القابلة للتنزيل غير مدعومة كما ذكرنا.
من مصدر خارجي
لنقم بتنزيل الخط الثاني الذي يُسمى “Barlow Condensed” من Google Fonts، ثم قم بفك ضغط الملف الذي تم تنزيله وقم بتغيير أسماء الملفين خط light وخط regular بصيغة .ttf إلى اسم جديد خالٍ من المسافات والأحرف الكبيرة.
بعد إتمام الخطوة السابقة ذلك، اسحب ملفيّ الخطين السابقين - light و regular - إلى مجلد الخطوط (font) في مجلد res في برنامج أندرويد ستوديو.
الآن ، نحن جاهزون للخطوة التالية وهي استخدام تلك الخطوط في ملف Type.kt.
Type.kt
داخل هذا الملف، نحتاج إلى تحديد عائلة الخطوط لكل خط أضفناه، الدالة FontFamily تأخذ قائمة من نفس الخط بأوزان مختلفة السماكة حتى تحمّل مايقابله من خط في ملف الـ res.
بالنسبة إلى خط Caveat، فنحن قمنا بتنزيل الخط العادي (regular)، لذا سيكون الوزن هو FontWeight.Normal. بالنسبة إلى خط Barlow، فنحن قمنا بتنزيل الخط العادي والـ light سيكون الوزن لكل منهما FontWeight.Normal و FontWeight.Light تباعاً.
سيكون كودك كالتالي:
private val Caveat = FontFamily(
Font(R.font.caveat, FontWeight.Normal)
)
private val Barlow = FontFamily(
Font(R.font.barlow_condensed_light, FontWeight.Light),
Font(
R.font.barlow_condensed_regular, FontWeight.Normal
)
)
الآن عرّفنا عائلة الخطوط دون استخدامها، لاستخدامها نحتاج إلى الإشارة إليها من داخل دالة TextStyle(). في تطبيق النباتات، أنواع النصوص المعروضة هي h1 و h2 و body2.
الكود أدناه يشير إلى عائلة الخطوط التي عرّفناها مسبقاً، ووزن الخط، وحجم الخط، ومحاذاة النص:
// Set of Material typography styles to start with
val Typography = Typography(
h1 = TextStyle(
fontFamily = Barlow,
fontWeight = FontWeight.Light,
fontSize = 30.sp,
textAlign = TextAlign.Center
),
h2 = TextStyle(
fontFamily = Caveat,
fontWeight = FontWeight.Normal,
fontSize = 20.sp,
textAlign = TextAlign.Center
),
body2 = TextStyle(
fontFamily = Barlow,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
textAlign = TextAlign.Left
),
)
هذا ما ستراه عند تشغيل التطبيق، نتيجة رائعة لكنها ستكون أفضل إذا عدّلنا شكل البطاقات.
الخطوة 8: نظام الأشكال
اذهب إلى ملف Shape.kt لترى القيم الافتراضية لنظام الأشكال، وهي نفسها القيم الافتراضية للثيم الأساسي.
Shape.kt
قم بتغيير قيمة الشكل المتوسط medium لتأخذ مستطيلاً بزاوية دائرية فقط من أعلى اليمين، كالتالي:
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(topEnd = 25.dp),
large = CutCornerShape(topStart = 50.dp)
)
نشغّل التطبيق لنرى النتيجة النهائية لتطبيقنا مع ثيمنا الخاص والفريد.
النتيجة
هذا هو التطبيق النهائي في الثيم الليلي/الداكن و النهاري/الفاتح.
🔗 التطبيق كاملاً على GitHub.
الخاتمة
في هذه التدوينة، أكملنا بناء تطبيقنا الذي يعرض النباتات المستخدمة في مستحضرات التجميل.
أثناء عمل ذلك، تعلمنا ما هو الثيم الأساسي، وذكرنا ملاحظات مهمة حول الثيم الليلي/الداكن والثيم النهاري/ الفاتح، ونظام الألوان، ونظام النصوص، ونظام الأشكال.
إذا كان هذا مفيدًا لك ، فيرجى مشاركة وإظهار الدعم!
🍀 في حال ساعدتك هذه التدوينة على تعلم شيء جديد، فيُرجى مشاركتها ودعمي لكتابة المزيد.