So zentrieren Sie Symbole und Text in einer Android-Schaltfläche, deren Breite auf "Eltern füllen" eingestellt ist.


118

Ich möchte einen Android-Button mit Symbol + Text in der Mitte haben. Ich verwende das Attribut drawableLeft, um das Bild festzulegen. Dies funktioniert gut, wenn die Schaltfläche eine Breite von hat "wrap_content", ich mich jedoch auf die maximale Breite dehnen muss, damit ich die Breite verwende "fill_parent". Dadurch wird mein Symbol direkt links von der Schaltfläche verschoben, und ich möchte, dass sowohl das Symbol als auch der Text in der Schaltfläche zentriert sind.

Ich habe versucht, die Polsterung einzurichten, aber dies erlaubt nur die Angabe eines festen Werts, so dass es nicht das ist, was ich brauche. Ich muss Symbol + Text in der Mitte ausgerichtet haben.

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

Irgendwelche Vorschläge, wie ich das erreichen könnte?


Ist es möglich, dass es dafür keine einfache Lösung gibt? Muss ich es mit einem 9patch-Button img mit dem Symbol versuchen?
Jloriente

Dies könnte eine Lösung sein. Wird der Schaltflächentext lokalisiert oder statisch sein?
Octavian A. Damiean

Es ist lokalisiert. Gibt es dafür keine andere Lösung? Ich habe es mit einem 9-Patch geschafft, hatte aber Probleme beim Ändern des Gebietsschemas.
Jloriente

Was ist mit der Verwendung eines Buttons mit zeichnbarem TOP und dem Hinzufügen von Polstern?
Francesco

schlechtes Gerüstdesign
Muhammad Babar

Antworten:


75

android: drawableLeft behält immer android: paddingLeft als Abstand vom linken Rand bei. Wenn die Schaltfläche nicht auf android: width = "wrap_content" eingestellt ist, hängt sie immer links!

Mit Android 4.0 (API Level 14) können Sie das Attribut android: drawableStart verwenden , um ein Zeichen am Anfang des Textes zu platzieren. Die einzige abwärtskompatible Lösung, die ich mir ausgedacht habe, ist die Verwendung eines ImageSpan zum Erstellen eines Text + Image Spannable:

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

In meinem Fall musste ich auch das Android: Gravity-Attribut des Buttons anpassen, damit es zentriert aussieht:

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

Nett. Die letzte Zeile sollte seinbutton.setText(buttonLabel)
AlexD

1
Unicode verfügt über eine umfangreiche Reihe von Zeichensymbolen, die mit Zeichenfolgen in Android kompatibel sind. Wenn Sie eine akzeptable finden können, ist dies eine einfache Lösung, und sie hat den zusätzlichen Vorteil, dass sie mit der Textgröße skaliert wird. Zum Beispiel hat es einen Umschlag für ein E-Mail-Symbol und ein paar verschiedene Telefone für eine Anruftaste.
GLee

1
Ich bin verwirrt, wie das bei jedem funktioniert hat. Bei mir werden zwei Symbole gezeichnet ... ein Weg nach links und einer direkt in der Mitte, der über dem Text angezeigt wird.
Justin

11
drawableStart funktioniert nicht. Siehe diesen Thread: stackoverflow.com/questions/15350990/… Es scheint auch, dass der Stil ignoriert wird, wenn Sie den Text mit einem Spannable festlegen.
Dapp

11
drawableStart funktioniert nicht und wurde in API Level 17 hinzugefügt, um RTL zu unterstützen
Silvia H

35

Ich weiß, dass ich diese Frage zu spät beantworte, aber das hat mir geholfen:

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

Ich habe diese Lösung von hier aus gefunden: Probleme mit der Android-Benutzeroberfläche: Erstellen einer Schaltfläche mit zentriertem Text und Symbol

Geben Sie hier die Bildbeschreibung ein


6
Das Problem dabei ist, dass die Schaltfläche nicht die Breite des Rahmenlayouts hat.
Clive Jefferies

29

Ich habe stattdessen LinearLayout verwendet Button verwendet . Der OnClickListener , den ich verwenden muss, funktioniert auch für LinearLayout einwandfrei.

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

26

Alle vorherigen Antworten scheinen veraltet zu sein

Sie können das MaterialButtonJetzt verwenden, mit dem Sie die Schwerkraft des Symbols einstellen können.

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

Geben Sie hier die Bildbeschreibung ein

