web-dev-qa-db-ja.com

android 4.0、アクションバーのテキストは決して表示されない

Googleの新しいAPI、特にアクションバーを使用しようとしています。

ビルドがapi 10に設定されたときに、メニューボタンを押すと、素敵な外観のメニューオプションがあり、それぞれに画像とアイコンがありました。 API 14を使用する場合、何を試しても、常にテキストなしでアイコンがアクションバーに配置されます。私は考えられるすべてを試しました。 「テキスト付き」プロパティを指定し、テキストを1文字に変更しました(部屋の問題の場合)が、何もしませんでした。

これは、Android.developerの開発者ガイドでも前に見たことがありますが、それを表示する方法についての答えは見つかりません。

59
BriCo84

狭いアクションバーに単一のメニュー項目のテキストとアイコンを表示しないことは、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>

次に、カスタムビューでクリックイベントを処理できるようにする必要があります。アクティビティでは、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);
}
83
dgmltn

これは、4.0.4を実行しているNexus Sで確認したこととまったく同じです。私のアプリは、フラグメントとして実装されるいくつかのタブを持つアクションバーを使用します。私のさまざまなフラグメントは、タブが表示されている間にアクションバーに表示されるメニューオプションを調整します。

これは、Nexus Sとエミュレーター(HVGAとWVGA800の両方)で次のように一貫して実行されるため、ICSのバグのようです。

  1. ポートレートモードでは、ロゴ/アップボタンがアクションバーの一番上の行に表示され、タブが2番目の行に表示され、すべてのアクションは一番上の行の右側にアイコンのみ(テキストなし)として表示されます。
  2. ただし、横向きに回転すると、アクションバーが1行に折りたたまれ、上ボタンの横にあるスピナー(ドロップダウンリスト)としてタブが上バーに移動します。 ただし、特に、アクションアイコンの横にテキストが表示されます。

タブスピナーのその他の不具合に気付き、このICSの小さな角は少し乱雑/バギーです。アプリケーションに狭いディスプレイでアクションバーを分割するように指示した場合( Android:uiOptions="splitActionBarWhenNarrow"をマニフェストに追加することにより、ICSは、上部にまだ十分なスペースがあるにもかかわらず、それらのアイテムを常に下部のバーにプッシュします。テキストは表示されず、アイコンのみが表示されます。

4.0.4を実行しているXoomでは、十分なスペースがあるため、タブとアクションアイテムは常に期待どおりに表示されます。

回避策:ポートレートモードでアクションバーにテキストが本当に必要な場合は、アイコンを放棄する必要があります。メニュー項目からアイコンを削除すると、テキストが表示されます。しかし、これは私たちが望んでいることとはまったく異なります。

バグレポートをここに投稿しました: https://code.google.com/p/Android/issues/detail?id=3018

10
Steve Liddle

「withText」プロパティは、ほとんどのタブレットで動作しますただし、小さなデバイスでアイコンとテキストを取得する簡単な方法は、アイコンの横にテキストを1つの画像(PNGファイル)として追加することです。これにより、テキストとアイコンの両方が1つのアイコンとして表示され、全体が表示されます。

WithTextプロパティを使用して、タブレットの元のアイコンを使用できます。

  • 「menu-w600dp」というタイトルのresディレクトリに追加のメニューフォルダーを作成する必要があります。

  • このフォルダー内のoptionmenu.xmlは、600dpを超える画面幅(アイコンとテキストを問題なく表示するもの)にのみ適用されます。

3
Lukos

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
knaak

私は多くのオプションを試しましたが、単純な「トリック」を思いつきましたwithout奇妙なコード行、without画像。また、カスタムactionLayoutを使用した最初のソリューションは、APIレベル10の互換性では動作しませんでした。

小さなアクションバーにテキストとアイコンを表示したい場合、スペースがあることを知っていますか?したがって、2つのメニュー項目を使用できます。

  • 最初はアイコンのみ(警告を無視、タイトルを設定するとタブレットは2回表示します)
  • 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;
    }
}
1

この問題を修正するには、「アプリでサポートライブラリを使用している場合」 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>

これらの他のもののどれもあなたのために働かない場合、これはかもしれない。

1
ejb

Dgmltnにほぼ基づいた別のオプションがあります。利点:

  • より詳細な制御-例レイアウトでテキストと画像を入れ替えました。
  • 使いやすく-アクティビティ/フラグメントに2行追加するだけです。
  • 2つの追加ファイルのみが必要です。
  • おそらく少し正確ですが、それはまだ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);

以上です!

0
Timmmm