【问题标题】:android 4.0, text on the action bar NEVER showsandroid 4.0,操作栏上的文字从不显示
【发布时间】:2012-02-14 18:21:11
【问题描述】:

我正在尝试使用来自 google 的新 api,特别是操作栏。

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

我之前已经看到过这样做,甚至在 android.developer 的开发人员指南中,但我似乎无法找到关于如何让它显示的答案。

【问题讨论】:

  • 您可以为活动显示您的 menu.xml 吗?我可能有一个解决方案

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


【解决方案1】:

我怀疑 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);
}

【讨论】:

  • 如果你使用 ActionBarSherlock,@color/ 和 @dimen/ 会有一些以 "abs__" 开头的选项。这些是 ActionBarSherlock 使用的值;您可以使用它们使您的自定义布局看起来正确。例如,您希望 @color/abs__holo_blue_light 作为高亮颜色。
  • 这种方法非常简单,但要使样式恰到好处却很棘手。我找到了 ABS 中使用的样式属性,因此它与本机样式相同。我把它放在这个要点中,以防其他人觉得它有用:gist.github.com/marczych/6908324
  • 你救了我的命,希望我能给你 10 票。
【解决方案2】:

这绝对是我在运行 4.0.4 的 Nexus S 上观察到的情况。我的应用程序使用带有多个选项卡的操作栏,这些选项卡作为片段实现。当标签可见时,我的各种片段会调整操作栏上显示的菜单选项。

这似乎是 ICS 中的一个错误,因为它在我的 Nexus S 和模拟器(HVGA 和 WVGA800)上的性能始终如一:

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

我注意到选项卡微调器的其他一些故障让我相信 ICS 的这个小角落有点混乱/错误。如果我告诉应用程序在窄显示器上拆分操作栏(通过在清单中添加android:uiOptions="splitActionBarWhenNarrow",ICS 总是将这些项目推到底部栏,即使顶部仍有足够的空间。即使有额外的栏,它仍然不显示文本,只显示图标。

在我运行 4.0.4 的 Xoom 上,选项卡和操作项总是以您期望的方式显示,因为有足够的空间。

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

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

【讨论】:

    【解决方案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;
    }
    

    【讨论】:

    • 谢谢,但这不是设置操作栏的主标题吗?我希望显示每个菜单项的文本。即......我有一个带有扳手图标的菜单项“首选项”,以及一个带有+号图标的菜单项“添加”。我希望每个项目都显示图标和文本。相反,我在操作栏的左下角(屏幕底部)和右下角的 + 符号中看到了扳手的图片。没有文字。如果我使用姜饼运行,然后按菜单按钮,我会看到两个选项都弹出文本和图标......就像它应该的那样。
    • 你说得对,我误会了。我将再次回答我如何在操作栏中同时显示文本和图标。
    • 是的,我有这些设置,但仍然无法正常工作。这是我的 xml schemas.android.com/apk/res/android" >
    • android:icon="@android:drawable/ic_menu_manage" android:title="@string/menu_settings" android:showAsAction="always|withText"/>
    • 请注意,这是针对运行 android 4.03 的智能手机。不是平板电脑。我敢打赌它可以在平板电脑上使用,但由于某种原因它不能在手机上使用。
    【解决方案4】:

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

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

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

    • 此文件夹中的 optionmenu.xml 仅适用于大于 600dp 的屏幕宽度 (可以毫无问题地显示图标和文本的那些)。

    【讨论】:

    • 很遗憾,如果您正在实施本地化,这不是一个解决方案
    • @jaseelder 您只需要以与以前相同的方式实现本地化,但现在使用图像而不是文本。我想这个问题现在可能已经解决了。
    【解决方案5】:

    通过阅读Specify the Actions in XML 下的“如果您的应用正在使用支持库”部分修复了此问题。

    ...为了兼容低至 Android 2.1 的版本,android: 命名空间中不提供 showAsAction 属性。相反,此属性由支持库提供,您必须定义自己的 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>
    

    如果这些其他方法都不适合你,这可能。

    【讨论】:

      【解决方案6】:

      我尝试了很多选项,最后想出了一个简单的“技巧”没有任何奇怪的代码行,没有图像。使用自定义 actionLayout 的第一个解决方案根本不适用于我的 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

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

      【讨论】:

      • 我尝试了这种方法,但是 ActionBar 在项目之间放置的分隔线使它们看起来不相交。不过感谢您的建议。
      • 我编辑了我的答案以添加这种精确度,谢谢!
      【解决方案7】:

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

      就是这样!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-28
        • 2017-02-28
        • 1970-01-01
        相关资源
        最近更新 更多