Android 4.0, текст на панели действий НИКОГДА не отображается

Я пытаюсь использовать новые api из google, в частности панель действий.

Когда сборка была установлена ​​на api 10, если я нажал кнопку меню, у меня появились приятные варианты меню, каждый из которых имел изображение и значок. При использовании api 14, независимо от того, что я пытаюсь, он всегда помещает значок в панель действий без текста. Я пробовал все, что мог придумать. Я дал ему свойство «с текстом», изменил текст на один символ (в случае, если это проблема с комнатой), но ничего.

Я видел это раньше, даже в руководстве разработчика в android.developer, но я не могу найти ответ, как КАК заставить его появиться.

Solutions Collecting From Web of "Android 4.0, текст на панели действий НИКОГДА не отображается"

Я подозреваю, что разработчики Android сознательно решили никогда не отображать текст и значок одного элемента меню на узкой панели действий. Но если вы действительно этого хотите, вы можете использовать android: actionLayout в вашем файле menu.xml. Документация Android ActionBar имеет несколько лучшее объяснение.

<?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> 

Затем создайте свой макет 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" /> 

И используйте селектор для своего фона bg_btn_action_bar.xml , поэтому он меняет цвет при нажатии на него:

 <?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> 

Теперь вам нужно, чтобы ваши пользовательские представления обрабатывали события click click. В вашей деятельности мне нравится делать это, чтобы я мог обрабатывать щелчок в onOptionsItemSelected вместе со всеми моими другими нестандартными элементами.

 @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); } 

Это, безусловно, то же самое, что я наблюдал на моем Nexus S, работающем 4.0.4. Мое приложение использует панель действий с несколькими вкладками, которые реализованы как фрагменты. Мои различные фрагменты корректируют параметры меню, отображаемые на панели действий, когда их вкладка видна.

Это похоже на ошибку в ICS, поскольку она выполняется последовательно следующим образом, как на моем Nexus S, так и в эмуляторе (как HVGA, так и WVGA800):

  1. В портретном режиме в верхней строке панели действий отображается моя кнопка «вверх / вниз», во второй строке отображаются вкладки, а любые действия отображаются только в виде значков (без текста) в правой части верхней строки.
  2. Но если при повороте в ландшафт, панель действий сворачивается в одну строку, а вкладки перемещаются вверх по верхней панели в виде прядильного (раскрывающегося списка) рядом с моей кнопкой вверх. Но, в частности, текст появляется рядом с моими значками действий.

Я заметил некоторые другие глюки с помощью счетчика, который заставлял меня поверить, что этот маленький уголок ICS немного грязный / багги. Если я скажу приложению разбить панель действий на узких дисплеях (добавив в манифест android:uiOptions="splitActionBarWhenNarrow" , ICS всегда подталкивает эти элементы к нижней панели, хотя в верхней части еще много места. И даже С дополнительным баром, он все еще не отображает текст, просто значок.

На моем Xoom, работающем 4.0.4, вкладки и элементы действия всегда появляются так, как вы ожидаете, они появятся, потому что есть много места.

Обход проблемы: если вы действительно хотите текст на панели действий в портретном режиме, вам нужно отказаться от значка. Удалите значок из вашего пункта меню и появится текст. Это не совсем то, что нам нужно.

Я разместил здесь отчет об ошибке: https://code.google.com/p/android/issues/detail?id=30180 .

Если вы хотите, чтобы ваше меню параметров отображалось в панели действий с помощью Honeycomb, я сделал следующее:

В вашей деятельности переопределите эту функцию:

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

Где R.menu.actionbar_universe определяет ваш пункт меню следующим образом:

 <?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> 

Обратите внимание на showAsAction = "always | withText" и укажите android: title.

Если у вас есть это и его не работает, скопируйте | вставьте свой ресурс меню здесь.

EDIT: Это отвечает на неправильный вопрос, но это оригинальный текст.

Я использую этот бит кода для установки заголовка панели действий и крашу его красным цветом с логотипом своих компаний. Он хорошо работает в версии 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; } 

Свойство «withText» работает с большинством планшетов, но простой способ получить значки и текст на более мелких устройствах – это добавить текст рядом со значком в виде одного изображения (PNG-файл). Таким образом, текст и значок будут отображаться как один значок, и все это будет отображаться.

Вы можете использовать оригинальный значок для таблеток, используя свойство withText.

  • Вы должны создать дополнительную папку меню в каталоге res под названием «menu-w600dp».

  • Файл optionsmenu.xml в этой папке применим только к ширине экрана больше 600dp (те, которые без проблем отображают значки и текст).

Исправлена ​​ошибка: « Если ваше приложение использует раздел« Библиотека поддержки »в разделе« Указание действий в XML » .

… для совместимости в версиях с Android 2.1 атрибут showAsAction недоступен из пространства имен android: Вместо этого этот атрибут предоставляется библиотекой поддержки, и вы должны определить собственное пространство имен XML и использовать это пространство имен в качестве префикса атрибута. (Пользовательское пространство имен XML должно быть основано на имени вашего приложения, но это может быть любое имя, которое вы хотите, и доступно только в пределах области файла, в котором вы его объявляете.) Например:

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

Если ни одна из этих вещей не работает для вас, это может быть.

Я попробовал много вариантов, и я придумал простой «трюк» без какой-либо странной строки кода, без изображений. И первое решение с пользовательским действиемLayout просто не работало для меня с совместимостью API уровня 10.

Если вы хотите отобразить значок текста И на небольшой панели действий, значит, вы знаете, что у вас есть пространство, верно? Таким образом, вы можете использовать 2 пункта меню:

  • Сначала с иконкой ТОЛЬКО (игнорируйте предупреждение, если вы установите табло заголовка, вы увидите его дважды)
  • Во-вторых, только текст

И при необходимости выберите текстовое действие в «ifRoom», чтобы, если вам нужно место, текст исчезнет. Это займет еще больше места на панели действий, но для меня это был хороший компромисс. Я получаю следующий код:

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

( EDIT, где «pelmel» – ваше имя приложения END EDIT )

И тогда ваш обработчик выбора должен поймать оба идентификатора:

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

Вот еще один вариант, основанный примерно на dgmltn. Преимущества:

  • Больше контроля – например, я поменял текст и изображение в своем макете.
  • Легче использовать – требуется только две дополнительные строки в ваших действиях / фрагментах.
  • Требуется только два дополнительных файла.
  • Возможно, немного правильнее, но это все еще немного взломать IMO.

Я предположил, что вы используете ActionBarSherlock в этом примере. Сначала создайте макет вида, который вы хотите. Это основано на ActionBarSherlock. Все, что я изменил, заключалось в замене изображения / просмотра, уменьшении общего поля / отступов до 0, чтобы они были ближе и разрешали все стили 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> 

Затем создайте соответствующий класс View . Возможно, вы захотите скопировать CapitalizingButton если вас беспокоит использование внутренних вещей. О, также я никогда не фиксировал материал минимальной ширины. Не думайте, что это действительно важно.

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

Хорошо, теперь вы готовы его использовать. В пунктах меню, которые вы хотите иметь текст, вы делаете то же самое, что и 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. 

И, наконец, просто добавьте этот код в свою активность / фрагмент:

 @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); 

Вот и все!