Cara memusatkan ikon dan teks di tombol android dengan lebar disetel ke "isi induk"

118

Saya ingin memiliki Tombol Android dengan ikon + teks di tengahnya. Saya menggunakan atribut drawableLeft untuk mengatur gambar, ini berfungsi dengan baik jika tombol memiliki lebar "wrap_content"tetapi saya perlu meregangkan ke lebar maksimal jadi saya menggunakan lebar "fill_parent". Ini memindahkan ikon saya langsung ke kiri tombol dan saya ingin ikon dan teks terpusat di dalam tombol.

Saya sudah mencoba menyiapkan padding tetapi ini hanya memungkinkan untuk memberikan nilai tetap sehingga bukan itu yang saya butuhkan. Saya perlu ikon + teks sejajar di tengah.

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

Ada saran tentang bagaimana saya bisa mencapai itu?

jloriente.dll
sumber
Mungkinkah tidak ada solusi yang mudah untuk ini? Apakah saya harus mencoba dengan img tombol 9patch dengan ikon di sana?
jloriente
Ini mungkin solusi. Apakah teks tombol akan dilokalkan atau statis?
Oktavianus A. Damiean
Ini dilokalkan. Tidak ada solusi lain untuk ini? Saya berhasil melakukannya dengan 9 tambalan tetapi mengalami masalah saat mengubah lokal.
jloriente
Bagaimana dengan menggunakan Tombol dengan TOP drawable dan menambahkan beberapa padding padanya?
Francesco
desain kerangka yang buruk
Muhammad Babar

Jawaban:

75

android: drawableLeft selalu menjaga android: paddingLeft sebagai jarak dari batas kiri. Jika tombol tidak disetel ke android: width = "wrap_content", tombol akan selalu menggantung di kiri!

Dengan Android 4.0 (API level 14) Anda bisa menggunakan atribut android: drawableStart untuk menempatkan drawable di awal teks. Satu-satunya solusi kompatibel mundur yang saya buat adalah menggunakan ImageSpan untuk membuat 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);

Dalam kasus saya, saya juga perlu menyesuaikan android: atribut gravitasi Tombol agar terlihat di tengah:

<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" />
Rodja
sumber
Bagus. Baris terakhir harusbutton.setText(buttonLabel)
AlexD
1
Unicode memiliki sekumpulan ikon karakter ekstensif yang kompatibel dengan string di Android. Jika Anda dapat menemukan yang dapat diterima, ini adalah solusi sederhana, dan memiliki bonus tambahan yang akan diskalakan dengan ukuran teks. Misalnya, ia memiliki amplop untuk ikon email dan beberapa telepon berbeda untuk tombol panggil.
GLee
1
Saya bingung bagaimana ini bekerja untuk siapa pun, bagi saya ini menggambar 2 ikon ... satu arah ke kiri, dan satu lagi langsung di tengah yang ditampilkan di atas teks.
Justin
11
drawableStart tidak akan berfungsi. Lihat utas ini: stackoverflow.com/questions/15350990/… Selain itu, tampaknya saat Anda menyetel teks menggunakan spannable, gayanya diabaikan.
Dapp
11
drawableStart tidak berfungsi, dan ditambahkan di API level 17 untuk mendukung rtl
Silvia H
35

Saya tahu saya terlambat menjawab pertanyaan ini, tetapi ini membantu saya:

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

Saya menemukan solusi ini dari sini: UI Android berjuang: membuat tombol dengan teks dan ikon di tengah

masukkan deskripsi gambar di sini

Sarvan
sumber
6
Masalahnya adalah tombol tersebut tidak selebar tata letak bingkai.
Clive Jefferies
29

Saya menggunakan LinearLayout, bukan Button . The OnClickListener , yang saya butuhkan untuk penggunaan bekerja dengan baik juga untuk 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>
petrnohejl
sumber
29

Semua jawaban sebelumnya sepertinya sudah ketinggalan zaman

Anda dapat menggunakan MaterialButtonnow yang memungkinkan pengaturan gravitasi ikon.

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

masukkan deskripsi gambar di sini

Untuk menggunakan komponen material, Anda jelas perlu:

Tambahkan ketergantungan implementation 'com.google.android.material:material:1.3.0-alpha01'(gunakan versi terbaru)

