Come centrare l'icona e il testo in un pulsante Android con larghezza impostata su "riempimento genitore"


118

Voglio avere un pulsante Android con icona + testo centrato al suo interno. Sto usando l'attributo drawableLeft per impostare l'immagine, funziona bene se il pulsante ha una larghezza di "wrap_content"ma ho bisogno di allungare alla larghezza massima, quindi uso la larghezza "fill_parent". Questo sposta la mia icona direttamente a sinistra del pulsante e voglio che sia l'icona che il testo siano centrati all'interno del pulsante.

Ho provato a impostare il padding ma questo mi permette solo di dare un valore fisso quindi non è quello che mi serve. Devo avere icona + testo allineati al centro.

<Button 
    android:id="@+id/startTelemoteButton" 
    android:text="@string/start_telemote"
    android:drawableLeft="@drawable/start"
    android:paddingLeft="20dip"
    android:paddingRight="20dip"            
    android:width="fill_parent"
    android:heigh="wrap_content" />

Qualche suggerimento su come potrei farlo?


Possibile che non ci sia una soluzione facile per questo? Devo provare con un pulsante 9patch img con l'icona lì dentro?
jloriente

Questa potrebbe essere una soluzione. Il testo del pulsante sarà localizzato o statico?
Octavian A. Damiean

È localizzato. Non c'è altra soluzione per questo? Sono riuscito a farlo con una patch 9 ma ho avuto problemi nel cambiare locale.
jloriente

Che ne dici di usare un pulsante con TOP estraibile e aggiungere un po 'di imbottitura?
Francesco

cattivo design del quadro
Muhammad Babar

Risposte:


75

android: drawableLeft mantiene sempre android: paddingLeft come una distanza dal bordo sinistro. Quando il pulsante non è impostato su android: width = "wrap_content", rimarrà sempre a sinistra!

Con Android 4.0 (livello API 14) puoi utilizzare l' attributo android: drawableStart per posizionare un oggetto disegnabile all'inizio del testo. L'unica soluzione compatibile con le versioni precedenti che ho escogitato è usare un ImageSpan per creare un testo + immagine spannabile:

