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

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

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

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

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

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

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

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

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

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

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

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

מידע נוסף על האופן שבו ערכות נושא וסגנונות פועלים יחד זמין בפוסט בבלוג Android styling: themes vs styles (סגנונות ב-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"
    ... />

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

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

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

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

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

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

עם זאת, תמיד כדאי להשתמש בסגנונות של אפליקציות הליבה מספריית התמיכה של Android. הסגנונות בספריית התמיכה מספקים תאימות על ידי אופטימיזציה של כל סגנון למאפייני ממשק המשתמש שזמינים בכל גרסה. לסגנונות בספריית התמיכה יש בדרך כלל שם דומה לסגנון מהפלטפורמה, אבל עם 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. עם זאת, בדרך כלל כדאי להתאים אישית את העיצוב כך שיתאים למותג של האפליקציה. הדרך הכי טובה לעשות את זה היא להרחיב את הסגנונות האלה מספריית התמיכה ולשנות חלק מהמאפיינים, כמו שמתואר בקטע הבא.

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

ב-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 הזה הוא הרחבה של ערכת נושא מספריית התמיכה, והוא כולל שינויים במאפייני הצבע שמשמשים רכיבי 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 בקובץ המניפסט, והמערכת בוחרת את הסגנונות שזמינים לכל גרסת מערכת.

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

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

לכל ווידג' במסגרת ובספריית התמיכה יש סגנון ברירת מחדל. לדוגמה, כשמעצבים את האפליקציה באמצעות ערכת נושא מהספרייה לתמיכה, מופע של 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>

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

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

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

פוסטים בבלוג