Buat tema Anda memperluas tema Material Components

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

Jika Anda tidak dapat melakukannya, perluas dari tema Material Bridge

<style name="AppTheme" parent="Theme.MaterialComponents.Light.Bridge">
...
</style>
Leo Droidcoder
sumber
Terima kasih! Anda menyelamatkan hari saya! Bekerja dengan baik
Black_Zerg
9

Saya menyesuaikannya dengan menambahkan padding kiri dan kanan sebagai berikut:

<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"
            />
Flowra
sumber
PaddingLeft dan paddingRight yang membantu saya dengan keterpusatan saya. upvoting untuk solusi mudah.
Arrie
2
Bagaimana Anda mengelola fakta bahwa lebar Anda dinamis? Jika Anda memutar layar, semua ikon Anda tidak akan berada di tengah, bukan? Saya menghadapi masalah ini sebenarnya
Jacks
ini adalah jawaban terbaik!
Dody Rachmat Wicaksono
8

Saya baru-baru ini mengalami masalah yang sama. Mencoba menemukan solusi yang lebih murah jadi munculkan ini.

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

Kemudian hanya memanggil OnClickListenerpada LinearLayout.

Semoga ini membantu seseorang karena sepertinya masalah yang sangat umum. :)

Ankit Popli
sumber
1
Ini ide yang bagus, tapi solusi yang buruk. Anda bisa mencapai hal yang sama hanya dengan satu TextView menggunakan atribut drawableLeft. Ini memungkinkan Anda untuk melihat drawable di sebelah kiri teks.
muetzenflo
@muetzenflo yup, itu benar. tapi saat Anda membuat textView cocok dengan lebar induk, drawable Anda akan berpindah ke paling kiri meskipun Anda memusatkan teks Anda. tolong beri tahu saya jika saya salah. dan pertanyaannya hanya tentang itu.
Ankit Popli
ah maaf..saya datang ke sini untuk masalah ini dan kehilangan fokus setelah mencoba terlalu banyak hal :) Sepertinya saya tidak melihat hutan untuk pepohonan. Salahku!
muetzenflo
7

Anda dapat menggunakan tombol khusus yang mengukur dan menggambar dirinya sendiri untuk mengakomodasi drawable kiri. Temukan contoh dan penggunaannya di sini

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

Pemakaian

<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" />
Rajiv
sumber
Anda dapat menyertakan kode dalam jawaban Anda, yang seharusnya menjadi cara yang disukai (jika tidak terlalu panjang), karena tautan dapat mati seiring waktu-
Lukas Knuth
2
Tidak terlalu akurat tapi saya menerimanya
Alex Semeniuk
Ini menggeser teks ke kanan, tetapi tidak cukup (gambar tumpang tindih dengan teks). Selain itu, sebagai solusi tampilan kustom lainnya, tidak menerima teks panjang dengan benar.
CoolMind
5

Ini adalah solusi yang saya tulis 3 tahun yang lalu. Tombol memiliki teks dan ikon kiri dan berada dalam bingkai yang merupakan tombol sebenarnya di sini dan dapat direntangkan oleh fill_parent. Saya tidak dapat mengujinya lagi tetapi berfungsi saat itu. Mungkin Tombol tidak harus digunakan dan dapat diganti dengan TextView tetapi saya tidak akan mengujinya sekarang dan tidak terlalu banyak mengubah fungsi di sini.

<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>
Renetik
sumber
1
Sekarang saya melihat bahwa saya tidak sendirian dengan solusi ini :)
Renetik
4

Saya tahu pertanyaan ini sedikit lebih tua, tetapi mungkin Anda masih terbuka untuk mendapatkan petunjuk atau solusi:

Buat RelativeLayout "wrap_content" dengan gambar tombol sebagai latar belakang atau tombol itu sendiri sebagai elemen pertama tata letak. Dapatkan LinearLayout dan setel ke "layout_centerInParent" dan "wrap_content". Kemudian atur Drawable Anda sebagai Imageview. Terakhir, atur TextView dengan teks Anda (lokal).

jadi pada dasarnya Anda memiliki struktur ini:

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

atau seperti ini:

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

