إنشاء واجهات للساعات WearOS - الجزء الثاني
إنشاء واجهات Watch Face لساعات WearOS بإستخدام Watch Face Format (WFF)
سنستكمل في هذا الجزء شرح عن WFF لإنشاء واجهات Watch Face للساعات Wear OS.
سنشرح بعض العناصر في WFF
OutGlow
تقوم بإضافة توهج خارجي للنص
<PartText
x="0"
y="0"
width="450"
height="450">
<Text >
<Font family="rubik" size="30" color="#ffffffff">
<OutGlow color="#ff0000" radius="2">
Hello 3alam Pro!
</OutGlow>
</Font>
</Text>
</PartText>
بهذا الشكل

Outline
تقوم بإضافة خط خارجي "Stroke"
<PartText
height="450"
width="450"
x="0"
y="0">
<Text>
<Font
color="#ffffffff"
family="rubik"
size="30">
<Outline
color="#ff0000"
width="float">
Hello 3alam Pro!
</Outline>
</Font>
</Text>
</PartText>

Upper و Lower
تقوم بتحويل النص الى Uppercase و Lowercase
في هذا المثال قد لا يكون لها استخدام كبير, ولكن يمكنك تخيل استخدامها عند التعامل مع التطبيقات الأخرى او "Complications" التي توفر بيانات معينة مثل الطقس, البطارية, أوقات الصلاة وغيرها.
<PartText
height="450"
width="450"
x="0"
y="0">
<Text>
<Font
color="#ffffffff"
family="rubik"
size="30">
<Upper>
Hello 3alam Pro!
</Upper>
</Font>
</Text>
</PartText>

<PartText
height="450"
width="450"
x="0"
y="0">
<Text>
<Font
color="#ffffffff"
family="rubik"
size="30">
<Lower>
Hello 3alam Pro!
</Lower>
</Font>
</Text>
</PartText>

سنشرح الآن عن بعض العناصر الرسومية PartDraw
مثال
<PartDraw x="integer" y="integer" width="integer" height="integer"
name="string" angle="float-degrees" pivotX="float" pivotY="float"
alpha="integer"
renderMode="[SOURCE | MASK | ALL]"
tintColor="argb-color | rgb-color">
<!-- Only the most common inner element is shown here. -->
<Line />
...
</PartDraw>
Line
<PartDraw
height="450"
width="450"
x="0"
y="0">
<Line startX="100" startY="100" endX="200" endY="200" >
<Stroke
color="#ffffff"
thickness="3" />
</Line>
</PartDraw>

حيث أنه يمكننا وضع Stroke أو WeightedStroke
تستخدم لرسم مستطيل
يمكننا استخدام Fill لتعبئة المستطيل
<PartDraw
height="450"
width="450"
x="0"
y="0">
<Rectangle
height="100"
width="100"
x="200"
y="100">
<Fill color="#ff0000"/>
</Rectangle>
</PartDraw>

أو يمكننا إستخدام Stroke لرسم مستطيل Outlined بدون تعبئة
<PartDraw
height="450"
width="450"
x="0"
y="0">
<Line startX="100" startY="100" endX="200" endY="200" >
<Stroke
color="#ffffff"
thickness="3" />
</Line>
</PartDraw>

يستخدم لرسم مستطيل بحواف مدورة
<PartDraw
height="450"
width="450"
x="0"
y="0">
<RoundRectangle
height="100"
width="100"
x="200"
y="100" cornerRadiusX="5" cornerRadiusY="5">
<!-- <Fill color="#ff0000" />-->
<Stroke color="#ff0000" thickness="3"/>
</RoundRectangle>
</PartDraw>
يمكننا إستخدام Stroke or Fill

تستخدم لرسم دائرة
<PartDraw
height="450"
width="450"
x="0"
y="0">
<Ellipse
height="100"
width="100"
x="200"
y="100">
<Fill color="#ff0000" />
<!-- <Stroke color="#ff0000" thickness="3"/>-->
</Ellipse>
</PartDraw>
يمكنك استخدامها لرسم خط منحني , شخصياً قمت باستخدامها لرسم Progress Bar لموعد الصلاة القادم.
<PartDraw
height="450"
width="450"
x="0"
y="0">
<Arc
centerX="225"
centerY="225"
endAngle="180"
height="100"
startAngle="0"
width="100">
<Stroke
color="#ffffffff"
thickness="3" />
</Arc>
</PartDraw>

تستخدم لعرض صورة / صور
<PartImage
height="450"
width="450"
x="0"
y="0">
<Image resource="wallpaper_4" />
</PartImage>
يجب العلم أنه يجب وضع الصورة داخل res/drawable


