wake-up-neo.com

android 4.0, Text in der Aktionsleiste wird NIE angezeigt

Ich versuche, die neuen APIs von Google zu verwenden, insbesondere die Aktionsleiste.

Als der Build auf API 10 eingestellt war und ich die Menütaste gedrückt habe, habe ich gut aussehende Menüoptionen mit jeweils einem Bild und einem Symbol erhalten. Bei Verwendung von API 14 wird unabhängig von meinem Versuch immer das Symbol in der Aktionsleiste ohne Text angezeigt. Ich habe alles versucht, was mir einfällt. Ich gab ihm die Eigenschaft "with text", änderte den Text in ein einzelnes Zeichen (falls es sich um ein Raumproblem handelte), aber nichts.

Ich habe dies schon einmal gesehen, sogar im Entwicklerhandbuch von Android.developer, aber ich kann anscheinend keine Antwort darauf finden, wie es angezeigt werden soll.

59
BriCo84

Ich vermute, dass es eine bewusste Entscheidung der Android) Entwickler war, niemals den Text und das Symbol eines einzelnen Menüelements in einer schmalen Aktionsleiste anzuzeigen. Aber wenn Sie das wirklich wollen, können Sie Folgendes verwenden: Android: actionLayout in Ihrer menu.xml-Datei Die Android ActionBar-Dokumentation hat eine etwas bessere Erklärung.

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

Dann erstelle dein action_button_foo.xml Layout:

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

und benutze einen Selektor als Hintergrund bg_btn_action_bar.xml, so ändert sich die Farbe, wenn Sie darauf tippen:

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

Jetzt müssen Sie festlegen, dass Ihre benutzerdefinierte Ansicht Klickereignisse verarbeitet. In Ihrer Aktivität mache ich das gerne, damit ich den Klick in onOptionsItemSelected zusammen mit all meinen anderen, nicht benutzerdefinierten Elementen verarbeiten kann.

@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

Dies ist definitiv dasselbe, was ich auf meinem Nexus S mit 4.0.4 beobachtet habe. Meine App verwendet eine Aktionsleiste mit mehreren Registerkarten, die als Fragmente implementiert sind. Meine verschiedenen Fragmente nehmen Anpassungen an den Menüoptionen vor, die in der Aktionsleiste angezeigt werden, während deren Registerkarte sichtbar ist.

Dies scheint ein Fehler in ICS zu sein, da es sowohl auf meinem Nexus S als auch im Emulator (sowohl HVGA als auch WVGA800) folgende konsistente Leistung erbringt:

  1. Im Hochformat wird in der oberen Reihe der Aktionsleiste die Schaltfläche "Mein Logo/Auf" angezeigt, in der zweiten Reihe werden Registerkarten angezeigt und alle Aktionen werden nur als Symbole (ohne Text) rechts in der oberen Reihe angezeigt.
  2. Wenn ich mich jedoch in das Querformat drehe, wird die Aktionsleiste zu einer einzelnen Zeile zusammengeklappt und die Registerkarten werden als Drehfeld (Dropdown-Liste) neben meiner Aufwärtsschaltfläche in die obere Leiste verschoben. Dann erscheint aber vor allem der Text neben meinen Aktionssymbolen.

Ich bemerkte einige andere Pannen mit dem Tab-Spinner, die mich glauben ließen, dass diese kleine Ecke von ICS ein bisschen chaotisch/fehlerhaft ist. Wenn ich der Anwendung befehle, die Aktionsleiste auf schmalen Displays zu teilen ( beim Hinzufügen Android:uiOptions="splitActionBarWhenNarrow" im Manifest schiebt ICS immer diese Elemente in die untere Leiste, obwohl oben noch genügend Platz vorhanden ist. Und selbst mit der zusätzlichen Leiste wird das nicht angezeigt Text, nur das Symbol.

Auf meinem Xoom 4.0.4 werden Registerkarten und Aktionselemente immer so angezeigt, wie Sie es erwarten würden, da genügend Platz vorhanden ist.

Workaround: Wenn Sie im Hochformat wirklich Text in der Aktionsleiste haben möchten, müssen Sie das Symbol aufgeben. Entfernen Sie das Symbol aus Ihrem Menüpunkt und der Text wird angezeigt. Dies ist jedoch nicht genau das, wonach wir suchen.

Ich habe hier einen Fehlerbericht gepostet: https://code.google.com/p/Android/issues/detail?id=3018 .

10
Steve Liddle

Die "withText" -Eigenschaft funktioniert mit den meisten Tablets. Eine einfache Möglichkeit, Symbole und Text auf kleineren Geräten abzurufen besteht darin, den Text neben dem Symbol als ein Bild (PNG-Datei) hinzuzufügen. Auf diese Weise werden sowohl der Text als auch das Symbol als ein Symbol angezeigt.

Sie können das ursprüngliche Symbol für Tablets mithilfe der withText-Eigenschaft verwenden.

  • Sie müssen einen zusätzlichen Menüordner im res-Verzeichnis mit dem Titel "menu-w600dp" erstellen.

  • Die Datei optionmenu.xml in diesem Ordner gilt nur für Bildschirmbreiten von mehr als 600 dpi (diejenigen, bei denen die Symbole und der Text ohne Probleme angezeigt werden).

3
Lukos

Wenn Sie möchten, dass Ihr Optionsmenü in Ihrer Aktionsleiste mit Honeycomb angezeigt wird, habe ich Folgendes ausgeführt:

Überschreiben Sie in Ihrer Aktivität diese Funktion:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.actionbar_universe, menu);
    return true;
}

