Android 4.0,操作栏上的文字从不显示

我试图从谷歌使用新的API,特别是操作栏。

当构build被设置为api 10时,如果我按下菜单button,我有很好看的菜单选项,每个选项都有一个图片和图标。 当使用api 14时,无论我尝试什么,它总是将图标放在操作栏中,没有文字。 我尝试了所有我能想到的。 我给了它“带有文本”的属性,将文本改为单个字符(如果是房间问题),但什么也不是。

我曾经见过这样做,即使在android.developer开发者指南,但我似乎无法find一个答案,如何得到它显示。

我怀疑这是Android开发者有意识的决定,不要在狭窄的操作栏上显示单个菜单项的文本和图标。 但是,如果你真的想这样做,你可以在你的menu.xml文件中使用android:actionLayout 。 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> 

然后创build你的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使用一个select器,所以当你点击它时它会改变颜色:

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

现在你需要使你的自定义视图处理点击事件。 在您的活动中,我喜欢这样做,以便我可以处理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); } 

这与我在运行4.0.4的Nexus S上观察到的情况完全相同。 我的应用程序使用一个操作栏和几个作为片段实现的选项卡。 我的各种片段可以调整显示在操作栏上的菜单选项,而其选项卡可见。

这似乎是ICS中的一个错误,因为它在我的Nexus S和模拟器(包括HVGA和WVGA800)上的执行过程如下:

  1. 在纵向模式下,我的标志/向上button出现在操作栏的最上面一行,选项卡出现在第二行,任何操作在最上面一行的右侧都显示为图标(没有文字)。
  2. 但是如果当我旋转到横向时,操作栏会折叠到一行,并且标签会移动到顶部的横条,作为微调(下拉列表)旁边的向上button。 但值得注意的是,文本出现在我的动作图标旁边。

我注意到其他的一些小问题,使我相信ICS的这个小angular落有点麻烦。 如果我告诉应用程序在狭窄的显示器上拆分操作栏(在清单中添加android:uiOptions="splitActionBarWhenNarrow" ,ICS始终将这些项目推到底部栏,尽pipe顶部仍有足够的空间。与额外的酒吧,它仍然不显示文字,只是图标。

在运行4.0.4的我的Xoom上,标签和操作项目总是以您期望的方式出现,因为有足够的空间。

解决方法:如果您确实需要在纵向模式下操作栏上的文本,则需要放弃该图标。 从菜单项中删除图标,文本将出现。 这并不完全是我们所追求的。

我在这里发布了一个错误报告: 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。

如果你有这个,它不工作,请复制|粘贴你的菜单资源在这里。

编辑:这回答错误的问题,但它是原始文本。

我使用这些代码来设置操作栏的标题,并用我的公司标志将其涂成红色。 它在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属性使用平板电脑的原始图标。

  • 你必须在名为“menu-w600dp”的res目录中创build一个额外的菜单文件夹。

  • 这个文件夹中的optionmenu.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> 

如果这些其他的东西都不适合你,这可能。

我尝试了很多select,我想出了一个简单的“技巧”, 没有任何怪异的代码, 没有图像。 与自定义actionLayout的第一个解决scheme根本不适合我的API级别10兼容性。

如果你想在小动作栏上显示文字和图标,这意味着你知道你有空间,对吧? 所以你可以使用2个菜单项:

  • 首先只有图标(忽略警告,如果您设置标题,平板电脑将显示两次)
  • 其次与文本只

如果需要的话,select“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> 

编辑其中“pelmel”是你的应用程序名称结束编辑

然后你的select处理程序只需要捕获两个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; } } 

这是另一个选项,大致基于dgmltn的。 优点:

  • 更多的控制 – 例如,我已经在我的布局中交换了文本和图像。
  • 更易于使用 – 只需要在活动/片段中添加两行。
  • 只需要两个额外的文件。
  • 可能稍微更正确一点,但这仍然是一个黑客国际海事组织。

我假设你在这个例子中使用了ActionBarSherlock。 首先,创build你想要的视图布局。 这个是基于ActionBarSherlock的。 所有我改变的是交换图像/视图,减less共享边距/填充为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> 

然后创build相应的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); 

而就是这样!