2012-04-01 4 views
6

ich in einem ungeraden Problem mit Android stecken geblieben - Ich mag einen Knopf haben, die wie folgt aussieht:Android: wie eine Schaltfläche mit Bild und Text erstellen, die sowohl zentriert sind

|-----------------------------------------------------------------------| 
|     [icon] <5px> [text text text]      | 
|-----------------------------------------------------------------------| 

und die Gruppe ([icon] < 5px> [Texttext] sollte zentriert werden. Beachten Sie, dass 5px nur als Platzhalter für alle Abstände verwendet wird, die Sie zwischen dem Symbol und dem Text haben möchten. Ich habe hier einige Antworten gefunden, die mehr oder weniger um einen Hintergrund herumlagen (was ich nicht möchte) tun, weil ich einen anderen Hintergrund habe) oder die Eigenschaft android: drawableLeft verwenden, um das Icon zu setzen.

Allerdings sieht die Dokumentation der setCompoundDrawablesWithIntrinsicBounds-Methode ist ein bisschen irreführend (see here). Es besagt, dass das Bild auf der linken/rechten/oberen/unteren Seite des TEXT platziert wird, was nicht wahr ist. Das Symbol befindet sich auf der entsprechenden Seite der Schaltfläche. Zum Beispiel:

Einstellen des Android: drawableLeft Eigenschaft legt das Symbol auf dem die meisten linken Position und wird mir diese (mit Schwerpunkt):

|-----------------------------------------------------------------------| 
| [icon]      [text text text]       | 
|-----------------------------------------------------------------------| 

oder diese (mit der Schwerkraft links):

|-----------------------------------------------------------------------| 
| [icon] [text text text]            | 
|-----------------------------------------------------------------------| 

Beide sind hässlich wie die Hölle :(

ich eine Abhilfe gefunden, die wie folgt aussieht:

public static void applyTextOffset(Button button, int buttonWidth) { 
    int textWidth = (int) button.getPaint().measureText(button.getText().toString()); 
    int padding = (buttonWidth/2) - ((textWidth/2) + Constants.ICON_WIDTH + Constants.ICON_TO_TEXT_PADDING); 
    button.setPadding(padding, 0, 0, 0); 
    button.setCompoundDrawablePadding(-padding); 
} 

Und es funktioniert mehr oder weniger, aber ich es nicht aus folgenden Gründen nach meinem Geschmack finden:

  • es erfordert die Schaltfläche Breite kennen. Mit automatisch skalierten Tasten ist es nicht bekannt, bis das Layout fertig ist. Google empfiehlt, einen Listener zu verwenden, um die tatsächliche Breite nach dem Rendern zu erfahren, aber dies erschwert den Code immens.
  • Ich fühle mich wie ich über das Layout Verantwortung aus dem Android-Layout-Engine nehme

Gibt es eine elegantere Lösung?

+0

Hoffnung, so dass Sie Sie Problem – Ishu

Antwort

10

Sie können die folgende Button Unterklasse verwenden, um diesen Effekt zu erzielen.

  1. Fügen Sie diese Klasse in Ihr Projekt ein und optimieren Sie den Paketnamen, falls gewünscht.
package com.phillipcalvin.iconbutton; 

    import android.content.Context; 
    import android.content.res.TypedArray; 
    import android.graphics.Rect; 
    import android.graphics.Paint; 
    import android.graphics.drawable.Drawable; 
    import android.util.AttributeSet; 
    import android.widget.Button; 

    public class IconButton extends Button { 
     protected int drawableWidth; 
     protected DrawablePositions drawablePosition; 
     protected int iconPadding; 

     // Cached to prevent allocation during onLayout 
     Rect bounds; 

     private enum DrawablePositions { 
     NONE, 
     LEFT, 
     RIGHT 
     } 

     public IconButton(Context context) { 
     super(context); 
     bounds = new Rect(); 
     } 

     public IconButton(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     bounds = new Rect(); 
     } 

     public IconButton(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     bounds = new Rect(); 
     } 

     public void setIconPadding(int padding) { 
     iconPadding = padding; 
     requestLayout(); 
     } 

     @Override 
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
     super.onLayout(changed, left, top, right, bottom); 

     Paint textPaint = getPaint(); 
     String text = getText().toString(); 
     textPaint.getTextBounds(text, 0, text.length(), bounds); 

     int textWidth = bounds.width(); 
     int contentWidth = drawableWidth + iconPadding + textWidth; 

     int contentLeft = (int)((getWidth()/2.0) - (contentWidth/2.0)); 
     setCompoundDrawablePadding(-contentLeft + iconPadding); 
     switch (drawablePosition) { 
     case LEFT: 
      setPadding(contentLeft, 0, 0, 0); 
      break; 
     case RIGHT: 
      setPadding(0, 0, contentLeft, 0); 
      break; 
     default: 
      setPadding(0, 0, 0, 0); 
     } 
     } 

     @Override 
     public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom) { 
     super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 
     if (null != left) { 
      drawableWidth = left.getIntrinsicWidth(); 
      drawablePosition = DrawablePositions.LEFT; 
     } else if (null != right) { 
      drawableWidth = right.getIntrinsicWidth(); 
      drawablePosition = DrawablePositions.RIGHT; 
     } else { 
      drawablePosition = DrawablePositions.NONE; 
     } 
     requestLayout(); 
     } 
    } 