wo R.menu.actionbar_universe definieren Sie Ihren Menüpunkt wie folgt:

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

Beachten Sie showAsAction = "always | withText" und geben Sie Android: title an.

Wenn Sie das haben und es nicht funktioniert, kopieren Sie | fügen Sie Ihre Menüressource hier ein.

EDIT: Dies beantwortet die falsche Frage, aber es ist der Originaltext.

Mit diesem Code setze ich den Titel der Aktionsleiste und male ihn rot mit dem Logo meines Unternehmens. Es funktioniert gut in 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

Ich habe viele Optionen ausprobiert und mir einen einfachen "Trick" ausgedacht ohne jede seltsame Codezeile ohne Bilder. Und die erste Lösung mit benutzerdefiniertem ActionLayout hat bei mir mit API Level 10-Kompatibilität einfach nicht funktioniert.

Wenn Sie Text UND Symbol in einer kleinen Aktionsleiste anzeigen möchten, bedeutet dies, dass Sie wissen, dass Sie über ausreichend Platz verfügen, oder? Sie können also 2 Menüpunkte verwenden:

  • Zuerst NUR mit dem Symbol (Warnung ignorieren, wenn Sie einen Titel festlegen, wird er zweimal angezeigt)
  • Zweitens nur mit dem Text

Wählen Sie bei Bedarf die Textaktion "ifRoom", damit der Text nicht mehr angezeigt wird, wenn Sie Platz benötigen. Es wird zwar etwas mehr Platz in der Aktionsleiste beanspruchen, war aber ein guter Kompromiss für mich. Am Ende habe ich folgenden Code:

<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 Wobei "pelmel" der Name Ihrer App ist END EDIT)

Und dann muss Ihr Auswahl-Handler nur noch beide IDs fangen:

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

Behebung des Problems durch Lesen des Abschnitts " Wenn Ihre App die Support-Bibliothek verwendet " unter Geben Sie die Aktionen in XML an .

... aus Gründen der Kompatibilität für Versionen ab Android 2.1) ist das Attribut showAsAction nicht im Namespace Android: verfügbar. Stattdessen wird dieses Attribut von der Support-Bibliothek bereitgestellt, und Sie müssen Definieren Sie Ihren eigenen XML-Namespace und verwenden Sie diesen Namespace als Attributpräfix. (Ein benutzerdefinierter XML-Namespace sollte auf dem Namen Ihrer App basieren. Er kann jedoch beliebig sein und ist nur innerhalb des Bereichs der Datei zugänglich, in der Sie ihn deklarieren .) Zum Beispiel:

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

Wenn keines dieser anderen Dinge für Sie funktioniert, kann dies sein.

1
ejb

Hier ist eine weitere Option, die grob auf dgmltns basiert. Die Vorteile:

  • Mehr Kontrolle - z. Ich habe den Text und das Bild in meinem Layout vertauscht.
  • Einfacher zu bedienen - erfordert nur zwei zusätzliche Zeilen in Ihren Aktivitäten/Fragmenten.
  • Benötigt nur zwei zusätzliche Dateien.
  • Möglicherweise etwas korrekter, aber es ist immer noch ein bisschen Hack IMO.

Ich habe angenommen, dass Sie in diesem Beispiel ActionBarSherlock verwenden. Erstellen Sie zunächst das gewünschte Ansichtslayout. Dieser basiert auf dem von ActionBarSherlock. Alles, was ich geändert habe, war, das Bild/die Ansicht zu vertauschen, den gemeinsamen Rand/den Abstand auf 0 zu reduzieren, damit sie näher sind, und alle ABS-Stile aufzulösen.

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

Erstellen Sie dann die entsprechende Klasse View. Möglicherweise möchten Sie CapitalizingButton kopieren, wenn Sie Bedenken haben, interne Dinge zu verwenden. Oh, ich habe auch nie die Mindestbreite festgelegt. Glaube aber nicht, dass es wirklich wichtig ist.

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, jetzt können Sie es verwenden. In Ihren Menüpunkten, die Sie mit Text versehen möchten, tun Sie dasselbe, was dgmltn gesagt hat:

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

Und schließlich fügen Sie einfach diesen Code zu Ihrer Aktivität/Ihrem Fragment hinzu:

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

Und das ist es!

0
Timmmm