יצירת הטמעה עם ממשקי API ישנים

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

בחירת פתרון חלופי

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

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

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

  • אפשר להטמיע ווידג'טים של NumberPicker ושל Switch באמצעות ווידג'טים של Spinner ושל ToggleButton, בהתאמה.

  • אפשר להטמיע ווידג'טים של ListPopupWindow ושל PopupMenu באמצעות ווידג'טים של PopupWindow.

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

הטמעת כרטיסיות באמצעות ממשקי API ישנים יותר

כדי ליצור הטמעה ישנה יותר של כרטיסיות בסרגל הפעולות, אפשר להשתמש ב-TabWidget וב-TabHost (אבל אפשר להשתמש בווידג'טים של Button בפריסה אופקית). מטמיעים את זה בכיתות שנקראות TabHelperEclair ו-CompatTabEclair, כי ההטמעה הזו משתמשת בממשקי API שהושקו לא יאוחר מ-Android 2.0 (Eclair).

תרשים סיווג להטמעת הכרטיסיות ב-Eclair.

איור 1. תרשים של הכיתה להטמעת הכרטיסיות ב-Eclair.

הטמעת CompatTabEclair שומרת מאפייני כרטיסיות, כמו הטקסט והסמל של הכרטיסייה, במשתני מופעים, כי אין אובייקט ActionBar.Tab זמין לטיפול באחסון הזה:

Kotlin

class CompatTabEclair internal constructor(val activity: FragmentActivity, tag: String) :
        CompatTab(tag) {

    // Store these properties in the instance,
    // as there is no ActionBar.Tab object.
    private var text: CharSequence? = null
    ...

    override fun setText(resId: Int): CompatTab {
        // Our older implementation simply stores this
        // information in the object instance.
        text = activity.resources.getText(resId)
        return this
    }

    ...
    // Do the same for other properties (icon, callback, etc.)
}

Java

public class CompatTabEclair extends CompatTab {
    // Store these properties in the instance,
    // as there is no ActionBar.Tab object.
    private CharSequence text;
    ...

    public CompatTab setText(int resId) {
        // Our older implementation simply stores this
        // information in the object instance.
        text = activity.getResources().getText(resId);
        return this;
    }

    ...
    // Do the same for other properties (icon, callback, etc.)
}

בהטמעה של TabHelperEclair נעשה שימוש בשיטות בווידג'ט TabHost כדי ליצור TabHost.TabSpec אובייקטים ומחווני כרטיסיות:

Kotlin

class TabHelperEclair internal constructor(activity: FragmentActivity) : TabHelper(activity) {

    private var tabHost: TabHost? = null
    ...

    override fun setUp() {
        // Our activity layout for pre-Honeycomb devices
        // must contain a TabHost.
        tabHost = tabHost ?: mActivity.findViewById<TabHost>(android.R.id.tabhost).apply {
            setup()
        }
    }

    override fun addTab(tab: CompatTab) {
        ...
        tabHost?.newTabSpec(tab.tag)?.run {
            setIndicator(tab.getText()) // And optional icon
            ...
            tabHost?.addTab(this)
        }
    }
    // The other important method, newTab() is part of
    // the base implementation.
}

Java

public class TabHelperEclair extends TabHelper {
    private TabHost tabHost;
    ...

    protected void setUp() {
        if (tabHost == null) {
            // Our activity layout for pre-Honeycomb devices
            // must contain a TabHost.
            tabHost = (TabHost) mActivity.findViewById(
                    android.R.id.tabhost);
            tabHost.setup();
        }
    }

    public void addTab(CompatTab tab) {
        ...
        TabSpec spec = tabHost
                .newTabSpec(tag)
                .setIndicator(tab.getText()); // And optional icon
        ...
        tabHost.addTab(spec);
    }

    // The other important method, newTab() is part of
    // the base implementation.
}

עכשיו יש לכם שתי הטמעות של CompatTab ו-TabHelper: אחת שפועלת במכשירים עם Android מגרסה 3.0 ואילך ומשתמשת בממשקי API חדשים, ואחת שפועלת במכשירים עם Android מגרסה 2.0 ואילך ומשתמשת בממשקי API ישנים יותר. בשיעור הבא נדון בשימוש בהטמעות האלה באפליקציה שלכם.