studio programacion móviles libros libro desarrollo desarrollar curso aprende aplicaciones android android-4.0 android-actionbar

móviles - manual de programacion android pdf



Android 4.0, el texto en la barra de acción NUNCA muestra (7)

Estoy tratando de usar las nuevas API de Google, específicamente la barra de acciones.

Cuando la compilación se configuró en api 10, si presioné el botón de menú, obtuve opciones de menú atractivas, cada una con una imagen y un ícono. Al usar api 14, no importa lo que intento, siempre coloca el icono en la barra de acción sin texto. He intentado todo lo que puedo pensar. Le di la propiedad "con texto", cambié el texto a un solo carácter (en caso de que fuera un problema de sala), pero nada.

He visto esto hecho antes, incluso en la guía para desarrolladores de android.developer, pero parece que no puedo encontrar una respuesta sobre cómo hacer que aparezca.


Aquí hay otra opción, basada aproximadamente en dgmltn. Las ventajas:

  • Más control, por ejemplo, he cambiado el texto y la imagen en mi diseño.
  • Más fácil de usar: solo requiere dos líneas adicionales en sus actividades / fragmentos.
  • Solo requiere dos archivos adicionales.
  • Posiblemente un poco más correcto, pero todavía es un poco de un truco de IMO.

Supuse que estás usando ActionBarSherlock en este ejemplo. Primero, crea el diseño de vista que quieras. Este está basado en ActionBarSherlock''s. Todo lo que cambié fue intercambiando la imagen / vista, reduciendo el margen / relleno compartido a 0 para que estén más cerca, y resolviendo todos los estilos de ABS.

<com.example.views.ActionMenuTextItemView xmlns:android="http://schemas.android.com/apk/res/android" style="@android:style/Widget.Holo.ActionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:addStatesFromChildren="true" android:focusable="true" android:gravity="center" android:clickable="true" android:paddingLeft="4dip" android:paddingRight="4dip" > <com.actionbarsherlock.internal.widget.CapitalizingButton android:id="@+id/abs__textButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:background="@null" android:ellipsize="none" android:focusable="false" android:minHeight="48dip" android:minWidth="48dip" android:paddingBottom="4dip" android:paddingLeft="4dip" android:paddingRight="0dip" android:paddingTop="4dip" android:singleLine="true" android:textAppearance="@android:style/TextAppearance.Holo.Widget.ActionBar.Menu" android:textColor="#fff3f3f3" /> <ImageButton android:id="@+id/abs__imageButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginBottom="4dip" android:layout_marginLeft="0dip" android:layout_marginRight="4dip" android:layout_marginTop="4dip" android:adjustViewBounds="true" android:background="@null" android:focusable="false" android:scaleType="fitCenter" android:visibility="gone" /> </com.example.views.ActionMenuTextItemView>

Luego crea la clase de View correspondiente. Es posible que desee copiar CapitalizingButton si le preocupa usar cosas internas. Oh, también, nunca arreglé las cosas de ancho mínimo. No creo que realmente importe sin embargo.