تستخدم لعرض بيانات معينة الذي يقدمها النظام كإسم اليوم الحالي, التاريخ الحالي, نسبة البطارية, نبضات القلب وغيرها , بالإضافة الى بعض التطبيقات الأخرى ك Complications
<PartText
height="100"
width="450"
x="100"
y="100">
<Text>
<Font
color="#FFFFFF"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[DAY_OF_WEEK_S]" />
</Template>
</Font>
</Text>
</PartText>
<PartText
height="100"
width="450"
x="100"
y="200">
<Text>
<Font
color="#FFFFFF"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[BATTERY_PERCENT]" />
</Template>
</Font>
</Text>
</PartText>
في هذا المثال قمنا بوضع نصين, الأول لعرض إسم اليوم الحالي DAY_OF_WEEK_S
والآخر لعرض نسبة البطارية الحالية BATTERY_PERCENT
يمكنك رؤية Providers الموجودة في الرابط
بعد أن تعرفنا على "معظم" العناصر الموجودة في WFF سنقوم الآن بإضافة بعض التخصيصات بالنسبة للمستخدم, مثل تغيير اللون, الخلفية وغيره.
سيستطيع المستخدم تغيير هذه الإعدادات من خلال الساعة نفسها (من خلال الضغط المطول على الواجهة) ثم اختيار تخصيص او Customize
أو من خلال تطبيق الساعة على الهاتف مثل Galaxy Wearable
سنقوم بإضافة Toggle بسيط لإظهار او إخفاء نسبة البطارية
يجب علينا أولاً تعريف UserConfigurations والتي ستحتوي على كل الإعدادات التي سنستخدمها سواءً Boolean,Color,List, الخ..
<UserConfigurations>
<BooleanConfiguration
defaultValue="FALSE"
displayName="show_battery_percentage"
id="show_battery"
/>
</UserConfigurations>
وضعنا القيمة الإفتراضية FALSE
إسم العرض الذي سيظهر في الإعدادات , علماً أنه يجب وضع اسم key داخل strings.xml ك displayName
و ID
حيث أن UserConfigurations سيكون خارج <Scene>
<WatchFace
height="450"
width="450">
<Metadata
key="CLOCK_TYPE"
value="DIGITAL" />
<UserConfigurations>
<BooleanConfiguration
defaultValue="FALSE"
displayName="show_battery_percentage"
id="show_battery"
/>
</UserConfigurations>
<Scene>
<PartText
height="100"
width="450"
x="100"
y="100">
<Text>
<Font
color="#FFFFFF"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[DAY_OF_WEEK_S]" />
</Template>
</Font>
</Text>
</PartText>
<PartText
height="100"
width="450"
x="100"
y="200">
<Text>
<Font
color="#FFFFFF"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[BATTERY_PERCENT]" />
</Template>
</Font>
</Text>
</PartText>
</Scene>
</WatchFace>
ملاحظة: يجب التأكد من أن خيار
<Editable value="true" />
موجود داخل xml/watch_face_info.xml
نقوم بتشغيل التطبيق لنرى الخيار

الآن سنقوم بوضع الكود اللازم للتحقق من حالة هذا الإعداد, وبناء عليه سنضيف خيار البطارية
<BooleanConfiguration id="show_battery">
<BooleanOption id="TRUE">
<PartText
height="100"
width="450"
x="100"
y="200">
<Text>
<Font
color="#FFFFFF"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[BATTERY_PERCENT]" />
</Template>
</Font>
</Text>
</PartText>
</BooleanOption>
</BooleanConfiguration>
عند استخدام Configuration معين فإنه يجب علينا وضع BooleanConfiguration مع ID الخاص به
وثم تحديد القيمة التي نريد العمل عليه, مثلاً في حالة TRUE , سنقوم بوضع الPartText
ونفس الفكرة يمكن تطبيقها في حال كان الخيار غير مفعل FALSE
نقوم بتشغيل التطبيق

