Criar uma implementação com APIs mais antigas
Mantenha tudo organizado com as coleções
Salve e categorize o conteúdo com base nas suas preferências.
Esta lição aborda a criação de implementações que espelham APIs mais recentes e que ainda são compatíveis com dispositivos mais antigos.
Escolher uma solução alternativa
A tarefa mais desafiadora ao usar recursos de IU mais recentes de forma compatível com versões anteriores é decidir e implementar uma solução antiga (substituta) para versões de plataformas mais antigas. Em muitos casos, é possível atender a finalidade desses novos componentes da IU usando recursos de framework mais antigos dela. Exemplo:
-
As barras de ação podem ser implementadas usando um LinearLayout
horizontal contendo botões de imagem, seja como barras de título personalizadas ou como visualizações no layout da atividade. É possível apresentar ações flutuantes sob o botão Menu do dispositivo.
-
As guias de barras de ações podem ser implementadas usando um LinearLayout
horizontal que contém botões ou usando o elemento TabWidget
da IU.
-
Os widgets NumberPicker
e Switch
podem ser implementados usando os widgets Spinner
e ToggleButton
, respectivamente.
-
Os widgets ListPopupWindow
e PopupMenu
podem ser implementados usando widgets PopupWindow
.
Geralmente, não há uma solução única para fazer retrocompatibilidade de componentes de IU mais recentes para dispositivos mais antigos. Pense sempre na experiência do usuário: em dispositivos mais antigos, os usuários podem não estar familiarizados com os padrões de design e componentes de IU mais recentes. Pense em como a mesma funcionalidade pode ser oferecida usando elementos conhecidos. Em muitos casos, isso é uma preocupação menor se os componentes da IU forem proeminentes no ecossistema de aplicativos, como a barra de ações, ou se o modelo de interação for extremamente simples e intuitivo, como deslizar visualizações usando um ViewPager
.
Implementar guias usando APIs mais antigas
Para criar uma implementação mais antiga de guias da barra de ações, você pode usar um TabWidget
e um TabHost
, embora também seja possível usar widgets Button
dispostos horizontalmente. Implemente isso em classes chamadas TabHelperEclair
e CompatTabEclair
, uma vez que essa implementação usa APIs introduzidas no máximo no Android 2.0 (Eclair).
Figura 1. Diagrama de classes para a implementação de guias do Eclair.
A implementação de CompatTabEclair
armazena propriedades da guia, como o texto e ícone dela em variáveis de instância, já que não há um objeto ActionBar.Tab
disponível para gerenciar esse armazenamento:
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.)
}
A implementação de TabHelperEclair
usa métodos na
Widget TabHost
para criar TabHost.TabSpec
objetos e indicadores de guia:
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.
}
Agora, você tem duas implementações de CompatTab
e TabHelper
: uma que funciona em dispositivos que executam o Android 3.0 ou versões mais recentes e usa APIs novas, e outra que funciona em dispositivos que executam o Android 2.0 ou versões mais recentes e usa APIs mais antigas. A próxima lição aborda o uso dessas implementações no seu aplicativo.
O conteúdo e os exemplos de código nesta página estão sujeitos às licenças descritas na Licença de conteúdo. Java e OpenJDK são marcas registradas da Oracle e/ou suas afiliadas.
Última atualização 2025-07-27 UTC.
[[["Fácil de entender","easyToUnderstand","thumb-up"],["Meu problema foi resolvido","solvedMyProblem","thumb-up"],["Outro","otherUp","thumb-up"]],[["Não contém as informações de que eu preciso","missingTheInformationINeed","thumb-down"],["Muito complicado / etapas demais","tooComplicatedTooManySteps","thumb-down"],["Desatualizado","outOfDate","thumb-down"],["Problema na tradução","translationIssue","thumb-down"],["Problema com as amostras / o código","samplesCodeIssue","thumb-down"],["Outro","otherDown","thumb-down"]],["Última atualização 2025-07-27 UTC."],[],[],null,["# Create an implementation with older APIs\n\nThis lesson discusses how to create an implementation that mirrors newer APIs yet supports older devices.\n\nDecide on a substitute solution\n-------------------------------\n\nThe most challenging task in using newer UI features in a backward-compatible way is deciding on and implementing an older (fallback) solution for older platform versions. In many cases, it's possible to fulfill the purpose of these newer UI components using older UI framework features. For example:\n\n- Action bars can be implemented using a horizontal [LinearLayout](/reference/android/widget/LinearLayout) containing image buttons, either as custom title bars or as views in your activity layout. Overflow actions can be presented under the device *Menu* button.\n\n- Action bar tabs can be implemented using a horizontal [LinearLayout](/reference/android/widget/LinearLayout) containing buttons, or using the [TabWidget](/reference/android/widget/TabWidget) UI element.\n\n- [NumberPicker](/reference/android/widget/NumberPicker) and [Switch](/reference/android/widget/Switch) widgets can be implemented using [Spinner](/reference/android/widget/Spinner) and [ToggleButton](/reference/android/widget/ToggleButton) widgets, respectively.\n\n- [ListPopupWindow](/reference/android/widget/ListPopupWindow) and [PopupMenu](/reference/android/widget/PopupMenu) widgets can be implemented using [PopupWindow](/reference/android/widget/PopupWindow) widgets.\n\nThere generally isn't a one-size-fits-all solution for backporting newer UI components to older devices. Be mindful of the user experience: on older devices, users may not be familiar with newer design patterns and UI components. Give some thought as to how the same functionality can be delivered using familiar elements. In many cases this is less of a concern---if newer UI components are prominent in the application ecosystem (such as the action bar), or where the interaction model is extremely simple and intuitive (such as swipe views using a [ViewPager](/reference/androidx/viewpager/widget/ViewPager)).\n\nImplement tabs using older APIs\n-------------------------------\n\nTo create an older implementation of action bar tabs, you can use a [TabWidget](/reference/android/widget/TabWidget) and [TabHost](/reference/android/widget/TabHost) (although one can alternatively use horizontally laid-out [Button](/reference/android/widget/Button) widgets). Implement this in classes called `TabHelperEclair` and `CompatTabEclair`, since this implementation uses APIs introduced no later than Android 2.0 (Eclair).\n\n**Figure 1.** Class diagram for the Eclair implementation of tabs.\n\nThe `CompatTabEclair` implementation stores tab properties such as the tab text and icon in instance variables, since there isn't an [ActionBar.Tab](/reference/android/app/ActionBar.Tab) object available to handle this storage: \n\n### Kotlin\n\n```kotlin\nclass CompatTabEclair internal constructor(val activity: FragmentActivity, tag: String) :\n CompatTab(tag) {\n\n // Store these properties in the instance,\n // as there is no ActionBar.Tab object.\n private var text: CharSequence? = null\n ...\n\n override fun setText(resId: Int): CompatTab {\n // Our older implementation simply stores this\n // information in the object instance.\n text = activity.resources.getText(resId)\n return this\n }\n\n ...\n // Do the same for other properties (icon, callback, etc.)\n}\n```\n\n### Java\n\n```java\npublic class CompatTabEclair extends CompatTab {\n // Store these properties in the instance,\n // as there is no ActionBar.Tab object.\n private CharSequence text;\n ...\n\n public CompatTab setText(int resId) {\n // Our older implementation simply stores this\n // information in the object instance.\n text = activity.getResources().getText(resId);\n return this;\n }\n\n ...\n // Do the same for other properties (icon, callback, etc.)\n}\n```\n\nThe `TabHelperEclair` implementation makes use of methods on the\n[TabHost](/reference/android/widget/TabHost) widget for creating [TabHost.TabSpec](/reference/android/widget/TabHost.TabSpec)\nobjects and tab indicators: \n\n### Kotlin\n\n```kotlin\nclass TabHelperEclair internal constructor(activity: FragmentActivity) : TabHelper(activity) {\n\n private var tabHost: TabHost? = null\n ...\n\n override fun setUp() {\n // Our activity layout for pre-Honeycomb devices\n // must contain a TabHost.\n tabHost = tabHost ?: mActivity.findViewById\u003cTabHost\u003e(android.R.id.tabhost).apply {\n setup()\n }\n }\n\n override fun addTab(tab: CompatTab) {\n ...\n tabHost?.newTabSpec(tab.tag)?.run {\n setIndicator(tab.getText()) // And optional icon\n ...\n tabHost?.addTab(this)\n }\n }\n // The other important method, newTab() is part of\n // the base implementation.\n}\n```\n\n### Java\n\n```java\npublic class TabHelperEclair extends TabHelper {\n private TabHost tabHost;\n ...\n\n protected void setUp() {\n if (tabHost == null) {\n // Our activity layout for pre-Honeycomb devices\n // must contain a TabHost.\n tabHost = (TabHost) mActivity.findViewById(\n android.R.id.tabhost);\n tabHost.setup();\n }\n }\n\n public void addTab(CompatTab tab) {\n ...\n TabSpec spec = tabHost\n .newTabSpec(tag)\n .setIndicator(tab.getText()); // And optional icon\n ...\n tabHost.addTab(spec);\n }\n\n // The other important method, newTab() is part of\n // the base implementation.\n}\n```\n\nYou now have two implementations of `CompatTab` and `TabHelper`: one that works on devices running Android 3.0 or later and uses new APIs, and another that works on devices running Android 2.0 or later and uses older APIs. The next lesson discusses using these implementations in your application."]]