package com.example.views; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.TextUtils; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.accessibility.AccessibilityEvent; import android.widget.ImageButton; import android.widget.LinearLayout; import com.actionbarsherlock.R; import com.actionbarsherlock.app.SherlockActivity; import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockListActivity; import com.actionbarsherlock.app.SherlockListFragment; import com.actionbarsherlock.internal.widget.CapitalizingButton; import com.actionbarsherlock.view.MenuItem; @SuppressLint({ "NewApi" }) public class ActionMenuTextItemView extends LinearLayout implements OnClickListener { private ImageButton mImageButton; private CapitalizingButton mTextButton; private Object mTarget; private MenuItem mItem; // Set up all the data. Object must be a sherlock activity or fragment with an onMenuItemSelected(). public void initialise(MenuItem item, Object target) { mItem = item; mTarget = target; setIcon(mItem.getIcon()); setTitle(mItem.getTitle()); } public ActionMenuTextItemView(Context context, AttributeSet attrs) { super(context, attrs); } public ActionMenuTextItemView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void onFinishInflate() { super.onFinishInflate(); mImageButton = (ImageButton) findViewById(R.id.abs__imageButton); mTextButton = (CapitalizingButton) findViewById(R.id.abs__textButton); mImageButton.setOnClickListener(this); mTextButton.setOnClickListener(this); setOnClickListener(this); } @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); mImageButton.setEnabled(enabled); mTextButton.setEnabled(enabled); } public void setIcon(Drawable icon) { mImageButton.setImageDrawable(icon); if (icon != null) mImageButton.setVisibility(VISIBLE); else mImageButton.setVisibility(GONE); } public void setTitle(CharSequence title) { mTextButton.setTextCompat(title); setContentDescription(title); } @Override public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { onPopulateAccessibilityEvent(event); return true; } @Override public void onPopulateAccessibilityEvent(AccessibilityEvent event) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) super.onPopulateAccessibilityEvent(event); final CharSequence cdesc = getContentDescription(); if (!TextUtils.isEmpty(cdesc)) event.getText().add(cdesc); } @Override public boolean dispatchHoverEvent(MotionEvent event) { // Don''t allow children to hover; we want this to be treated as a single component. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) return onHoverEvent(event); return false; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int minWidth = 0; final int widthMode = MeasureSpec.getMode(widthMeasureSpec); final int specSize = MeasureSpec.getSize(widthMeasureSpec); final int oldMeasuredWidth = getMeasuredWidth(); final int targetWidth = widthMode == MeasureSpec.AT_MOST ? Math.min(specSize, minWidth) : minWidth; if (widthMode != MeasureSpec.EXACTLY && minWidth > 0 && oldMeasuredWidth < targetWidth) { // Remeasure at exactly the minimum width. super.onMeasure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), heightMeasureSpec); } } @Override public void onClick(View v) { if (mTarget == null) return; else if (mTarget instanceof SherlockActivity) ((SherlockActivity)mTarget).onOptionsItemSelected(mItem); else if (mTarget instanceof SherlockFragmentActivity) ((SherlockFragmentActivity)mTarget).onOptionsItemSelected(mItem); else if (mTarget instanceof SherlockListActivity) ((SherlockListActivity)mTarget).onOptionsItemSelected(mItem); else if (mTarget instanceof SherlockListFragment) ((SherlockListFragment)mTarget).onOptionsItemSelected(mItem); else if (mTarget instanceof SherlockFragment) ((SherlockFragment)mTarget).onOptionsItemSelected(mItem); else throw new IllegalArgumentException("Target must be a sherlock activity or fragment."); } }

Ok, ahora estás listo para usarlo. En los elementos de su menú que desea tener texto, hace lo mismo que dijo dgmltn:

<item android:id="@+id/menu_foo" android:icon="@drawable/..." android:showAsAction="always|withText" // Doesn''t do anything really. android:title="Sell" android:titleCondensed="Sell" android:actionLayout="@layout/view_action_menu_text_item"/> // Or whatever you called it.

Y finalmente, solo agregue este código a su actividad / fragmento:

@Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getSupportMenuInflater().inflate(R.menu.activity_main, menu); // The magic lines. MenuItem it = menu.findItem(R.id.menu_foo); ((ActionMenuTextItemView)it.getActionView()).initialise(it, this);

¡Y eso es!


Esto es definitivamente lo mismo que he observado en mi Nexus S con 4.0.4. Mi aplicación utiliza una barra de acción con varias pestañas que se implementan como fragmentos. Mis diversos fragmentos hacen ajustes a las opciones de menú que se muestran en la barra de acciones mientras su pestaña está visible.

Esto parece ser un error en ICS, porque funciona consistentemente de la siguiente manera, tanto en mi Nexus S como en el emulador (tanto HVGA como WVGA800):

  1. En modo retrato, mi botón de logotipo / arriba aparece en la fila superior de la barra de acciones, las pestañas aparecen en la segunda fila y las acciones aparecen solo como iconos (sin texto) en el lado derecho de la fila superior.
  2. Pero si cuando gire hacia el paisaje, la barra de acción se colapsará en una sola fila, y las pestañas avanzarán a la barra superior como una rueda giratoria (lista desplegable) al lado de mi botón de subida. Pero, sobre todo, el texto aparece junto a mis iconos de acción.

Observé algunos otros fallos técnicos con el rotador de pestañas que me llevan a creer que este pequeño rincón de ICS es un poco desordenado / con errores. Si le digo a la aplicación que divida la barra de acciones en pantallas angostas (agregando android:uiOptions="splitActionBarWhenNarrow" en el manifiesto, ICS siempre empuja esos elementos a la barra inferior, aunque todavía hay mucho espacio en la parte superior. con la barra adicional, todavía no muestra el texto, solo el ícono.

En mi Xoom con 4.0.4, las pestañas y los elementos de acción siempre aparecen de la manera en que esperaría que aparezcan porque hay mucho espacio.

Solución alternativa: si realmente desea texto en la barra de acciones en modo vertical, debe abandonar el icono. Retire el icono de su elemento de menú y aparecerá el texto. Esto no es exactamente lo que buscamos sin embargo.

He publicado un informe de error aquí: https://code.google.com/p/android/issues/detail?id=30180 .


Intenté muchas opciones y se me ocurrió un simple "truco" sin ninguna línea de código extraña, sin imágenes. Y la primera solución con ActionLayout personalizado simplemente no funcionó para mí con compatibilidad API de nivel 10.

Si desea mostrar texto e ícono en una pequeña barra de acción, significa que sabe que tiene espacio, ¿verdad? Para que pueda usar 2 elementos del menú:

  • Primero con el ícono ÚNICAMENTE (ignore la advertencia, si establece un título, las tabletas lo mostrarán dos veces)
  • Segundo con el texto SOLAMENTE

Y elija la acción de texto en ''ifRoom'' si es necesario para que, si necesita espacio, el texto desaparecerá. Sin embargo, tomará más espacio en la barra de acción, pero fue un buen compromiso para mí. Termino con el siguiente código:

<item android:id="@+id/menu_save" android:icon="@drawable/save" pelmel:showAsAction="always"> </item> <item android:id="@+id/menu_save_text" android:title="@string/profileSave" pelmel:showAsAction="ifRoom"> </item>

( EDITAR Donde "pelmel" es el nombre de su aplicación END EDIT )

Y luego su manejador de selección solo tiene que atrapar ambos ID:

public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_save: case R.id.menu_save_text: // Your code here return true; } }


La propiedad "withText" funciona con la mayoría de las tabletas, pero una manera fácil de obtener iconos y texto en dispositivos más pequeños es agregar el texto junto al icono como una imagen (archivo PNG). De esta forma, tanto el texto como el icono se verán como un ícono y se mostrará todo.

Puede usar el ícono original para tabletas usando la propiedad withText.

  • Debe crear una carpeta de menú adicional en el directorio res titulado "menu-w600dp".

  • El archivo optionmenu.xml de esta carpeta solo se aplicará a anchos de pantalla superiores a 600 pb (los que mostrarán los iconos y el texto sin problemas).


Se corrigió este problema al leer " Si su aplicación está utilizando la Biblioteca de soporte " sección bajo Especificar las acciones en XML .

... para la compatibilidad en versiones tan bajas como Android 2.1, el atributo showAsAction no está disponible en android: namespace. En cambio, este atributo lo proporciona la Biblioteca de soporte y debe definir su propio espacio de nombres XML y usar ese espacio de nombres como el prefijo del atributo. (Un espacio de nombres XML personalizado debe basarse en el nombre de su aplicación, pero puede ser cualquier nombre que desee y solo se puede acceder dentro del alcance del archivo en el que lo declara). Por ejemplo:

<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yourapp="http://schemas.android.com/apk/res-auto" > <!-- Search, should appear as action button --> <item android:id="@+id/action_search" android:icon="@drawable/ic_action_search" android:title="@string/action_search" yourapp:showAsAction="ifRoom" /> ... </menu>

Si ninguna de estas otras cosas funciona para usted, esto puede suceder.


Si quieres que tu menú de opciones aparezca en tu barra de acción con Honeycomb, hice esto:

En su actividad, anule esta función:

@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.actionbar_universe, menu); return true; }