Button button = (Button) findViewById(R.id.button);
Spannable buttonLabel = new SpannableString(" Button Text");
buttonLabel.setSpan(new ImageSpan(getApplicationContext(), R.drawable.icon,      
    ImageSpan.ALIGN_BOTTOM), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
button.setText(buttonLabel);

Nel mio caso avevo bisogno di regolare anche l'attributo android: gravity del Button per farlo sembrare centrato:

<Button
  android:id="@+id/button"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:minHeight="32dp"
  android:minWidth="150dp"
  android:gravity="center_horizontal|top" />

Bello. L'ultima riga dovrebbe esserebutton.setText(buttonLabel)
AlexD

1
Unicode ha un ampio set di icone di caratteri compatibili con le stringhe in Android. Se riesci a trovarne uno accettabile, questa è una soluzione semplice e ha il vantaggio aggiuntivo che si ridimensionerà con le dimensioni del testo. Ad esempio, ha una busta per un'icona di posta elettronica e un paio di telefoni diversi per un pulsante di chiamata.
GLee

1
Sono confuso come ha funzionato per chiunque, per me disegna 2 icone ... un modo a sinistra e uno direttamente al centro che viene visualizzato sopra il testo.
Justin

11
drawableStart non funzionerà. Vedi questo thread: stackoverflow.com/questions/15350990/… Inoltre, sembra che quando imposti il ​​testo usando uno spannabile, lo stile viene ignorato.
Dapp

11
drawableStart non funziona ed è stato aggiunto nel livello API 17 per supportare rtl
Silvia H

35

So di essere in ritardo nel rispondere a questa domanda, ma questo mi ha aiutato:

<FrameLayout
            android:layout_width="match_parent"
            android:layout_height="35dp"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="10dp"
            android:background="@color/fb" >

            <Button
                android:id="@+id/fbLogin"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:background="@null"
                android:drawableLeft="@drawable/ic_facebook"
                android:gravity="center"
                android:minHeight="0dp"
                android:minWidth="0dp"
                android:text="FACEBOOK"
                android:textColor="@android:color/white" />
        </FrameLayout>

Ho trovato questa soluzione da qui: L' interfaccia utente di Android fatica: creare un pulsante con testo e icona centrati

inserisci qui la descrizione dell'immagine


6
Il problema con questo è che il pulsante non è la larghezza del layout della cornice.
Clive Jefferies

29

Ho usato LinearLayout invece di Button . L'OnClickListener , che ho bisogno di usare funziona bene anche per LinearLayout.

<LinearLayout
    android:id="@+id/my_button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/selector"
    android:gravity="center"
    android:orientation="horizontal"
    android:clickable="true">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="15dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:src="@drawable/icon" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Text" />

</LinearLayout>

29

Tutte le risposte precedenti sembrano essere obsolete

È possibile utilizzare MaterialButtonadesso che consente di impostare la gravità dell'icona.

 <com.google.android.material.button.MaterialButton
        android:id="@+id/btnDownloadPdf"
        android:layout_width="0dp"
        android:layout_height="56dp"
        android:layout_margin="16dp"
        android:gravity="center"
        android:textAllCaps="true"
        app:backgroundTint="#fc0"
        app:icon="@drawable/ic_pdf"
        app:iconGravity="textStart"
        app:iconPadding="10dp"
        app:iconTint="#f00"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:text="Download Pdf" />

inserisci qui la descrizione dell'immagine

Ovviamente per l'utilizzo dei componenti materiali sarà necessario:

Aggiungi una dipendenza implementation 'com.google.android.material:material:1.3.0-alpha01'(usa la versione più recente)

Fai in modo che il tuo tema estenda il tema dei componenti materiali

<style name="AppTheme" parent="Theme.MaterialComponents.Light">
...
</style>

Nel caso non sia possibile farlo, estenderlo dal tema Material Bridge

<style name="AppTheme" parent="Theme.MaterialComponents.Light.Bridge">
...
</style>

Grazie! Mi hai salvato la giornata! Funziona bene
Black_Zerg

9

Lo aggiusto aggiungendo imbottitura sinistra e destra come segue:

<Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/btn_facebookact_like"
            android:text="@string/btn_facebookact_like"
            android:textColor="@color/black"
            android:textAllCaps="false"
            android:background="@color/white"
            android:drawableStart="@drawable/like"
            android:drawableLeft="@drawable/like"
            android:gravity="center"
            android:layout_gravity="center"
            android:paddingLeft="40dp"
            android:paddingRight="40dp"
            />

Il paddingLeft e il paddingRight mi hanno aiutato con la centratura. voto positivo per una soluzione semplice.
Arrie

2
Come gestisci il fatto che la tua larghezza sia dinamica? Se ruoti lo schermo, tutte le tue icone non saranno centrate, giusto? In realtà sto affrontando questo problema
Jacks

questa è la risposta migliore!
Dody Rachmat Wicaksono

8

Recentemente mi sono imbattuto nello stesso problema. Ho cercato di trovare una soluzione più economica, quindi ho pensato a questo.

   <LinearLayout
        android:id="@+id/linearButton"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/selector_button_translucent_ab_color"
        android:clickable="true"
        android:descendantFocusability="blocksDescendants"
        android:gravity="center"
        android:orientation="horizontal" >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/app_name"
            android:textColor="@android:color/white" />
    </LinearLayout>

Allora chiama l' OnClickListeneron LinearLayout.

Spero che questo aiuti qualcuno in quanto sembra un problema molto comune. :)


1
Questa è una buona idea, ma una cattiva soluzione. Puoi ottenere la stessa cosa con un solo TextView usando l'attributo drawableLeft. Ciò consente di visualizzare un disegnabile a sinistra del testo.
muetzenflo

@muetzenflo yup, è vero. ma quando fai corrispondere la textView alla larghezza principale, il tuo disegnabile si sposterà all'estrema sinistra anche se centrerai il testo. per favore fatemi sapere se sbaglio. e la domanda riguarda solo questo.
Ankit Popli

ah scusa .. sono venuto qui esattamente per questo problema e ho perso la concentrazione dopo aver provato troppe cose :) Immagino di non aver visto la foresta per gli alberi. Colpa mia!
muetzenflo

7

