סגנונות ועיצובים

כדאי לנסות את התכונה 'כתיבה מהירה'
'Jetpack פיתוח נייטיב' היא ערכת הכלים המומלצת לממשק המשתמש ל-Android. איך עובדים עם עיצוב נושאים ב-Compose

סגנונות ועיצובים ב-Android מאפשרים להפריד את הפרטים של עיצוב האפליקציה מהמבנה וההתנהגות של ממשק המשתמש, בדומה לגיליונות ראשיים בעיצוב אתרים.

style הוא אוסף של מאפיינים שמציינים את המראה של View יחיד. סגנון יכול לציין מאפיינים כמו צבע הגופן, גודל הגופן, צבע הרקע ועוד הרבה.

עיצוב הוא אוסף של מאפיינים שחלים על האפליקציה, הפעילות או היררכיית התצוגה כולה, ולא רק על תצוגה בודדת. כשמחילים עיצוב, כל תצוגה באפליקציה או בפעילות מחילה את כל המאפיינים של העיצוב שתומכים בה. עיצובים יכולים להחיל סגנונות גם על רכיבים שלא מיועדים לתצוגה, כמו שורת הסטטוס ורקע החלון.

הכרזות על סגנונות ועיצובים נמצאות בקובץ משאב של סגנון ב-res/values/, בדרך כלל בשם styles.xml.

איור 1. שני עיצובים שהוחלו על אותה פעילות: Theme.AppCompat (שמאל) ו-Theme.AppCompat.Light (ימין).

עיצובים לעומת סגנונות

יש הרבה דמיון בין עיצובים לסגנונות, אבל הם משמשים למטרות שונות. לנושאים ולסגנונות יש את אותו מבנה בסיסי – צמד מפתח/ערך שממפה מאפיינים למשאבים.

style מציין מאפיינים לסוג מסוים של תצוגה. לדוגמה, סגנון אחד יכול לציין את המאפיינים של לחצן. כל מאפיין שציינתם בסגנון הוא מאפיין שאפשר להגדיר בקובץ הפריסה. חילוץ כל המאפיינים לסגנון מאפשר להשתמש בקלות בווידג'טים שונים ולתחזק אותם.

עיצוב מגדיר אוסף של משאבים בעלי שם שאפשר להפנות אליהם לפי סגנונות, פריסות, ווידג'טים ועוד. נושאים מקצים שמות סמנטיים, כמו colorPrimary, למשאבים של Android.

סגנונות ועיצובים אמורים לפעול יחד. לדוגמה, יכול להיות שיש לכם סגנון שמציין שחלק אחד של לחצן הוא colorPrimary וחלק אחר הוא colorSecondary. ההגדרות בפועל של הצבעים האלה מצוינות בעיצוב. כשהמכשיר עובר למצב לילה, האפליקציה יכולה לעבור מעיצוב 'בהיר' לעיצוב 'כהה', וכך לשנות את הערכים של כל שמות המשאבים האלה. אין צורך לשנות את הסגנונות, כי הסגנונות משתמשים בשמות הסמנטיים ולא בהגדרות ספציפיות של צבעים.

מידע נוסף על האופן שבו עיצובים וסגנונות פועלים יחד זמין בפוסט בבלוג עיצוב ב-Android: עיצובים לעומת סגנונות.

יצירה והחלה של סגנון

כדי ליצור סגנון חדש, פותחים את הקובץ res/values/styles.xml של הפרויקט. לכל סגנון שרוצים ליצור, מבצעים את השלבים הבאים:

  1. צריך להוסיף רכיב <style> עם שם שמזהה את הסגנון באופן ייחודי.
  2. מוסיפים רכיב <item> לכל מאפיין סגנון שרוצים להגדיר. השדה name בכל פריט מציין מאפיין שאותו משתמשים בו כמאפיין XML בפריסה. הערך ברכיב <item> הוא הערך של המאפיין הזה.

