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

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

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

לדוגמה, קובץ 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>

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

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

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

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