Saya tahu dengan solusi ini ada banyak elemen yang harus ditangani, tetapi Anda dapat membuat tombol kustom Anda sendiri dengan sangat mudah dan juga mengatur posisi teks dan drawable yang tepat :)

einschnaehkeee
sumber
Pendekatan ini bisa bekerja dengan baik. Dalam kasus saya, yang saya butuhkan hanyalah RelativeLayout yang berisi TextView. RelativeLayout mendapatkan latar belakang, TextView mendapatkan ikon drawableLeft. Kemudian di kode: lampirkan onClickListener ke RelativeLayout dan findViewById untuk TextView secara terpisah jika diperlukan
Stan Kurdziel
Struktur yang disarankan pertama memberikan Pengecualian "Tombol tidak dapat ditransmisikan ke ViewGroup".
Youngjae
4

Cara saya mengatasinya melibatkan mengelilingi tombol dengan <View ../>elemen ringan yang mengubah ukuran secara dinamis. Di bawah ini adalah beberapa contoh yang dapat dicapai dengan ini:

Demo oleh Dev-iL

Perhatikan bahwa area tombol yang dapat diklik di contoh 3 sama dengan di 2 (yaitu dengan spasi), yang berbeda dari contoh 4 di mana tidak ada celah "yang tidak bisa diklik" di antaranya.

Kode:

<?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>
Setan
sumber
2

Anda dapat membuat widget khusus:

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

}

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

Untuk menggunakan widget khusus ini:

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

Anda harus memberikan namespace untuk atribut khusus xmlns: ibutton = "http://schemas.android.com/apk/res/com.test.android.xxx" di mana com.test.android.xxx adalah paket root dari aplikasi.

Letakkan saja di bawah xmlns: android = "http://schemas.android.com/apk/res/android".

Hal terakhir yang Anda perlukan adalah atribut khusus di attrs.xml.

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

Untuk pemosisian yang lebih baik, gabungkan Tombol khusus di dalam LinearLayout, jika Anda ingin menghindari potensi masalah dengan pemosisian RelativeLayout.

Nikmati!

kirilv.dll
sumber
2

Memiliki masalah serupa tetapi ingin memiliki drawable tengah tanpa teks dan tata letak yang dibungkus. Solusinya adalah membuat tombol khusus dan menambahkan satu lagi drawable selain KIRI, KANAN, ATAS, BAWAH. Seseorang dapat dengan mudah mengubah penempatan drawable dan menempatkannya pada posisi yang diinginkan relatif terhadap teks.

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>

pemakaian

<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"/>
Vilen
sumber
Terima kasih! Itulah yang saya cari.
MistaGreen
maukah Anda membantu saya dalam pertanyaan ini, stackoverflow.com/questions/35912539/… , dengan jawaban Anda, saya sangat dekat dengannya tetapi dua
drawable
Solusi ini menempatkan drawable di tengah tombol, tepat di atas teks tengah.
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>

Letakkan FrameLayout di LinearLayout dan atur orientasi ke Horizontal.

Feay Jarana Manotumruksa
sumber
1

Anda dapat meletakkan tombol di atas 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>
tukang daging202
sumber
0

Apa yang terjadi jika Anda mencoba android: gravity = "center_horizontal"?

Ted Hopp
sumber
5
Ini tidak berhasil. Teksnya agak di tengah tetapi drawableLeft menempel di sisi kiri.
Peter Ajtai
0

Saya pikir android: gravity = "center" seharusnya berfungsi

devanshu_kaushik
sumber
6
Tidak berhasil untuk saya. Ini memusatkan teks, tetapi drawableLeft tetap berada di paling kiri.
Peter Ajtai
Anda harus mendeklarasikan ikon dan teks di bawah induk yang sama, gunakan android: gravity = "center" untuk induk
devanshu_kaushik
0

Seperti yang disarankan oleh Rodja, sebelum 4.0 tidak ada cara langsung untuk memusatkan teks dengan drawable. Dan memang menyetel nilai padding_left tidak akan menjauhkan drawable dari batas. Oleh karena itu, saran saya adalah pada saat runtime Anda menghitung dengan tepat berapa banyak piksel dari batas kiri yang dibutuhkan drawable Anda dan kemudian meneruskannya menggunakan setPadding Perhitungan Anda mungkin seperti

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