È possibile utilizzare un pulsante personalizzato che misura e disegna se stesso per accogliere un disegnabile a sinistra. Si prega di trovare esempio e utilizzo qui

public class DrawableAlignedButton extends Button {

    public DrawableAlignedButton(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public DrawableAlignedButton(Context context) {
    super(context);
}

public DrawableAlignedButton(Context context, AttributeSet attrs, int style) {
    super(context, attrs, style);
}

private Drawable mLeftDrawable;

@Override
    //Overriden to work only with a left drawable.
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left,
        Drawable top, Drawable right, Drawable bottom) {
    if(left == null) return;
    left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight());
    mLeftDrawable = left;
}

@Override
protected void onDraw(Canvas canvas) {
    //transform the canvas so we can draw both image and text at center.
    canvas.save();
    canvas.translate(2+mLeftDrawable.getIntrinsicWidth()/2, 0);
    super.onDraw(canvas);
    canvas.restore();
    canvas.save();
    int widthOfText = (int)getPaint().measureText(getText().toString());
    int left = (getWidth()+widthOfText)/2 - mLeftDrawable.getIntrinsicWidth() - 2;
    canvas.translate(left, (getHeight()-mLeftDrawable.getIntrinsicHeight())/2);
    mLeftDrawable.draw(canvas);
    canvas.restore();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int height = getMeasuredHeight();
    height = Math.max(height, mLeftDrawable.getIntrinsicHeight() + getPaddingTop() + getPaddingBottom());
    setMeasuredDimension(getMeasuredWidth(), height);
}
}

uso

<com.mypackage.DrawableAlignedButton
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:drawableLeft="@drawable/my_drawable"
        android:gravity="center"
        android:padding="7dp"
        android:text="My Text" />

Puoi includere il codice nella tua risposta, che dovrebbe essere il modo preferito (se non è troppo lungo), poiché i collegamenti potrebbero morire nel tempo-
Lukas Knuth

2
Non molto preciso ma
presumo

Sposta un testo a destra, ma non abbastanza (un'immagine si sovrappone al testo). Inoltre, come altre soluzioni di visualizzazione personalizzata, non accetta testo lungo correttamente.
CoolMind

5

Questa è la mia soluzione che ho scritto 3 anni fa. Il pulsante ha il testo e l'icona a sinistra ed è nel frame che è il pulsante effettivo qui e può essere allungato da fill_parent. Non posso provarlo di nuovo, ma allora funzionava. Probabilmente Button non deve essere utilizzato e può essere sostituito da TextView, ma non lo testerò adesso e non cambia troppo la funzionalità qui.

<FrameLayout
    android:id="@+id/login_button_login"
    android:background="@drawable/apptheme_btn_default_holo_dark"
    android:layout_width="fill_parent"
    android:layout_gravity="center"
    android:layout_height="40dp">
    <Button
        android:clickable="false"
        android:drawablePadding="15dp"
        android:layout_gravity="center"
        style="@style/WhiteText.Small.Bold"
        android:drawableLeft="@drawable/lock"
        android:background="@color/transparent"
        android:text="LOGIN" />
</FrameLayout>

1
Ora vedo che non ero solo con questa soluzione :)
Renetik

4

So che questa domanda è un po 'più vecchia, ma forse sei ancora aperto per suggerimenti o soluzioni alternative:

Crea un RelativeLayout "wrap_content" con l'immagine del pulsante come sfondo o il pulsante stesso come primo elemento del layout. Ottieni un LinearLayout e impostalo su "layout_centerInParent" e "wrap_content". Quindi imposta il tuo Drawable come Imageview. Infine imposta un TextView con il tuo testo (locale).

quindi fondamentalmente hai questa struttura:

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

o così:

RelativeLayout with "android-specific" button image as background
  LinearLayout
    ImageView
    TextView

So che con questa soluzione ci sono molti elementi da gestire, ma puoi creare molto facilmente il tuo pulsante personalizzato con esso e anche impostare la posizione esatta del testo e dei disegnabili :)


Questo approccio può funzionare bene. Nel mio caso, tutto ciò di cui avevo bisogno era un RelativeLayout contenente un TextView. Il RelativeLayout ha lo sfondo, il TextView ottiene l'icona drawableLeft. Quindi nel codice: collega onClickListener a RelativeLayout e findViewById per TextView separatamente se necessario
Stan Kurdziel