2. Ändern Sie bitte Ihre Layout dieser neuen Unterklasse zu verwenden, anstatt plain Button:

<com.phillipcalvin.iconbutton.IconButton 
     android:id="@+id/search" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:drawableLeft="@drawable/search" 
     android:text="@string/search" /> 

3. Wenn Sie Polsterung zwischen dem ziehbar und den Text hinzufügen möchten, fügen Sie den folgenden Ihre Tätigkeit des onCreate:

// Anywhere after setContentView(...) 
    IconButton button = (IconButton)findViewById(R.id.search); 
    button.setIconPadding(10); 

Diese Unterklasse unterstützt auch drawableRight. Es unterstützt nicht mehr als einen Zeichensatz.

Wenn Sie mehr Funktionen, wie die Möglichkeit, wollen die iconPadding direkt in Ihrem Layout XML angeben, ich habe eine library that supports this.

-3

ich dies in Eclipse versucht und es spritzte keine Fehler:

<Button android:id="@+id/test" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:background="@android:color/transparent" > 
<LinearLayout 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:layout_weight="1" 
    android:gravity="center" 
    android:background="@android:color/transparent" > 

    </LinearLayout> 
    </Button> 

Deshalb nehme ich Sie ein Bild und Textansichten in einem Layout hinzufügen könnte, selbst in einem Knopf, und in der Mitte das Layout.

Mit freundlichen Grüßen.

+0

nur gelöst hatte es sollte horizontal sein – Gangnus

+0

Ich würde sagen, nya nya nya, wenn Sie nicht vollkommen richtig waren. – pouzzler

+0

Und Sie haben es vertikal :-) – Gangnus

0

Sie können auch eine benutzerdefinierte Ansicht verwenden, um eine benutzerdefinierte Schaltfläche zu erstellen.

Dies könnte von leicht bis extrem komplex sein.

Es wäre einfach, wenn Sie nur onDraw() überschreiben müssen. Es wird komplexer, wenn Sie mehrere Ansichten planen müssen.

+0

Ich werde diese Antwort akzeptieren, weil sie korrekt ist und eine Lösung bietet, obwohl ich nicht sicher bin, ob ich sie als "elegantere" Lösung einstufen kann. Mein Punkt ist, dass es eigentlich ein gesunder Menschenverstand ist, zu erwarten, dass der Text und das Symbol zentriert sind, wenn Sie setGravity (CENTER) aufrufen und benutzerdefinierte Komponenten nur für DAS erstellen, das ein bisschen übertrieben ist. – vap78

0

einfach Art und Weise Knopf in Linearlayout zu schreiben ist. So etwas wie dieses

<LinearLayout 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:gravity="center"> 

      <Button 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:drawableLeft="@drawable/ic_left" 
       android:drawablePadding="5dp" 
       android:duplicateParentState="true" 
       android:text="Button text"/> 

     </LinearLayout> 
Verwandte Themen