ColorConfiguration
سنقوم بوضع خيار للمستخدم لتغيير لون الخط عبر ColorConfiguration
<ColorConfiguration
defaultValue="0"
displayName="font_color"
id="font_color">
<ColorOption
id="0"
colors="#FFFFFF"
displayName="white"/>
<ColorOption
id="1"
colors="#FF0000"
displayName="red"/>
<ColorOption
id="2"
colors="#00FF00"
displayName="green"/>
<ColorOption
id="3"
colors="#0000FF"
displayName="blue"/>
</ColorConfiguration>
قمنا بوضع ColorConfiguration مع id الخاص ب defaultValue
وداخله الألوان الذي نريد إضافتها "ColorOption"
يمكننا استخدام عدة ألوان داخل colors لتعمل ك theme ونفصل بينهم بمسافة, ولكن لتبسيط الشرح وضعنا كل لون كخيار منفصل
سنقوم الآن بتغيير ألوان النصوص على حسب خيار المستخدم
<PartText
height="100"
width="450"
x="100"
y="100">
<Text>
<Font
color="[CONFIGURATION.font_color]"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[DAY_OF_WEEK_S]" />
</Template>
</Font>
</Text>
</PartText>
قمنا فقط بتغيير اللون من الأبيض "#ffffff" الى CONFIGURATION.font_color
ليصبح الملف كاملاً
<WatchFace
height="450"
width="450">
<Metadata
key="CLOCK_TYPE"
value="DIGITAL" />
<UserConfigurations>
<BooleanConfiguration
defaultValue="FALSE"
displayName="show_battery_percentage"
id="show_battery" />
<ColorConfiguration
defaultValue="0"
displayName="font_color"
id="font_color">
<ColorOption
id="0"
colors="#FFFFFF"
displayName="white"/>
<ColorOption
id="1"
colors="#FF0000"
displayName="red"/>
<ColorOption
id="2"
colors="#00FF00"
displayName="green"/>
<ColorOption
id="3"
colors="#0000FF"
displayName="blue"/>
</ColorConfiguration>
</UserConfigurations>
<Scene>
<PartText
height="100"
width="450"
x="100"
y="100">
<Text>
<Font
color="[CONFIGURATION.font_color]"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[DAY_OF_WEEK_S]" />
</Template>
</Font>
</Text>
</PartText>
<BooleanConfiguration id="show_battery">
<BooleanOption id="TRUE">
<PartText
height="100"
width="450"
x="100"
y="200">
<Text>
<Font
color="[CONFIGURATION.font_color]"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[BATTERY_PERCENT]" />
</Template>
</Font>
</Text>
</PartText>
</BooleanOption>
</BooleanConfiguration>
</Scene>
</WatchFace>
نقوم بتشغيل التطبيق

ListConfiguration
تستخدم للاختيار من عدة خيارات, سنستخدمها لوضع خلفية بين الخلفيات الموجودة في drawable
قمت بوضع عدة خلفيات في مجلد drawable

سنقوم بتعريف الخيارات على حسب عدد الخلفيات الموجودة
<ListConfiguration
id="wallpaper"
displayName="wallpaper"
defaultValue="0">
<ListOption id="0" />
<ListOption id="1" />
<ListOption id="2" />
<ListOption id="3" />
</ListConfiguration>
سنقوم الآن بعرض الخلفية بناءً على اختيار المستخدم
<ListConfiguration id="wallpaper">
<ListOption id="0">
<PartImage
height="450"
width="450"
x="0"
y="0">
<Image
resource="wallpaper_1" />
</PartImage>
</ListOption>
<ListOption id="1">
<PartImage
height="450"
width="450"
x="0"
y="0">
<Image
resource="wallpaper_2" />
</PartImage>
</ListOption>
<ListOption id="2">
<PartImage
height="450"
width="450"
x="0"
y="0">
<Image
resource="wallpaper_3" />
</PartImage>
</ListOption>
<ListOption id="3">
<PartImage
height="450"
width="450"
x="0"
y="0">
<Image
resource="wallpaper_4" />
</PartImage>
</ListOption>
</ListConfiguration>
يمكنك إعتبار الكود السابق ك "switch statement" , اذا كان الخيار رقم ١ اعرض الخلفية رقم ١, وهكذا...
نقوم بتشغيل التطبيق

