2012-04-01 13 views
6

sono rimasto bloccato in un numero dispari con Android - voglio avere un pulsante che assomiglia a questo:Android: come creare un pulsante con immagine e testo che sono entrambi centrati

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

e il gruppo ([icona] < 5px> [testo testo testo]) dovrebbe essere centrato. Notare che 5px è usato solo come segnaposto per qualsiasi padding che si desidera avere tra l'icona e il testo

Ho trovato qui alcune risposte che erano più o meno gravitanti attorno ad entrambi impostando uno sfondo (che non voglio fare perché ho un altro background) o utilizzare la proprietà android: drawableLeft per impostare l'icona.

Tuttavia sembra che la documentazione del metodo setCompoundDrawablesWithIntrinsicBounds sia un po 'ingannevole (see here). Indica che l'immagine è posizionata sul lato sinistro/destro/alto/basso del TEXT che non è vero. L'icona è posizionata sul lato corrispondente del BUTTON. Per esempio:

Impostazione del android: drawableLeft proprietà mette l'icona sulla posizione più a sinistra e mi fa questo (con centro di gravità):

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

o del presente (con la gravità SINISTRA):

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

Entrambi sono brutto come l'inferno :(

ho trovato una soluzione che assomiglia a questo:

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

E funziona più o meno, ma io non lo trovo di mio gradimento per le seguenti ragioni:

  • si richiede di conoscere la larghezza tasto. Con i pulsanti di dimensioni automatiche non sarà noto fino a quando non verrà eseguito il layout effettivo. Google consiglia di utilizzare un listener per apprendere la larghezza effettiva dopo il rendering, ma ciò complica enormemente il codice.
  • mi sento come sto prendendo la responsabilità layout dal motore di layout di Android

non c'è una soluzione più elegante?

+0

Speranza in modo da aveste risolto problema – Ishu

risposta

10

Per ottenere questo effetto è possibile utilizzare la seguente sottoclasse Button.

  1. Incolla questa classe nel progetto e modifica il nome del pacchetto se lo desideri.
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. Modificare il layout di utilizzare questo nuovo sottoclasse invece di pianura 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. Se si desidera aggiungere imbottitura tra il drawable e il testo, aggiungere il seguente del onCreate vostra attività:

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

Questa sottoclasse supporta anche drawableRight. Non supporta più di un drawable.

Se vuoi più funzionalità, come la possibilità di specificare il iconPadding direttamente nel layout XML, ho un library that supports this.

-3

Ho provato questo in Eclipse e becco errori:

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

Pertanto, suppongo che si possa aggiungere un vista di immagine e testo in un layout, per sé all'interno di un pulsante, e il centro di layout.

Cordiali saluti.

+0

Solo dovrebbe essere orizzontale – Gangnus

+0

direi Nya Nya Nya, se non eri perfettamente ragione. – pouzzler

+0

E tu hai verticale :-) – Gangnus

0

Si può anche considerare l'utilizzo di una vista personalizzata per creare un pulsante personalizzato.

Questo può essere ovunque, da facile a estremamente complesso.

Sarebbe facile se tutto ciò che devi fare è ignorare onDraw(). Sarà più complesso se è necessario disporre più viste.

+0

Accetterò questa risposta perché è corretta e fornisce una soluzione, anche se non sono sicuro di poterla classificare come una soluzione "più elegante". Il mio punto è che in realtà è un buon senso aspettarsi che il testo e l'icona siano centrati quando si chiama setGravity (CENTER) e la creazione di componenti personalizzati solo per THAT è un po 'eccessivo. – vap78

0

Semplicemente modo è quello di scrivere Button nella LinearLayout. Qualcosa di simile

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