donde R.menu.actionbar_universe define su elemento de menú de esta manera:

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/crossholdings" android:showAsAction="always|withText" android:title="Cross Holdings" android:icon="@drawable/actionbar_cross"/> </menu>

Tenga en cuenta el showAsAction = "always | withText" y especifique android: title.

Si tiene eso y no funciona, copie y pegue aquí su recurso de menú.

EDITAR: Esto responde la pregunta incorrecta, pero es el texto original.

Uso este código para configurar el título de la barra de acción y pintarlo de rojo con el logotipo de mi empresa. Funciona bien en 3.0.

public ActionBar setActionBarStyle(String title) { ActionBar actionBar = setActionBarStyle(); actionBar.setTitle(title); return actionBar; } public ActionBar setActionBarStyle() { ActionBar actionBar = getActionBar(); ShapeDrawable actionBackground = new ShapeDrawable(); actionBackground.getPaint().setColor(Color.RED); actionBackground.setBounds(0, 0, 5, 5); actionBar.setBackgroundDrawable(actionBackground); actionBar.setDisplayUseLogoEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true); return actionBar; }


Sospecho que fue una decisión consciente de los desarrolladores de Android que nunca se muestre el texto y el ícono de un solo elemento de menú en una barra de acción estrecha. Pero si realmente quieres hacerlo, puedes usar android:actionLayout en tu archivo menu.xml. La documentación de Android ActionBar tiene una explicación ligeramente mejor.

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_foo" android:title="@string/menu_foo" android:icon="@drawable/ic_menu_foo" android:showAsAction="always" android:actionLayout="@layout/action_button_foo" /> </menu>

Luego crea tu diseño action_button_foo.xml :

<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="14dp" android:paddingBottom="14dp" android:gravity="center" android:text="@string/menu_foo" android:drawableLeft="@drawable/ic_menu_foo" android:background="@drawable/bg_btn_action_bar" android:clickable="true" />

y use un selector para su fondo bg_btn_action_bar.xml , por lo que cambia de color cuando lo toca:

<?xml version="1.0" encoding="utf-8" ?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/bg_action_bar_pressed" /> <item android:drawable="@color/transparent" /> </selector>

Ahora necesitará hacer que sus eventos personalizados de clic de identificador de vista. En su actividad, me gusta hacer esto, de modo que pueda manejar el clic en onOptionsItemSelected junto con todos mis otros elementos no personalizados.

@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.my_menu, menu); final MenuItem item = menu.findItem(R.id.menu_foo); item.getActionView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onOptionsItemSelected(item); } }); return super.onCreateOptionsMenu(menu); }