android 4.0,动作栏上的文字永远不会显示

时间:2012-02-14 18:21:12

标签: android android-4.0-ice-cream-sandwich android-actionbar

我正在尝试使用谷歌的新api,特别是动作栏。

当构建设置为api 10时,如果按下菜单按钮,我会看到漂亮的菜单选项,每个选项都带有图片和图标。当使用api 14时,无论我尝试什么,它总是将图标放在操作栏中,没有文字。我已经尝试了我能想到的一切。我给了它“with text”属性,将文本更改为单个字符(如果是房间问题),但没有。

我之前已经看过这个,即使是在android.developer的开发者指南中,但我似乎无法找到答案如何让它出现。

7 个答案:

答案 0 :(得分:83)

我怀疑Android开发人员有意识地决定永远不会在狭窄的操作栏上显示单个菜单项的文本和图标。但如果您真的想这样做,可以在menu.xml文件中使用android:actionLayoutAndroid ActionBar documentation有一个更好的解释。

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

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

答案 1 :(得分:10)

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

这似乎是ICS中的一个错误,因为它在我的Nexus S和仿真器(HVGA和WVGA800)中都表现如下:

  1. 在纵向模式下,我的徽标/向上按钮显示在操作栏的顶行,选项卡显示在第二行,任何操作在顶行的右侧仅显示为图标(无文本)。 / LI>
  2. 但是,当我旋转到横向时,操作栏会折叠到一行,并且标签会作为我的向上按钮旁边的微调器(下拉列表)向上移动到顶部栏。 但值得注意的是,文字会显示在我的操作图标旁边。
  3. 我注意到制表器旋转器的其他一些故障让我相信ICS的这个小角落有点凌乱/错误。如果我告诉应用程序在窄显示屏上拆分操作栏(通过在清单中添加android:uiOptions="splitActionBarWhenNarrow",ICS总是会将这些项目推送到底栏,即使顶部仍有足够的空间。即使是额外的栏,它仍然不显示文字,只显示图标。

    在运行4.0.4的Xoom上,标签和操作项总是以您希望它们出现的方式显示,因为有足够的空间。

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

    我在这里发布了一个错误报告:https://code.google.com/p/android/issues/detail?id=30180

答案 2 :(得分:3)

如果您希望选项菜单显示在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;
}

答案 3 :(得分:3)

“withText”属性适用于大多数平板电脑,但在较小设备上获取图标和文字的简便方法是将图标旁边的文字添加为一个图像(PNG文件)。 这样,文本和图标都将被视为一个图标,整个事物将显示出来。

您可以使用withText属性将平板电脑的原始图标用于。

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

  • 此文件夹中的optionmenu.xml仅适用于大于600dp的屏幕宽度 (那些将显示图标和文字没有问题的那些)。

答案 4 :(得分:1)

通过阅读Specify the Actions in 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>

如果这些其他事情都不适合你,可能会这样做。

答案 5 :(得分:1)

我尝试了很多选项,然后我提出了一个简单的&#34;技巧&#34; 没有任何奇怪的代码行,没有图片。使用自定义actionLayout的第一个解决方案根本不适用于API级别10兼容性。

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

  • 首先只显示图标(忽略警告,如果设置标题,平板电脑会显示两次)
  • 仅限文字

并选择文本操作,以及&#39; ifRoom&#39;如果需要,如果你确实需要空间,文本将会消失。虽然行动吧需要更多的空间,但对我来说这是一个很好的妥协。 我最终得到以下代码:

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

编辑其中&#34; pelmel&#34;是您的应用名称 END EDIT

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

答案 6 :(得分:0)

这是另一个选项,大致基于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.

最后,只需将此代码添加到您的activity / fragment:

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

就是这样!