android 4.0, text on the action bar NEVER shows

2019-01-06 09:46发布

I am trying to use the new api's from google, specifically the action bar.

When the build was set at api 10, if I pressed the menu button, I got nice looking menu options, each with a picture and icon. When using api 14, No matter what I try, it always puts the icon in the action bar with NO text. I have tried everything I can think of. I gave it the "with text" property, changed the text to a single character (in case it was a room issue), but nothing.

I have seen this done before, even in the developer guide at android.developer, but I can't seem to find an answer as to HOW to get it to show up.

7条回答
我欲成王,谁敢阻挡
2楼-- · 2019-01-06 10:17

Here's another option, based roughly on dgmltn's. The advantages:

  • More control - e.g. I've swapped the text and image over in my layout.
  • Easier to use - only requires two extra lines in your activities/fragments.
  • Only requires two extra files.
  • Possibly slightly more correct, but it's still a bit of a hack IMO.

I've assumed you're using ActionBarSherlock in this example. First, create the view layout you want. This one is based on ActionBarSherlock's. All I changed was swapping the image/view over, reducing the shared margin/padding to 0 so they are closer, and resolving all the ABS styles.

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

Then create the corresponding View class. You may want to copy CapitalizingButton if you are worried about using internal things. Oh, also I never fixed the minimum width stuff. Don't think it really matters though.

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

}

Ok now you're ready to use it. In your menu items that you want to have text, you do the same as what dgmltn said:

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

And finally, just add this code to your 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);

And that's it!

查看更多
登录 后发表回答