לדוגמה, נניח שמגדירים את הסגנון הבא:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="GreenText" parent="TextAppearance.AppCompat">
        <item name="android:textColor">#00FF00</item>
    </style>
</resources>

אפשר להחיל את הסגנון על תצוגה באופן הבא:

<TextView
    style="@style/GreenText"
    ... />

כל מאפיין שצוין בסגנון חל על התצוגה הזו, אם התצוגה מקבלת אותו. התצוגה מתעלמת מכל המאפיינים שהיא לא מקבלת.

עם זאת, במקום להחיל סגנון על תצוגות ספציפיות, בדרך כלל מחילים סגנונות כנושא לכל האפליקציה, הפעילות או האוסף של התצוגות, כפי שמתואר בקטע אחר במדריך הזה.

הרחבה והתאמה אישית של סגנון

כשיוצרים סגנונות משלכם, תמיד צריך להרחיב סגנון קיים מהמסגרת או מספריית התמיכה כדי לשמור על תאימות לסגנונות של ממשק המשתמש בפלטפורמה. כדי להרחיב סגנון, מציינים את הסגנון שרוצים להרחיב באמצעות המאפיין parent. לאחר מכן תוכלו לשנות את מאפייני הסגנון שעברו בירושה ולהוסיף מאפיינים חדשים.

לדוגמה, אפשר לרשת את מראה הטקסט שמוגדר כברירת מחדל בפלטפורמת Android ולשנות אותו באופן הבא:

<style name="GreenText" parent="@android:style/TextAppearance">
    <item name="android:textColor">#00FF00</item>
</style>

עם זאת, תמיד צריך לרשת את סגנונות הליבה של האפליקציה מ-Android Support Library. הסגנונות ב-Support Library מספקים תאימות על ידי אופטימיזציה של כל סגנון למאפייני ממשק המשתמש שזמינים בכל גרסה. לרוב, השמות של הסגנונות בספריית התמיכה דומים לשמות של הסגנונות מהפלטפורמה, אבל כוללים את AppCompat.

כדי לרשת סגנונות מספרייה או מפרויקט משלכם, מגדירים את שם סגנון ההורה בלי החלק @android:style/ שמוצג בדוגמה הקודמת. לדוגמה, הדוגמה הבאה יורשת סגנונות של מראה טקסט מ-Support Library:

<style name="GreenText" parent="TextAppearance.AppCompat">
    <item name="android:textColor">#00FF00</item>
</style>

אפשר גם לרשת סגנונות – מלבד אלה מהפלטפורמה – על ידי הרחבת שם הסגנון באמצעות סימן נקודה, במקום להשתמש במאפיין parent. כלומר, מוסיפים לשם הסגנון את שם הסגנון שרוצים לרשת, ומפרידים ביניהם בנקודה. בדרך כלל עושים זאת רק כשמרחיבים את הסגנונות שלכם, ולא באמצעות סגנונות מספריות אחרות. לדוגמה, הסגנון הבא יורש את כל הסגנונות מ-GreenText בדוגמה הקודמת, ואז מגדיל את גודל הטקסט:

<style name="GreenText.Large">
    <item name="android:textSize">22dp</item>
</style>

אפשר להמשיך לקבל בירושה סגנונות כאלה כמה פעמים שרוצים, על ידי צירוף שמות נוספים.

כדי לבדוק אילו מאפיינים אפשר להצהיר עליהם באמצעות תג <item>, אפשר לעיין בטבלה 'מאפייני XML' במסמכי העזרה השונים של הכיתות. כל התצוגות תומכות במאפייני XML מהקלאס הבסיסי View, ובתצוגות רבות נוספים מאפיינים מיוחדים משלהם. לדוגמה, מאפייני ה-XML של TextView כוללים את המאפיין android:inputType שאפשר להחיל על תצוגת טקסט שמקבלת קלט, כמו ווידג'ט EditText.

החלת סגנון כעיצוב

