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.

Wybór rozwiązania zastępczego

Największym wyzwaniem w korzystaniu z nowszych funkcji interfejsu w sposób zgodny ze starszymi wersjami jest wybranie i wdrożenie starszego (awaryjnego) rozwiązania na potrzeby starszych wersji platformy. W wielu przypadkach przeznaczenie nowych komponentów UI jest możliwe, korzystając ze starszych funkcji platformy. Na przykład:

  • Paski działań można wdrożyć za pomocą poziomego elementu LinearLayout zawierającego przyciski obrazów. Mogą to być niestandardowe paski tytułów lub widoki w układzie aktywności. Czynności dodatkowe można wyświetlać pod przyciskiem Menu urządzenia.

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

  • Widżety NumberPickerSwitch można zaimplementować odpowiednio za pomocą widżetów SpinnerToggleButton.

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

Nie ma uniwersalnego rozwiązania, które pozwala przenieść nowsze komponenty interfejsu na starsze urządzenia. Bierz pod uwagę wygodę użytkowników: na starszych urządzeniach użytkownicy mogą nie znać nowszych wzorców projektowania i elementów interfejsu. Zastanów się, jak zapewnić tę samą funkcjonalność za pomocą znanych elementów. W wielu przypadkach nie ma to większego znaczenia, jeśli nowsze komponenty interfejsu są widoczne w ekosystemie aplikacji (np. pasek działań) lub gdy model interakcji jest bardzo prosty i intuicyjny (np. przesuwanie palcem za pomocą ViewPager).

Implementowanie kart za pomocą starszych interfejsów API

Aby utworzyć starszą implementację kart na pasku działań, możesz użyć elementów TabWidget i TabHost (ale możesz też użyć poziomych widżetów Button). Zaimplementuj go w klasach 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. Diagram klas implementacji kart w Eclair

Implementacja CompatTabEclair przechowuje właściwości karty, takie jak tekst karty i ikona w zmiennych instancji, ponieważ nie ma dostępnego obiektu ActionBar.Tab obsługującego tę pamięć:

KotlinJava
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.)
}
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 widgeta TabHost do tworzenia obiektów TabHost.TabSpec i wskaźników kart:

KotlinJava
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.
}
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 funkcji CompatTabTabHelper: 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. W następnej lekcji omówimy używanie tych implementacji w aplikacji.