La prima struttura suggerita fornisce l'eccezione "Impossibile eseguire il cast del pulsante su ViewGroup".
Youngjae

4

Il mio modo di risolverlo consisteva nel circondare il pulsante con <View ../>elementi leggeri che si ridimensionavano dinamicamente. Di seguito sono riportati alcuni esempi di ciò che si può ottenere con questo:

Demo di Dev-iL

Notare che l'area selezionabile dei pulsanti nell'esempio 3 è la stessa di 2 (cioè con spazi), che è diversa dall'esempio 4 dove non ci sono spazi "non cliccabili" nel mezzo.

Codice:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 1: Button with a background color:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:layout_weight="0.3"/>
        <!-- Play around with the above 3 values to modify the clickable 
             area and image alignment with respect to text -->
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 2: Button group + transparent layout + spacers:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 3: Button group + colored layout:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 4 (reference): Button group + no spacers:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray">
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>   
    </LinearLayout>
</LinearLayout>


2

Puoi creare un widget personalizzato:

Il pulsante IB della classe Java:

public class IButton extends RelativeLayout {

private RelativeLayout layout;
private ImageView image;
private TextView text;

public IButton(Context context) {
    this(context, null);
}

public IButton(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public IButton(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.ibutton, this, true);

    layout = (RelativeLayout) view.findViewById(R.id.btn_layout);

    image = (ImageView) view.findViewById(R.id.btn_icon);
    text = (TextView) view.findViewById(R.id.btn_text);

    if (attrs != null) {
        TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.IButtonStyle);

        Drawable drawable = attributes.getDrawable(R.styleable.IButtonStyle_button_icon);
        if(drawable != null) {
            image.setImageDrawable(drawable);
        }

        String str = attributes.getString(R.styleable.IButtonStyle_button_text);
        text.setText(str);

        attributes.recycle();
    }

}

@Override
public void setOnClickListener(final OnClickListener l) {
    super.setOnClickListener(l);
    layout.setOnClickListener(l);
}

public void setDrawable(int resId) {
    image.setImageResource(resId);
}

}

Il layout ibutton.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/btn_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" >

<ImageView
    android:id="@+id/btn_icon"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_marginRight="2dp"
    android:layout_toLeftOf="@+id/btn_text"
    android:duplicateParentState="true" />

<TextView
    android:id="@+id/btn_text"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:duplicateParentState="true"
    android:gravity="center_vertical"
    android:textColor="#000000" />
</RelativeLayout>

Per utilizzare questo widget personalizzato:

<com.test.android.widgets.IButton
     android:id="@+id/new"
     android:layout_width="fill_parent"         
     android:layout_height="@dimen/button_height"
     ibutton:button_text="@string/btn_new"
     ibutton:button_icon="@drawable/ic_action_new" />

Devi fornire lo spazio dei nomi per gli attributi personalizzati xmlns: ibutton = "http://schemas.android.com/apk/res/com.test.android.xxx" dove com.test.android.xxx è il pacchetto principale di l'applicazione.

Mettilo sotto xmlns: android = "http://schemas.android.com/apk/res/android".

L'ultima cosa di cui avrai bisogno sono gli attributi personalizzati in attrs.xml.

Nel file attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="IButtonStyle">
        <attr name="button_text" />
        <attr name="button_icon" format="integer" />
    </declare-styleable>

    <attr name="button_text" />

</resources>

Per un posizionamento migliore, avvolgere il pulsante personalizzato all'interno di un LinearLayout, se si desidera evitare potenziali problemi con i posizionamenti RelativeLayout.

Godere!


2

Aveva un problema simile ma volevo avere il centro disegnabile senza testo e senza layout avvolti. La soluzione era creare un pulsante personalizzato e aggiungere un altro disegnabile oltre a SINISTRA, DESTRA, IN ALTO, IN BASSO. Si può facilmente modificare il posizionamento del disegno e averlo nella posizione desiderata rispetto al testo.

CenterDrawableButton.java

public class CenterDrawableButton extends Button {
    private Drawable mDrawableCenter;

    public CenterDrawableButton(Context context) {
        super(context);
        init(context, null);
    }

