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