Lebar drawable Anda tetap dan Anda dapat mencarinya dan Anda juga dapat menghitung atau menebak lebar teks.

Terakhir, Anda perlu menggandakan nilai padding berdasarkan kepadatan layar, yang dapat Anda lakukan menggunakan DisplayMetrics

ılǝ
sumber
0

kelas publik DrawableCenterTextView memperluas 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);
}

}

tangjun
sumber
Ini sama sekali tidak berhasil untuk saya. Bisakah Anda menunjukkan contoh? Mungkin saya tidak menggunakannya dengan benar
pengembang android
0

Perbaikan kotor.

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

Menentukan padding yang tepat menyelesaikan tujuan. Namun, untuk layar yang bervariasi, gunakan padding yang berbeda dan letakkan di sumber daya dimens di folder nilai masing-masing.

Ngudup
sumber
0

Gunakan RelativeLayout (container) dan android: layout_centerHorizontal = "true" , contoh saya:

                <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>
vuhung3990
sumber
0

Kemungkinan lain untuk mempertahankan tema Tombol.

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

Dengan solusi ini jika Anda menambahkan @ color / your_color @ color / your_highlight_color di tema aktivitas Anda, Anda dapat memiliki tema Matherial di Lollipop dengan bayangan dan riak, dan untuk tombol datar versi sebelumnya dengan warna dan sorot coor saat Anda menekannya.

Apalagi dengan solusi ini autoresize gambar

Hasil: Pertama pada perangkat Lollipop Kedua: Pada perangkat pra-lollipop 3: Tombol tekan perangkat pra-lollipop

masukkan deskripsi gambar di sini

Anthone
sumber
0

Saya telah memusatkan textViewdengan ikon menggunakan paddingLeftdan dan menyelaraskan textView ke kiri | centerVertical . dan untuk celah kecil antara tampilan dan ikon yang saya gunakandrawablePadding

         <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" />
Zar E Ahmer
sumber
2
Ini tidak akan berfungsi di banyak layar, hanya di satu layar yang android:paddingLeftberfungsi.
soshial
0

Ini mungkin utas lama / tertutup tetapi saya telah mencari di mana-mana tidak menemukan sesuatu yang berguna, sampai saya memutuskan untuk membuat solusi saya sendiri. Jika ada orang di sini yang mencoba mencari jawaban, coba yang ini, mungkin menghemat waktu Anda berpikir

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

Karena Linear layout bertindak sebagai container dan orang yang memiliki selector, ketika Anda mengklik seluruh linear layout akan terlihat seperti apa seharusnya. jika Anda ingin keduanya berada di tengah, gunakan insteaf relatif. Jika Anda ingin memusatkan horizontal, ubah orientasi menjadi horizontal.

Perhatikan JANGAN lupa untuk menambahkan android: clickable = "true" ke penampung utama Anda (relatif atau linier) agar tindakan tersebut terjadi.

Sekali lagi ini mungkin utas lama tetapi masih dapat membantu seseorang di sana.

-selamat berharap ini membantu- happycodings.

ralphgabb.dll
sumber
0

Jika Anda menggunakan salah satu solusi tampilan kustom , berhati-hatilah, karena solusi tersebut sering gagal pada teks panjang atau multiline . Saya menulis ulang beberapa jawaban, mengganti onDraw()dan memahami bahwa itu adalah cara yang salah.

CoolMind
sumber
0

Saya telah melihat solusi untuk menyelaraskan drawable di awal / kiri tetapi tidak ada solusi untuk drawable end / kanan, jadi saya menemukan solusi ini. Ini menggunakan bantalan yang dihitung secara dinamis untuk menyelaraskan gambar dan teks di sisi kiri dan kanan.

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

Penting untuk menyetel gravitasi dalam tata letak Anda ke "center_vertical | start" atau "center_vertical | end" tergantung di mana Anda menyetel ikon. Sebagai contoh:

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

Satu-satunya masalah dengan implementasi ini adalah tombol hanya dapat memiliki satu baris teks, jika tidak, area teks akan mengisi tombol dan paddings akan menjadi 0.

Siim Puniste
sumber
-5

Gunakan ini android:background="@drawable/ic_play_arrow_black_24dp"

cukup atur latar belakang ke ikon yang ingin Anda pusatkan

kudzai zishumba
sumber