    public CenterDrawableButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }


    private void init(Context context, AttributeSet attrs){
        //if (isInEditMode()) return;
        if(attrs!=null){
            TypedArray a = context.getTheme().obtainStyledAttributes(
                    attrs, R.styleable.CenterDrawableButton, 0, 0);

            try {
                setCenterDrawable(a.getDrawable(R.styleable.CenterDrawableButton_drawableCenter));

            } finally {
                a.recycle();
            }

        }
    }

    public void setCenterDrawable(int center) {
        if(center==0){
            setCenterDrawable(null);
        }else
        setCenterDrawable(getContext().getResources().getDrawable(center));
    }
    public void setCenterDrawable(@Nullable Drawable center) {
        int[] state;
        state = getDrawableState();
        if (center != null) {
            center.setState(state);
            center.setBounds(0, 0, center.getIntrinsicWidth(), center.getIntrinsicHeight());
            center.setCallback(this);
        }
        mDrawableCenter = center;
        invalidate();
        requestLayout();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(mDrawableCenter!=null) {
            setMeasuredDimension(Math.max(getMeasuredWidth(), mDrawableCenter.getIntrinsicWidth()),
                    Math.max(getMeasuredHeight(), mDrawableCenter.getIntrinsicHeight()));
        }
    }
    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if (mDrawableCenter != null) {
            int[] state = getDrawableState();
            mDrawableCenter.setState(state);
            mDrawableCenter.setBounds(0, 0, mDrawableCenter.getIntrinsicWidth(),
                    mDrawableCenter.getIntrinsicHeight());
        }
        invalidate();
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);

        if (mDrawableCenter != null) {
            Rect rect = mDrawableCenter.getBounds();
            canvas.save();
            canvas.translate(getWidth() / 2 - rect.right / 2, getHeight() / 2 - rect.bottom / 2);
            mDrawableCenter.draw(canvas);
            canvas.restore();
        }
    }
}

attrs.xml

<resources>
    <attr name="drawableCenter" format="reference"/>
    <declare-styleable name="CenterDrawableButton">
        <attr name="drawableCenter"/>
    </declare-styleable>
</resources>

uso

<com.virtoos.android.view.custom.CenterDrawableButton
            android:id="@id/centerDrawableButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:drawableCenter="@android:drawable/ic_menu_info_details"/>

Grazie! Questo è quello che stavo cercando.
MistaGreen

potresti aiutarmi per favore in questa domanda, stackoverflow.com/questions/35912539/… , con la tua risposta ci sono molto vicino ma appaiono due drawables
Reprator

Questa soluzione colloca drawable al centro di un pulsante, appena sopra il testo centrato.
CoolMind

1
<style name="captionOnly">
    <item name="android:background">@null</item>
    <item name="android:clickable">false</item>
    <item name="android:focusable">false</item>
    <item name="android:minHeight">0dp</item>
    <item name="android:minWidth">0dp</item>
</style>

<FrameLayout
   style="?android:attr/buttonStyle"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" >

    <Button
       style="@style/captionOnly"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center"
       android:drawableLeft="@android:drawable/ic_delete"
       android:gravity="center"
       android:text="Button Challenge" />
</FrameLayout>

Metti il ​​FrameLayout in LinearLayout e imposta l'orientamento su Orizzontale.


1

Puoi mettere il pulsante su un LinearLayout

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/activity_login_fb_height"
        android:background="@mipmap/bg_btn_fb">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/lblLoginFb"
                android:textColor="@color/white"
                android:drawableLeft="@mipmap/icon_fb"
                android:textSize="@dimen/activity_login_fb_textSize"
                android:text="Login with Facebook"
                android:gravity="center" />
        </LinearLayout>
        <Button
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/btnLoginFb"
            android:background="@color/transparent"
            />
    </RelativeLayout>

0

Cosa succede se provi android: gravity = "center_horizontal"?


5
Non funziona. Il testo è in qualche modo centrato ma il drawableLeft resta sul lato sinistro.
Peter Ajtai

0

Penso che android: gravity = "center" dovrebbe funzionare


6
Non funziona per me. Centra il testo, ma il drawableLeft rimane all'estrema sinistra.
Peter Ajtai