Für die Verwendung der Materialkomponenten müssen Sie natürlich:

Fügen Sie eine Abhängigkeit hinzu implementation 'com.google.android.material:material:1.3.0-alpha01' (verwenden Sie die neueste Version)

Erweitern Sie das Thema Materialkomponenten

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

Falls Sie dies nicht tun können, erweitern Sie es aus dem Material Bridge-Thema

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

Vielen Dank! Du hast meinen Tag gerettet! Funktioniert gut
Black_Zerg

9

Ich passe es an, indem ich links und rechts Polster wie folgt hinzufüge:

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

Das paddingLeft und das paddingRight halfen mir beim Zentrieren. Upvoting für eine einfache Lösung.
Arrie

2
Wie schaffen Sie es, dass Ihre Breite dynamisch ist? Wenn Sie Ihren Bildschirm drehen, werden nicht alle Symbole richtig zentriert? Ich stehe tatsächlich vor diesem Problem
Jacks

Das ist die beste Antwort!
Dody Rachmat Wicaksono

8

Ich bin kürzlich auf das gleiche Problem gestoßen. Ich habe versucht, eine billigere Lösung zu finden.

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

Dann rufen Sie einfach OnClickListeneran LinearLayout.

Ich hoffe, dies hilft jemandem, da es ein sehr häufiges Problem zu sein scheint. :) :)


1
Dies ist eine gute Idee, aber eine schlechte Lösung. Mit dem drawableLeft-Attribut können Sie dasselbe mit nur einer Textansicht erreichen. Auf diese Weise können Sie eine Zeichnung links vom Text anzeigen.
Muetzenflo

@ Muetzenflo yup, das stimmt. Wenn Sie jedoch festlegen, dass die Textansicht mit der übergeordneten Breite übereinstimmt, wird Ihre Zeichenfläche ganz nach links verschoben, selbst wenn Sie Ihren Text zentrieren. Bitte lassen Sie mich wissen, wenn ich falsch liege. und die Frage ist nur darüber.
Ankit Popli

ah sorry..Ich bin wegen genau diesem Problem hierher gekommen und habe den Fokus verloren, nachdem ich zu viele Dinge ausprobiert hatte :) Ich schätze, ich habe den Wald vor lauter Bäumen nicht gesehen. Mein Fehler!
Muetzenflo

7

Sie können eine benutzerdefinierte Schaltfläche verwenden, die sich selbst misst und zeichnet, um eine linke Zeichenfläche aufzunehmen. Beispiel und Verwendung finden Sie hier

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

Verwendung

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

Sie können Code in Ihre Antwort aufnehmen, was der bevorzugte Weg sein sollte (wenn er nicht zu lang ist), da Links im Laufe der Zeit absterben können
Lukas Knuth

2
Nicht sehr genau, aber ich nehme an
Alex Semeniuk

Es verschiebt einen Text nach rechts, aber nicht genug (ein Bild überlappt den Text). Wie bei anderen Lösungen der benutzerdefinierten Ansicht wird auch kein langer Text richtig akzeptiert.
CoolMind

5

Dies ist meine Lösung, die ich vor 3 Jahren geschrieben habe. Die Schaltfläche hat Text und ein linkes Symbol und befindet sich im Rahmen, der hier die eigentliche Schaltfläche ist und von fill_parent gestreckt werden kann. Ich kann es nicht noch einmal testen, aber es hat damals funktioniert. Wahrscheinlich muss Button nicht verwendet werden und kann durch TextView ersetzt werden, aber ich werde es jetzt nicht testen und es ändert die Funktionalität hier nicht zu sehr.

<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
Jetzt sehe ich, dass ich mit dieser Lösung nicht allein war :)
Renetik

4

Ich weiß, dass diese Frage etwas älter ist, aber vielleicht sind Sie immer noch offen für Hinweise oder Problemumgehungen:

Erstellen Sie ein RelativeLayout "wrap_content" mit dem Schaltflächenbild als Hintergrund oder der Schaltfläche selbst als erstem Element des Layouts. Holen Sie sich ein LinearLayout und setzen Sie es auf "layout_centerInParent" und "wrap_content". Stellen Sie dann Ihr Drawable als Bildansicht ein. Stellen Sie endlich eine Textansicht mit Ihrem Text (Gebietsschema) ein.

Sie haben also im Grunde diese Struktur:

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

oder so:

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