אפשר ליצור עיצוב באותו אופן שבו יוצרים סגנונות. ההבדל הוא באופן היישום: במקום להחיל סגנון באמצעות המאפיין style על תצוגה, מחילים עיצוב באמצעות המאפיין android:theme על התג <application> או על תג <activity> בקובץ AndroidManifest.xml.

לדוגמה, כך מחילים את העיצוב הכהה של Material Design בספריית התמיכה של Android על כל האפליקציה:

<manifest ... >
    <application android:theme="@style/Theme.AppCompat" ... >
    </application>
</manifest>

כך מחילים את העיצוב 'אור' רק על פעילות אחת:

<manifest ... >
    <application ... >
        <activity android:theme="@style/Theme.AppCompat.Light" ... >
        </activity>
    </application>
</manifest>

כל תצוגה באפליקציה או בפעילות מחילה את הסגנונות שהיא תומכת בהם מתוך אלה שמוגדרים בנושא הנתון. אם תצוגה תומכת רק בחלק מהמאפיינים שהוגדרו בסגנון, היא מחילה רק את המאפיינים האלה ומתעלם מהמאפיינים שלא נתמכים בה.

החל מ-Android 5.0 (רמת API‏ 21) ומ-Android Support Library v22.1, אפשר גם לציין את המאפיין android:theme לתצוגה בקובץ הפריסה. הפעולה הזו משנה את העיצוב של התצוגה הזו ושל כל תצוגות הצאצא, כדי שתוכלו לשנות את לוחות הצבעים של העיצוב בחלק מסוים בממשק.

בדוגמאות הקודמות מוסבר איך מחילים נושא כמו Theme.AppCompat שסופק על ידי Android Support Library. עם זאת, בדרך כלל תרצו להתאים אישית את העיצוב כך שיתאים למותג של האפליקציה. הדרך הטובה ביותר לעשות זאת היא להרחיב את הסגנונות האלה מ-Support Library ולשנות את ערכי ברירת המחדל של חלק מהמאפיינים, כפי שמתואר בקטע הבא.

היררכיית סגנונות

ב-Android יש מגוון דרכים להגדיר מאפיינים באפליקציה ל-Android. לדוגמה, תוכלו להגדיר מאפיינים ישירות בפריסה, להחיל סגנון על תצוגה, להחיל עיצוב על פריסה ואפילו להגדיר מאפיינים באופן פרוגרמטי.

כשבוחרים את הסגנון של האפליקציה, חשוב לשים לב להיררכיית הסגנונות של Android. באופן כללי, כדאי להשתמש בעיצובים ובסגנונות עד כמה שאפשר כדי לשמור על עקביות. אם תציינו את אותם מאפיינים במספר מקומות, הרשימה הבאה תקבע אילו מאפיינים יחולו בסופו של דבר. הרשימה ממוינת לפי קדימות מהגבוהה ביותר לנמוכה ביותר.

  1. החלת סגנון ברמת התו או הפסקה באמצעות קטעי טקסט על כיתות שמבוססות על TextView.
  2. החלת מאפיינים באופן פרוגרמטי.
  3. החלת מאפיינים ספציפיים ישירות על תצוגה מפורטת.
  4. החלת סגנון על תצוגה.
  5. עיצוב ברירת מחדל.
  6. החלת עיצוב על אוסף תצוגות, על פעילות או על האפליקציה כולה.
  7. החלת סגנון ספציפי לתצוגה מסוימת, למשל הגדרת TextAppearance ב-TextView.

איור 2. עיצוב מ-span מבטל את העיצוב מ-textAppearance.

TextAppearance

אחת מהמגבלות של סגנונות היא שאפשר להחיל רק סגנון אחד על View. עם זאת, ב-TextView אפשר לציין גם מאפיין TextAppearance שפועל באופן דומה לסגנון, כפי שמוצג בדוגמה הבאה:

<TextView
    ...
    android:textAppearance="@android:style/TextAppearance.Material.Headline"
    android:text="This text is styled via textAppearance!" />