تستخدم لعرض بيانات يقدمها النظام أو تطبيق معين ويمكن تخصيصها من قبل المستخدم لاختيار Complication الذي يريد
يوجد العديد من أنواع Complications , يمكنك رؤية التفاصيل في هذا الرابط
سنقوم بالتركيز على نوع COMPLICATION.TEXT في هذا المثال
<ComplicationSlot
name="left_complication"
displayName="Left Complication"
height="85"
slotId="2"
supportedTypes="SHORT_TEXT"
width="85"
x="100"
y="230">
<DefaultProviderPolicy
defaultSystemProvider="WATCH_BATTERY"
defaultSystemProviderType="SHORT_TEXT"
primaryProvider="EMPTY"
primaryProviderType="SHORT_TEXT" />
<BoundingOval
height="112"
outlinePadding="2"
width="112"
x="0"
y="0" />
<Complication type="SHORT_TEXT">
<PartText
height="50"
width="150"
x="0"
y="0">
<Text align="CENTER">
<Font
color="#ffffff"
family="rubik"
size="28"
slant="NORMAL"
weight="NORMAL">
<Upper>
<Template>%s
<Parameter expression="[COMPLICATION.TEXT]" />
</Template>
</Upper>
</Font>
</Text>
</PartText>
</Complication>
</ComplicationSlot>
لنشرح المثال السابق
أولاً قمنا بتعريف ComplicationSlot ووضعنا المعلومات المطلوبة , أهمها slotId و supportedTypes
ثم وضعنا DefaultProviderPolicy والذي سيقول للنظام أن هذه Complication بشكل إفتراضي ستقوم بعرض "نسبة البطارية" في حال المستخدم لم يقم بتغييرها
وبحسب نوع الComplication فإن كل Complication ستقدم Text و Title وقد تختلف من تطبيق لآخر
في حالتنا قمنا بوضع WATCH_BATTERY بشكل إفتراضي
كما يمكنك وضع Complication خاص بتطبيق معين اذا كان يقدم Complication
مثل:
com.devlomi.prayerwear/com.devlomi.prayerwatchface.complications.NextPrayerTimeLeftComplicationService
BoundingOval هي الدائرة التي ستظهر للمستخدم عند الدخول الى نافذة التخصيص

داخل Complication وضعنا PartText داخله Parameter
وقمنا بأخذ [COMPLICATION.TEXT] الذي يقدمه الComplication
الكود كاملا
<WatchFace
height="450"
width="450">
<Metadata
key="CLOCK_TYPE"
value="DIGITAL" />
<UserConfigurations>
<BooleanConfiguration
defaultValue="FALSE"
displayName="show_battery_percentage"
id="show_battery" />
<ListConfiguration
defaultValue="0"
displayName="wallpaper"
id="wallpaper">
<ListOption id="0" />
<ListOption id="1" />
<ListOption id="2" />
<ListOption id="3" />
</ListConfiguration>
<ColorConfiguration
defaultValue="0"
displayName="font_color"
id="font_color">
<ColorOption
colors="#FFFFFF"
displayName="white"
id="0" />
<ColorOption
colors="#FF0000"
displayName="red"
id="1" />
<ColorOption
colors="#00FF00"
displayName="green"
id="2" />
<ColorOption
colors="#0000FF"
displayName="blue"
id="3" />
</ColorConfiguration>
</UserConfigurations>
<Scene>
<PartText
height="100"
width="450"
x="100"
y="100">
<Text>
<Font
color="[CONFIGURATION.font_color]"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[DAY_OF_WEEK_S]" />
</Template>
</Font>
</Text>
</PartText>
<BooleanConfiguration id="show_battery">
<BooleanOption id="TRUE">
<PartText
height="100"
width="450"
x="100"
y="200">
<Text>
<Font
color="[CONFIGURATION.font_color]"
family="rubik"
size="30">
<Template>%s
<Parameter expression="[BATTERY_PERCENT]" />
</Template>
</Font>
</Text>
</PartText>
</BooleanOption>
</BooleanConfiguration>
<ComplicationSlot
name="left_complication"
displayName="Left Complication"
height="85"
slotId="2"
supportedTypes="SHORT_TEXT"
width="85"
x="100"
y="230">
<DefaultProviderPolicy
defaultSystemProvider="WATCH_BATTERY"
defaultSystemProviderType="SHORT_TEXT"
primaryProvider="EMPTY"
primaryProviderType="SHORT_TEXT" />
<BoundingOval
height="112"
outlinePadding="2"
width="112"
x="0"
y="0" />
<Complication type="SHORT_TEXT">
<PartText
height="50"
width="150"
x="0"
y="0">
<Text align="CENTER">
<Font
color="#ffffff"
family="rubik"
size="28"
slant="NORMAL"
weight="NORMAL">
<Upper>
<Template>%s
<Parameter expression="[COMPLICATION.TEXT]" />
</Template>
</Upper>
</Font>
</Text>
</PartText>
</Complication>
</ComplicationSlot>
</Scene>
</WatchFace>
نقوم بتشغيل التطبيق

بشكل إفتراضي قام بعرض نسبة البطارية
كما استطعنا تغيير النص من نسبة البطارية الى عدد الخطوات من خلال إعدادات الWatch Face
التعليقات (0)
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !