Tworzenie implementacji przy użyciu starszych interfejsów API

Z tej lekcji dowiesz się, jak utworzyć implementację, która odzwierciedla nowsze interfejsy API, ale obsługuje starsze urządzenia.

Wybierz rozwiązanie zastępcze

Najtrudniejszym zadaniem związanym z używaniem nowszych funkcji interfejsu w sposób zgodny wstecz jest wybranie i wdrożenie starszego (zapasowego) rozwiązania dla starszych wersji platformy. W wielu przypadkach można osiągnąć cel tych nowszych komponentów interfejsu, korzystając ze starszych funkcji platformy interfejsu. Przykład:

  • Paski działań można zaimplementować za pomocą poziomego elementu LinearLayout zawierającego przyciski obrazów, jako niestandardowe paski tytułu lub jako widoki w układzie aktywności. Działania w rozszerzonym menu można wyświetlać pod przyciskiem Menu urządzenia.

  • Karty paska działań można zaimplementować za pomocą poziomego elementu LinearLayout zawierającego przyciski lub za pomocą elementu interfejsu TabWidget.

  • Widżety NumberPicker i Switch można zaimplementować odpowiednio za pomocą widżetów Spinner i ToggleButton.

  • Widżety ListPopupWindow i PopupMenu można zaimplementować za pomocą widżetów PopupWindow.

Zasadniczo nie ma uniwersalnego rozwiązania, które umożliwiałoby portowanie wsteczne nowszych komponentów interfejsu do starszych urządzeń. Pamiętaj o wrażeniach użytkownika: na starszych urządzeniach użytkownicy mogą nie znać nowszych wzorców projektowych i komponentów interfejsu. Zastanów się, jak można zapewnić tę samą funkcjonalność za pomocą znanych elementów. W wielu przypadkach nie jest to problem – jeśli nowsze komponenty interfejsu są widoczne w ekosystemie aplikacji (np. pasek działań) lub gdy model interakcji jest prosty i intuicyjny (np. widoki przesuwane za pomocą elementu ViewPager).

Implementowanie kart za pomocą starszych interfejsów API

Aby utworzyć starszą implementację kart paska działań, możesz użyć elementów TabWidget i TabHost (możesz też użyć poziomo ułożonych widżetów Button). Zaimplementuj to w klasach o nazwach TabHelperEclair i CompatTabEclair, ponieważ ta implementacja korzysta z interfejsów API wprowadzonych nie później niż w Androidzie 2.0 (Eclair).

Diagram klas implementacji kart w Eclair.
Rysunek 1. Schemat klas dla implementacji kart w Eclair.

Implementacja CompatTabEclair przechowuje właściwości karty, takie jak tekst i ikona karty, w zmiennych instancji, ponieważ nie ma obiektu ActionBar.Tab, który mógłby obsługiwać to przechowywanie:

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.)
}

Implementacja TabHelperEclair korzysta z metod widżetu TabHost do tworzenia TabHost.TabSpec obiektów i wskaźników kart:

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.
}

Masz teraz 2 implementacje CompatTab i TabHelper: jedną, która działa na urządzeniach z Androidem 3.0 lub nowszym i korzysta z nowych interfejsów API, oraz drugą, która działa na urządzeniach z Androidem 2.0 lub nowszym i korzysta ze starszych interfejsów API. Z następnej lekcji dowiesz się, jak używać tych implementacji w aplikacji.