TextAppearance מאפשר להגדיר סגנון ספציפי לטקסט, תוך שמירה על הסגנון של View לשימושים אחרים. עם זאת, חשוב לזכור שאם מגדירים מאפייני טקסט ישירות ב-View או בסגנון, הערכים האלה מבטלים את הערכים של TextAppearance.

TextAppearance תומך בקבוצת משנה של מאפייני עיצוב ש-TextView מציע. רשימת המאפיינים המלאה מפורטת במאמר TextAppearance.

חלק מהמאפיינים הנפוצים של TextView שלא נכללים הם lineHeight[Multiplier|Extra], lines, breakStrategy וגם hyphenationFrequency. TextAppearance פועל ברמת התווים ולא ברמת הפסקה, ולכן אין תמיכה במאפיינים שמשפיעים על כל הפריסה.

התאמה אישית של עיצוב ברירת המחדל

כשיוצרים פרויקט ב-Android Studio, המערכת מחילה על האפליקציה נושא של Material Design כברירת מחדל, כפי שמוגדר בקובץ styles.xml של הפרויקט. הסגנון AppTheme מרחיב נושא מ-Support Library וכולל שינויים מברירת המחדל למאפייני צבע שבהם משתמשים רכיבי UI מרכזיים, כמו סרגל האפליקציות ולחצן הפעולה הצף, אם משתמשים בהם. כך תוכלו להתאים אישית במהירות את עיצוב הצבעים של האפליקציה על ידי עדכון הצבעים שסופקו.

לדוגמה, הקובץ styles.xml נראה כך:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

ערכי הסגנון הם למעשה הפניות למשאבי צבע אחרים, שמוגדרים בקובץ res/values/colors.xml של הפרויקט. זה הקובץ שאתם עורכים כדי לשנות את הצבעים. כדאי לעיין בסקירה הכללית על צבעים ב-Material Design כדי לשפר את חוויית המשתמש באמצעות צבעים דינמיים וצבעים מותאמים אישית נוספים.

אחרי זיהוי הצבעים, מעדכנים את הערכים ב-res/values/colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--   Color for the app bar and other primary UI elements. -->
    <color name="colorPrimary">#3F51B5</color>

    <!--   A darker variant of the primary color, used for
           the status bar (on Android 5.0+) and contextual app bars. -->
    <color name="colorPrimaryDark">#303F9F</color>

    <!--   a secondary color for controls like checkboxes and text fields. -->
    <color name="colorAccent">#FF4081</color>
</resources>

לאחר מכן אפשר לשנות את הסגנונות האחרים שרוצים. לדוגמה, אפשר לשנות את צבע הרקע של הפעילות באופן הבא:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <item name="android:windowBackground">@color/activityBackground</item>
</style>

ברשימת המאפיינים שאפשר להשתמש בהם בעיצוב אפשר לעיין בטבלת המאפיינים ב-R.styleable.Theme. כשמוסיפים סגנונות לתצוגות של הפריסה, אפשר למצוא את המאפיינים בטבלה 'מאפייני XML' בהפניות של הכיתות. לדוגמה, כל התצוגות תומכות במאפייני XML מהקלאס הבסיסי View.

רוב המאפיינים חלים על סוגים ספציפיים של תצוגות מפורטות, וחלקם חלים על כל התצוגות המפורטות. עם זאת, חלק ממאפייני העיצוב שמפורטים בקטע R.styleable.Theme חלים על חלון הפעילות, ולא על התצוגות בפריסה. לדוגמה, windowBackground משנה את הרקע של החלון ו-windowEnterTransition מגדיר אנימציית מעבר לשימוש כשהפעילות מתחילה. פרטים נוספים זמינים במאמר התחלת פעילות באמצעות אנימציה.

בספריית התמיכה ב-Android יש גם מאפיינים נוספים שאפשר להשתמש בהם כדי להתאים אישית את העיצוב המורחב מ-Theme.AppCompat, כמו המאפיין colorPrimary שמוצג בדוגמה שלמעלה. מומלץ להציג אותם בקובץ attrs.xml של הספרייה.