Devi dichiarare l'icona e il testo sotto lo stesso genitore, usa android: gravity = "center" per il genitore
devanshu_kaushik

0

Come suggerito da Rodja, prima della 4.0 non esisteva un modo diretto per centrare il testo con il disegnabile. E infatti l'impostazione di un valore padding_left sposta il drawable lontano dal bordo. Pertanto il mio suggerimento è che in fase di esecuzione calcoli esattamente quanti pixel dal bordo sinistro deve essere il tuo disegnabile e poi lo passi usando setPadding Il tuo calcolo potrebbe essere qualcosa di simile

int paddingLeft = (button.getWidth() - drawableWidth - textWidth) / 2;

La larghezza del tuo disegnabile è fissa e puoi cercarla e puoi anche calcolare o indovinare la larghezza del testo.

Infine, dovresti moltiplicare il valore di riempimento per la densità dello schermo, cosa che puoi fare usando DisplayMetrics



0

la classe pubblica DrawableCenterTextView estende TextView {

public DrawableCenterTextView(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
}

public DrawableCenterTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public DrawableCenterTextView(Context context) {
    super(context);
}

@Override
protected void onDraw(Canvas canvas) {
    Drawable[] drawables = getCompoundDrawables();
    if (drawables != null) {
        Drawable drawableLeft = drawables[0];
        Drawable drawableRight = drawables[2];
        if (drawableLeft != null || drawableRight != null) {
            float textWidth = getPaint().measureText(getText().toString());
            int drawablePadding = getCompoundDrawablePadding();
            int drawableWidth = 0;
            if (drawableLeft != null)
                drawableWidth = drawableLeft.getIntrinsicWidth();
            else if (drawableRight != null) {
                drawableWidth = drawableRight.getIntrinsicWidth();
            }
            float bodyWidth = textWidth + drawableWidth + drawablePadding;
            canvas.translate((getWidth() - bodyWidth) / 2, 0);
        }
    }
    super.onDraw(canvas);
}

}


Questo non ha funzionato affatto per me. Puoi mostrare un esempio? Forse non lo uso correttamente
sviluppatore Android

0

Soluzione sporca.

android:paddingTop="10dp"
android:drawableTop="@drawable/ic_src"

Capire l'imbottitura giusta risolve lo scopo. Tuttavia, per schermi diversi, utilizzare una spaziatura interna diversa e inserirla nella risorsa dimens nella rispettiva cartella dei valori.


0

Utilizza RelativeLayout (container) e android: layout_centerHorizontal = "true" , il mio esempio:

                <RelativeLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1" >

                    <CheckBox
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:layout_centerHorizontal="true"
                        android:layout_gravity="center"
                        android:layout_marginBottom="5dp"
                        android:layout_marginLeft="10dp"
                        android:layout_marginTop="5dp"
                        android:button="@drawable/bg_fav_detail"
                        android:drawablePadding="5dp"
                        android:text=" Favorite" />
                </RelativeLayout>

0

Altre possibilità per mantenere il tema Button.

<Button
            android:id="@+id/pf_bt_edit"
            android:layout_height="@dimen/standard_height"
            android:layout_width="match_parent"
            />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_alignBottom="@id/pf_bt_edit"
            android:layout_alignLeft="@id/pf_bt_edit"
            android:layout_alignRight="@id/pf_bt_edit"
            android:layout_alignTop="@id/pf_bt_edit"
            android:layout_margin="@dimen/margin_10"
            android:clickable="false"
            android:elevation="20dp"
            android:gravity="center"
            android:orientation="horizontal"
            >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:clickable="false"
                android:src="@drawable/ic_edit_white_48dp"/>

            <TextView
                android:id="@+id/pf_tv_edit"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginLeft="@dimen/margin_5"
                android:clickable="false"
                android:gravity="center"
                android:text="@string/pf_bt_edit"/>

        </LinearLayout>

Con questa soluzione se aggiungi @ color / your_color @ color / your_highlight_color nel tema dell'attività, puoi avere il tema Matherial su Lollipop con ombre e increspature, e per la versione precedente pulsante piatto con il tuo colore ed evidenziare coor quando lo premi.

Inoltre, con questa soluzione si autorizza il ridimensionamento dell'immagine