Ich weiß, dass es bei dieser Lösung viele Elemente gibt, mit denen Sie sich befassen müssen, aber Sie können damit ganz einfach Ihre eigene benutzerdefinierte Schaltfläche erstellen und auch die genaue Position von Text und Zeichen festlegen :)


Dieser Ansatz kann gut funktionieren. In meinem Fall brauchte ich nur ein RelativeLayout mit einer Textansicht. Das RelativeLayout hat den Hintergrund, die TextView das drawableLeft-Symbol. Dann im Code: onClickListener an das RelativeLayout anhängen und bei Bedarf die ViewViewById für die TextView separat finden
Stan Kurdziel

Die erste vorgeschlagene Struktur gibt die Ausnahme "Schaltfläche kann nicht in ViewGroup umgewandelt werden".
Youngjae

4

Meine Art, es zu lösen, bestand darin, die Schaltfläche mit leichten <View ../>Elementen zu umgeben, deren Größe sich dynamisch ändert. Nachfolgend einige Beispiele, was damit erreicht werden kann:

Demo von Dev-iL

Beachten Sie, dass der anklickbare Bereich der Schaltflächen in Beispiel 3 der gleiche ist wie in 2 (dh mit Leerzeichen), was sich von Beispiel 4 unterscheidet, in dem keine "nicht klickbaren" Lücken dazwischen vorhanden sind.

Code:

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

Sie können ein benutzerdefiniertes Widget erstellen:

Die Java-Klasse IButton:

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

}}

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

So verwenden Sie dieses benutzerdefinierte Widget:

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

Sie müssen den Namespace für die benutzerdefinierten Attribute xmlns angeben: ibutton = "http://schemas.android.com/apk/res/com.test.android.xxx" wobei com.test.android.xxx das Stammpaket von ist die Anwendung.

Setzen Sie es einfach unter xmlns: android = "http://schemas.android.com/apk/res/android".

Das Letzte, was Sie brauchen, sind die benutzerdefinierten Attribute in der Datei attrs.xml.

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

Um eine bessere Positionierung zu erzielen, wickeln Sie die benutzerdefinierte Schaltfläche in ein LinearLayout ein, wenn Sie potenzielle Probleme mit RelativeLayout-Positionierungen vermeiden möchten.

Genießen!


2

Hatte ein ähnliches Problem, wollte aber eine Mitte ohne Text und ohne umbrochene Layouts zeichnen. Die Lösung bestand darin, eine benutzerdefinierte Schaltfläche zu erstellen und zusätzlich zu LINKS, RECHTS, OBEN und UNTEN eine weitere Zeichenfläche hinzuzufügen. Man kann die zeichnbare Platzierung leicht ändern und sie in der gewünschten Position relativ zum Text haben.

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>

Verwendung

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

Vielen Dank! Das habe ich gesucht.
MistaGreen

Würden Sie mir bitte bei dieser Frage helfen, stackoverflow.com/questions/35912539/… , mit Ihrer Antwort bin ich sehr nah dran, aber zwei Drawables erscheinen
Reprator

Diese Lösung platziert Drawable in der Mitte einer Schaltfläche direkt über zentriertem Text.
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>

Setzen Sie das FrameLayout in LinearLayout und setzen Sie die Ausrichtung auf Horizontal.


1

Sie können die Schaltfläche über einem LinearLayout platzieren

<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

Was passiert, wenn Sie Android versuchen: Gravity = "center_horizontal"?


5
Es funktioniert nicht. Der Text ist etwas zentriert, aber das drawableLeft bleibt auf der linken Seite.
Peter Ajtai

0

Ich denke Android: Schwerkraft = "Zentrum" sollte funktionieren


6
Funktioniert bei mir nicht Es zentriert den Text, aber das drawableLeft bleibt ganz links.
Peter Ajtai

Sie müssen das Symbol und den Text unter demselben Elternteil deklarieren. Verwenden Sie android :
vity

0

Wie von Rodja vorgeschlagen, gibt es vor 4.0 keine direkte Möglichkeit, den Text mit dem Zeichenelement zu zentrieren. Wenn Sie einen padding_left-Wert festlegen, wird das Zeichenobjekt vom Rand entfernt. Daher ist mein Vorschlag, dass Sie zur Laufzeit genau berechnen, wie viele Pixel vom linken Rand Ihr Zeichenelement sein muss, und es dann mit setPadding übergeben. Ihre Berechnung könnte so etwas wie sein

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