בספריית התמיכה יש גם עיצובים שונים שאולי תרצו להרחיב במקום עיצובים שמוצגים בדוגמה שלמעלה. המקום הטוב ביותר לראות את הנושאים הזמינים הוא קובץ themes.xml של הספרייה.

הוספת סגנונות ספציפיים לגרסה

אם בגרסה חדשה של Android נוספו מאפייני עיצוב שאתם רוצים להשתמש בהם, תוכלו להוסיף אותם לעיצוב ועדיין לשמור על תאימות לגרסאות ישנות. כל מה שצריך הוא קובץ styles.xml נוסף ששמור בתיקייה values וכולל את מסמכי הסיווג של גרסאות המשאבים:

res/values/styles.xml        # themes for all versions
res/values-v21/styles.xml    # themes for API level 21+ only

מכיוון שהסגנונות בקובץ values/styles.xml זמינים לכל הגרסאות, אפשר להעביר אותם לנושאים ב-values-v21/styles.xml. כלומר, אפשר להימנע מכפילות של סגנונות על ידי התחלה עם עיצוב 'בסיסי' ולאחר מכן הרחבה שלו בסגנונות ספציפיים לגרסה.

לדוגמה, כדי להצהיר על מעברים בין חלונות ב-Android 5.0 (רמת API‏ 21) ואילך, צריך להשתמש במאפיינים חדשים. לכן, העיצוב הבסיסי ב-res/values/styles.xml יכול להיראות כך:

<resources>
    <!-- Base set of styles that apply to all versions. -->
    <style name="BaseAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/primaryColor</item>
        <item name="colorPrimaryDark">@color/primaryTextColor</item>
        <item name="colorAccent">@color/secondaryColor</item>
    </style>

    <!-- Declare the theme name that's actually applied in the manifest file. -->
    <style name="AppTheme" parent="BaseAppTheme" />
</resources>

לאחר מכן, מוסיפים את הסגנונות הספציפיים לגרסה בקובץ res/values-v21/styles.xml באופן הבא:

<resources>
    <!-- extend the base theme to add styles available only with API level 21+ -->
    <style name="AppTheme" parent="BaseAppTheme">
        <item name="android:windowActivityTransitions">true</item>
        <item name="android:windowEnterTransition">@android:transition/slide_right</item>
        <item name="android:windowExitTransition">@android:transition/slide_left</item>
    </style>
</resources>

עכשיו אפשר להחיל את AppTheme בקובץ המניפסט, והמערכת תבחר את הסגנונות שזמינים לכל גרסת מערכת.

למידע נוסף על שימוש במשאבים חלופיים במכשירים שונים, ראו הוספת משאבים חלופיים.

התאמה אישית של סגנונות הווידג'ט

לכל ווידג'ט ב-Support Library ובמסגרת יש סגנון ברירת מחדל. לדוגמה, כשאתם מעצבים את האפליקציה באמצעות נושא מ-Support Library, מופע של Button מעוצב באמצעות הסגנון Widget.AppCompat.Button. אם רוצים להחיל סגנון ווידג'ט אחר על לחצן, אפשר לעשות זאת באמצעות המאפיין style בקובץ הפריסה. לדוגמה, הקוד הבא מחיל את סגנון הלחצן ללא שוליים של הספרייה:

<Button
    style="@style/Widget.AppCompat.Button.Borderless"
    ... />

אם רוצים להחיל את הסגנון הזה על כל הלחצנים, אפשר להצהיר עליו ב-buttonStyle של העיצוב באופן הבא:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="buttonStyle">@style/Widget.AppCompat.Button.Borderless</item>
    ...
</style>

אפשר גם להרחיב סגנונות של ווידג'טים, בדיוק כמו הרחבת סגנון אחר, ואז להחיל את סגנון הווידג'ט המותאם אישית בפריסה או בנושא.

מקורות מידע נוספים

למידע נוסף על עיצובים וסגנונות, אפשר לעיין במקורות המידע הבאים:

פוסטים בבלוגים