example - show action bar android
Cambiar el color de texto del elemento de menú mediante programación (4)
MenuItem según lo definido por la documentación es una interfaz. Definitivamente se implementará con un widget de vista antes de ser retratado como un menú. La mayoría de los casos, estos elementos del menú se implementan como TextView. Puede usar UiAutomatorViewer para ver la jerarquía de vistas o incluso usar hierarchyviewer que se encontrará en [sdk-home] / tools /. Se adjuntó una captura de pantalla de uiautomatorviewer de muestra para un MenuItem
Por lo tanto, siempre puede encasillar su MenuItem y establecer el color.
TextView liveitem = (TextView)mOptionsMenu.findItem(R.id.action_live);
liveitem.setTextColor(Color.RED);
EDITAR:
Como hubo una solicitud para ver cómo usar esta herramienta, estoy agregando algunos contenidos más.
Asegúrese de haber configurado la variable de entorno $ ANDROID_HOME apuntando a su SDK HOME.
En tu terminal:
cd $ANDROID_HOME
./tools/uiautomatorviewer
Esta herramienta se abrirá.
El segundo o tercer botón (consulte la captura de pantalla) en el menú capturará la captura de pantalla de su dispositivo o emulador conectado y podrá inspeccionar la vista y su jerarquía. Al hacer clic en la vista, se describirá la vista y su información. Es una herramienta diseñada a propósito para las pruebas y puede inspeccionar cualquier aplicación.
Consulte el sitio del desarrollador para obtener más información: uiautomatorviewer
Así que tengo un elemento de menú, que se define como:
<item
android:id="@+id/action_live"
android:title="@string/action_live"
android:orderInCategory="1"
app:showAsAction="ifRoom|withText" />
Se muestra como texto, como puedes ver a continuación:
Y quiero cambiar programáticamente el color de texto "EN VIVO". He buscado por un tiempo y encontré un método:
Con globalmente definido:
private Menu mOptionsMenu;
y:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mOptionsMenu = menu;
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
Hago:
MenuItem liveitem = mOptionsMenu.findItem(R.id.action_live);
SpannableString s = new SpannableString(liveitem.getTitle().toString());
s.setSpan(new ForegroundColorSpan(Color.RED), 0, s.length(), 0);
liveitem.setTitle(s);
¡Pero nada pasa!
Si hago lo mismo con un elemento del menú de desbordamiento, funciona:
¿Existe alguna limitación para los elementos de la aplicación: showAsAction = "ifRoom | withText"? ¿Hay algún trabajo alrededor?
Gracias por adelantado.
Llegué un poco tarde a la fiesta con esta, pero pasé un tiempo trabajando en esto y encontré una solución, que puede ser útil para cualquier otra persona que intente hacer lo mismo. Algo de crédito va para Harish Sridharan por dirigirme en la dirección correcta.
Puede usar findViewById(R.id.MY_MENU_ITEM_ID)
para ubicar el elemento del menú (siempre que el menú haya sido creado y preparado), y TextView
a una instancia de TextView
como lo sugiere Harish, que luego se puede diseñar según sea necesario.
public class MyAwesomeActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
super.onCreate(savedInstanceState);
// Force invalidatation of the menu to cause onPrepareOptionMenu to be called
invalidateOptionsMenu();
}
private void styleMenuButton() {
// Find the menu item you want to style
View view = findViewById(R.id.YOUR_MENU_ITEM_ID_HERE);
// Cast to a TextView instance if the menu item was found
if (view != null && view instanceof TextView) {
((TextView) view).setTextColor( Color.BLUE ); // Make text colour blue
((TextView) view).setTextSize(TypedValue.COMPLEX_UNIT_SP, 24); // Increase font size
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean result = super.onPrepareOptionsMenu(menu);
styleMenuButton();
return result;
}
}
El truco aquí es forzar la invalidación del menú en el evento onCreate
la actividad (lo que hace que onPrepareMenuOptions
se llame antes de lo normal). Dentro de este método, podemos ubicar el elemento y el estilo del menú según sea necesario.
Solo se convierte en una vista de texto después de la inspección, su clase real es ActionMenuItemView, en la que podemos configurar el color del texto de esta manera:
public static void setToolbarMenuItemTextColor(final Toolbar toolbar,
final @ColorRes int color,
@IdRes final int resId) {
if (toolbar != null) {
for (int i = 0; i < toolbar.getChildCount(); i++) {
final View view = toolbar.getChildAt(i);
if (view instanceof ActionMenuView) {
final ActionMenuView actionMenuView = (ActionMenuView) view;
// view children are accessible only after layout-ing
actionMenuView.post(new Runnable() {
@Override
public void run() {
for (int j = 0; j < actionMenuView.getChildCount(); j++) {
final View innerView = actionMenuView.getChildAt(j);
if (innerView instanceof ActionMenuItemView) {
final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
if (resId == itemView.getId()) {
itemView.setTextColor(ContextCompat.getColor(toolbar.getContext(), color));
}
}
}
}
});
}
}
}
}
@RRP dame una pista, pero su solución no funciona para mí. Y @Box se dan mutuamente, pero su respuesta se ve un poco menos clara. Gracias ellos. Entonces, según ellos, tengo una solución total.
private static void setMenuTextColor(final Context context, final Toolbar toolbar, final int menuResId, final int colorRes) {
toolbar.post(new Runnable() {
@Override
public void run() {
View settingsMenuItem = toolbar.findViewById(menuResId);
if (settingsMenuItem instanceof TextView) {
if (DEBUG) {
Log.i(TAG, "setMenuTextColor textview");
}
TextView tv = (TextView) settingsMenuItem;
tv.setTextColor(ContextCompat.getColor(context, colorRes));
} else { // you can ignore this branch, because usually there is not the situation
Menu menu = toolbar.getMenu();
MenuItem item = menu.findItem(menuResId);
SpannableString s = new SpannableString(item.getTitle());
s.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, colorRes)), 0, s.length(), 0);
item.setTitle(s);
}
}
});
}