Die Breite Ihrer Zeichen ist festgelegt und Sie können sie nachschlagen und die Textbreite berechnen oder erraten.

Schließlich müssten Sie den Füllwert mit der Bildschirmdichte multiplizieren, was Sie mit DisplayMetrics tun können



0

öffentliche Klasse DrawableCenterTextView erweitert 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);
}

}}


Das hat bei mir überhaupt nicht funktioniert. Können Sie bitte ein Beispiel zeigen? Vielleicht benutze ich es nicht richtig
Android-Entwickler

0

Schmutzige Lösung.

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

Das Finden der richtigen Polsterung löst den Zweck. Verwenden Sie für einen abwechslungsreichen Bildschirm jedoch unterschiedliche Auffüllungen und legen Sie diese in der Dimens-Ressource im entsprechenden Werteordner ab.


0

Verwenden Sie RelativeLayout (Container) und Android: layout_centerHorizontal = "true" , mein Beispiel:

                <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

Andere Möglichkeit, das Button-Thema beizubehalten.

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

Mit dieser Lösung können Sie, wenn Sie @ color / your_color @ color / your_highlight_color in Ihrem Aktivitätsthema hinzufügen, ein Matherial-Thema auf Lollipop mit Schatten und Welligkeit und für die vorherige Version eine flache Schaltfläche mit Ihrer Farbe und Hervorhebungsfarbe haben, wenn Sie darauf drücken.

Darüber hinaus wird mit dieser Lösung die Bildgröße automatisch angepasst

Ergebnis: Zuerst am Lollipop-Gerät Zweitens: Am Pre-Lollipop-Gerät 3 .: Pre-Lollipop-Gerät Taste drücken

Geben Sie hier die Bildbeschreibung ein


0

Ich habe textViewmit dem Symbol zentriert paddingLeftund textView auf left | centerVertical ausgerichtet . und für eine kleine Lücke zwischen Ansicht und Symbol habe ich verwendetdrawablePadding

         <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
Dies funktioniert nicht auf vielen Bildschirmen, sondern nur auf dem, für den es android:paddingLeftfunktioniert hat.
Soshial

0

Dies mag ein alter / geschlossener Thread sein, aber ich habe überall gesucht und nichts Nützliches gefunden, bis ich mich entschied, meine eigene Lösung zu erstellen. Wenn jemand hier versucht, nach einer Antwort zu suchen, versuchen Sie diese, könnte Ihnen eine Minute des Nachdenkens ersparen

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

Da das lineare Layout als Container und derjenige mit dem Selektor fungiert, sieht es beim Klicken auf das gesamte lineare Layout genau so aus, wie es sein sollte. Wenn Sie möchten, dass beide zentriert sind, verwenden Sie relative Insteaf. Wenn Sie möchten, dass es horizontal zentriert ist, ändern Sie die Ausrichtung in horizontal.

Beachten Sie nicht vergessen , hinzuzufügen android: anklickbare = „true“ , dass Sie Ihrem Hauptcontainer (relativ oder linear) damit die Aktion ausgeführt werden kann.

Auch dies kann ein alter Thread sein, kann aber trotzdem jemandem dort helfen.

-cheers hoffen es hilft- happycodings.


0

Wenn Sie eine der Lösungen der benutzerdefinierten Ansicht verwenden, seien Sie vorsichtig, da diese häufig bei langem oder mehrzeiligem Text fehlschlagen . Ich schrieb einige Antworten um, ersetzte onDraw()und verstand, dass das ein falscher Weg war.


0

Ich habe Lösungen für das Ausrichten von Drawable am Anfang / links gesehen, aber nichts für Drawable End / Right, also habe ich diese Lösung gefunden. Es verwendet dynamisch berechnete Auffüllungen zum Ausrichten von Zeichen- und Text auf der linken und rechten Seite.

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

Es ist wichtig, die Schwerkraft in Ihrem Layout entweder auf "center_vertical | start" oder "center_vertical | end" zu setzen, je nachdem, wo Sie das Symbol einstellen. Beispielsweise:

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

Das einzige Problem bei dieser Implementierung ist, dass die Schaltfläche nur eine einzige Textzeile enthalten kann. Andernfalls füllt der Textbereich die Schaltfläche aus und die Auffüllungen sind 0.


-5

benutze das android:background="@drawable/ic_play_arrow_black_24dp"

Stellen Sie einfach den Hintergrund auf das Symbol ein, das Sie zentrieren möchten

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.