Risultato: primo sul dispositivo Lollipop Secondo: sul dispositivo pre lollipop 3 °: dispositivo pre lollipop premere il pulsante

inserisci qui la descrizione dell'immagine


0

Ho centrato textViewcon l'icona usando paddingLefte e allineando textView a sinistra | centerVertical . e per un piccolo spazio tra la vista e l'icona ho usatodrawablePadding

         <Button
            android:id="@+id/have_it_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/textbox"
            android:drawableLeft="@drawable/have_it"
            android:drawablePadding="30dp"
            android:gravity="left|center_vertical"
            android:paddingLeft="60dp"
            android:text="Owner Contact"
            android:textColor="@android:color/white" />

2
Questo non funzionerà su molti schermi, solo su quello per cui ha android:paddingLeftfunzionato.
soshial

0

Questo può essere un thread vecchio / chiuso ma ho cercato ovunque non ho trovato qualcosa di utile, fino a quando non ho deciso di creare la mia soluzione. Se c'è qualcuno qui che sta cercando di cercare una risposta, prova questo, potrebbe farti risparmiare un minuto di riflessione

          <LinearLayout
            android:id="@+id/llContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/selector"
            android:clickable="true"
            android:gravity="center"
            android:orientation="vertical"
            android:padding="10dp"
            android:textStyle="bold">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="This is a text" />

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/icon_image />


        </LinearLayout>

Poiché il layout lineare funge da contenitore e da quello che ha il selettore, quando fai clic sull'intero layout lineare, apparirà proprio come dovrebbe essere. se vuoi che siano entrambi centrati, usa l'insteaf relativo. Se vuoi che sia centrato orizzontalmente, cambia l'orientamento in orizzontale.

Prendi nota NON dimenticare di aggiungere android: clickable = "true" al tuo contenitore principale (relativo o lineare) affinché l'azione abbia luogo.

Anche in questo caso potrebbe essere un vecchio thread ma potrebbe comunque aiutare qualcuno.

-grazie speriamo che aiuti- happycodings.


0

Se utilizzi una delle soluzioni di visualizzazione personalizzata , fai attenzione, perché spesso non riescono su testo lungo o multilinea . Ho riscritto alcune risposte, le ho sostituite onDraw()e ho capito che quella era una strada sbagliata.


0

Ho visto soluzioni per l'allineamento del drawable all'inizio / a sinistra ma niente per drawable end / right, quindi ho pensato a questa soluzione. Utilizza imbottiture calcolate dinamicamente per allineare il disegno e il testo sia sul lato sinistro che su quello destro.

class IconButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = R.attr.buttonStyle
) : AppCompatButton(context, attrs, defStyle) {

    init {
        maxLines = 1
    }

    override fun onDraw(canvas: Canvas) {
        val buttonContentWidth = (width - paddingLeft - paddingRight).toFloat()

        val textWidth = paint.measureText(text.toString())

        val drawable = compoundDrawables[0] ?: compoundDrawables[2]
        val drawableWidth = drawable?.intrinsicWidth ?: 0
        val drawablePadding = if (textWidth > 0 && drawable != null) compoundDrawablePadding else 0
        val bodyWidth = textWidth + drawableWidth.toFloat() + drawablePadding.toFloat()

        canvas.save()

        val padding = (buttonContentWidth - bodyWidth).toInt() / 2
        val leftOrRight = if (compoundDrawables[0] != null) 1 else -1
        setPadding(leftOrRight * padding, 0, -leftOrRight * padding, 0)

        super.onDraw(canvas)
        canvas.restore()
    }
}

È importante impostare la gravità nel layout su "center_vertical | start" o "center_vertical | end" a seconda di dove imposti l'icona. Per esempio:

<com.stackoverflow.util.IconButton
        android:id="@+id/cancel_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:drawableStart="@drawable/cancel"
        android:drawablePadding="@dimen/padding_small"
        android:gravity="center_vertical|start"
        android:text="Cancel" />

L'unico problema con questa implementazione è che il pulsante può avere solo una singola riga di testo, altrimenti l'area del testo riempie il pulsante e le imbottiture saranno 0.


-5

Usa questo android:background="@drawable/ic_play_arrow_black_24dp"

imposta lo sfondo sull'icona che desideri centrare

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.