Cách căn giữa biểu tượng và văn bản trong một nút android với chiều rộng được đặt thành "điền chính"


118

Tôi muốn có một Nút Android với biểu tượng + văn bản ở giữa. Tôi đang sử dụng thuộc tính drawableLeft để đặt hình ảnh, điều này hoạt động tốt nếu nút có chiều rộng "wrap_content"nhưng tôi cần kéo dài đến chiều rộng tối đa, vì vậy tôi sử dụng chiều rộng "fill_parent". Thao tác này sẽ di chuyển biểu tượng của tôi thẳng sang bên trái của nút và tôi muốn cả biểu tượng và văn bản đều được căn giữa bên trong nút.

Tôi đã thử thiết lập phần đệm nhưng điều này chỉ cho phép cung cấp một giá trị cố định nên nó không phải là thứ tôi cần. Tôi cần căn chỉnh biểu tượng + văn bản ở giữa.

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

Bất kỳ đề xuất nào về cách tôi có thể đạt được điều đó?


Có thể là không có một giải pháp dễ dàng cho điều này? Tôi có phải thử với một nút 9patch img với biểu tượng ở đó không?
jloriente

Đây có thể là một giải pháp. Văn bản nút sẽ được bản địa hóa hay tĩnh?
Octavian A. Damiean

Nó được bản địa hóa. Không có bất kỳ giải pháp nào khác cho điều này? Tôi đã quản lý để làm điều đó với bản vá 9 nhưng gặp sự cố khi thay đổi ngôn ngữ.
jloriente

Điều gì về việc sử dụng một Nút với TOP có thể vẽ và thêm một số đệm vào nó?
Francesco

thiết kế khung xấu
Muhammad Babar

Câu trả lời:


75

android: drawableLeft luôn giữ android: paddingLeft như một khoảng cách so với đường viền bên trái. Khi nút không được đặt thành android: width = "wrap_content", nó sẽ luôn bị treo ở bên trái!

Với Android 4.0 (API cấp 14), bạn có thể sử dụng thuộc tính android: drawableStart để đặt một drawable ở đầu văn bản. Giải pháp tương thích ngược duy nhất mà tôi đưa ra là sử dụng ImageSpan để tạo 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);

Trong trường hợp của tôi, tôi cũng cần điều chỉnh thuộc tính android :vity của Nút để làm cho nó trông ở giữa:

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

Đẹp. Dòng cuối cùng phải làbutton.setText(buttonLabel)
AlexD

1
Unicode có nhiều biểu tượng ký tự tương thích với các chuỗi ký tự trong Android. Nếu bạn có thể tìm thấy một cái có thể chấp nhận được, đây là một giải pháp đơn giản và nó có thêm điểm cộng là nó sẽ mở rộng theo kích thước văn bản. Ví dụ, nó có một phong bì cho biểu tượng email và một vài điện thoại khác nhau cho nút gọi.
GLee

1
Tôi bối rối làm thế nào điều này hoạt động cho bất kỳ ai, đối với tôi, nó vẽ 2 biểu tượng ... một ở bên trái và một ở ngay giữa trung tâm hiển thị trên đầu văn bản.
Justin

11
drawableStart sẽ không hoạt động. Xem chủ đề này: stackoverflow.com/questions/15350990/… Ngoài ra, có vẻ như khi bạn đặt văn bản bằng cách sử dụng spannable, kiểu sẽ bị bỏ qua.
Dapp

11
drawableStart không làm việc, và nó đã được bổ sung ở mức API 17 đến hỗ trợ rtl
Silvia H

35

Tôi biết mình đã muộn trong việc trả lời câu hỏi này, nhưng điều này đã giúp tôi:

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

Tôi đã tìm thấy giải pháp này từ đây: Giao diện người dùng Android gặp khó khăn: tạo một nút với văn bản và biểu tượng ở giữa

nhập mô tả hình ảnh ở đây


6
Vấn đề với điều này là nút không phải là chiều rộng của bố cục khung.
Clive Jefferies

29

Tôi đã sử dụng LinearLayout thay vì Button . Các OnClickListener , mà tôi cần phải sử dụng hoạt động tốt cũng cho 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

Tất cả các câu trả lời trước đây dường như đã lỗi thời

Bạn có thể sử dụng tính năng MaterialButtonbây giờ cho phép thiết lập lực hấp dẫn của biểu tượng.

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

nhập mô tả hình ảnh ở đây

Để sử dụng các thành phần vật liệu, bạn rõ ràng sẽ cần:

Thêm phụ thuộc implementation 'com.google.android.material:material:1.3.0-alpha01'(sử dụng phiên bản mới nhất)

Làm cho chủ đề của bạn mở rộng chủ đề Thành phần Vật liệu

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

Trong trường hợp bạn không thể làm như vậy, hãy mở rộng nó từ chủ đề Material Bridge

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

Cảm ơn! Bạn đã cứu ngày của tôi! Hoạt động tốt
Black_Zerg

9

Tôi điều chỉnh nó bằng cách thêm padding trái và phải như sau:

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

PaddingLeft và paddingRight đã giúp tôi căn giữa. ủng hộ giải pháp dễ dàng.
Arrie

2
Làm thế nào để bạn quản lý thực tế rằng chiều rộng của bạn là động? Nếu bạn xoay màn hình, tất cả các biểu tượng của bạn sẽ không được căn giữa đúng không? Tôi đang đối mặt với vấn đề này thực sự
Jacks

đây là câu trả lời tốt nhất!
Dody Rachmat Wicaksono

8

Gần đây tôi đã gặp phải vấn đề tương tự. Cố gắng tìm một giải pháp rẻ hơn nên đã nghĩ ra điều này.

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

Sau đó, chỉ cần gọi OnClickListenertrên LinearLayout.

Hy vọng điều này sẽ giúp ai đó vì nó có vẻ như là một vấn đề rất phổ biến. :)


1
Đây là một ý tưởng tốt, nhưng là một giải pháp tồi. Bạn có thể đạt được điều tương tự chỉ với một TextView bằng cách sử dụng thuộc tính drawableLeft. Điều này cho phép bạn xem một phần có thể vẽ ở bên trái của văn bản.
muetzenflo

@muetzenflo yup, đúng vậy. nhưng khi bạn làm cho textView khớp với chiều rộng gốc, bản vẽ của bạn sẽ di chuyển sang cực trái ngay cả khi bạn căn giữa văn bản. xin vui lòng cho tôi biết nếu tôi sai. và câu hỏi chỉ là về điều đó.
Ankit Popli

ah xin lỗi..tôi đến đây vì chính xác vấn đề này và mất tập trung sau khi thử quá nhiều thứ :) Đoán là tôi không nhìn thấy rừng cho cây. Lỗi của tôi!
muetzenflo

7

Bạn có thể sử dụng một nút tùy chỉnh để đo và vẽ chính nó để chứa một bên trái có thể kéo được. Vui lòng tìm ví dụ và cách sử dụng tại đây

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

Sử dụng

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

Bạn có thể bao gồm mã trong câu trả lời của bạn, mà nên là cách ưa thích (nếu nó không quá dài), là các liên kết có thể chết trên tốn nhiều thời gian
Lukas Knuth

2
Không chính xác lắm nhưng tôi hiểu
Alex Semeniuk

Nó dịch đúng văn bản, nhưng không đủ (hình ảnh chồng lên văn bản). Ngoài ra, như các giải pháp của chế độ xem tùy chỉnh khác, nó không chấp nhận văn bản dài.
CoolMind

5

Đây là giải pháp của tôi, tôi đã viết 3 năm trước. Nút có văn bản và biểu tượng bên trái và nằm trong khung là nút thực tế ở đây và có thể được kéo dài bởi fill_parent. Tôi không thể kiểm tra nó một lần nữa nhưng nó đã hoạt động trở lại sau đó. Có lẽ Nút không cần phải được sử dụng và có thể được thay thế bằng TextView nhưng tôi sẽ không kiểm tra nó ngay bây giờ và nó không thay đổi chức năng quá nhiều ở đây.

<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
Bây giờ tôi thấy rằng tôi không đơn độc với giải pháp này :)
Renetik

4

Tôi biết câu hỏi này hơi cũ hơn một chút, nhưng có lẽ bạn vẫn đang tìm kiếm các gợi ý hoặc cách giải quyết:

Tạo một RelativeLayout "wrap_content" với hình ảnh nút làm nền hoặc chính nút làm phần tử đầu tiên của bố cục. Lấy một LinearLayout và đặt nó thành "layout_centerInParent" và "wrap_content". Sau đó, đặt Có thể vẽ của bạn làm Chế độ xem hình ảnh. Cuối cùng, hãy đặt TextView với văn bản của bạn (ngôn ngữ).

về cơ bản bạn có cấu trúc này:

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

hoặc như thế này:

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

Tôi biết với giải pháp này có nhiều yếu tố cần xử lý, nhưng bạn có thể tạo nút tùy chỉnh của riêng mình rất dễ dàng với nó và cũng có thể đặt vị trí chính xác của văn bản và các bảng vẽ :)


Cách tiếp cận này có thể hoạt động tốt. Trong trường hợp của tôi, tất cả những gì tôi cần là một RelativeLayout chứa TextView. RelativeLayout có nền, TextView có biểu tượng drawableLeft. Sau đó, trong các mã: đính kèm OnClickListener đến RelativeLayout và findViewById cho TextView riêng nếu cần thiết
Stan Kurdziel

Cấu trúc được đề xuất đầu tiên cung cấp Ngoại lệ "Không thể truyền nút tới ViewGroup".
Youngjae

4

Cách giải quyết của tôi liên quan đến việc bao quanh nút bằng <View ../>các yếu tố nhẹ có thể thay đổi kích thước động. Dưới đây là một số ví dụ về những gì có thể đạt được với điều này:

Demo của Dev-iL

Lưu ý rằng vùng có thể nhấp của các nút trong ví dụ 3 giống như trong 2 (nghĩa là có khoảng trắng), khác với ví dụ 4 là không có khoảng trống "không thể nhấp" ở giữa.

Mã:

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

Bạn có thể tạo một widget tùy chỉnh:

IButton lớp 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);
}

}

Bố cục 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>

Để sử dụng tiện ích tùy chỉnh này:

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

Bạn phải cung cấp không gian tên cho các thuộc tính tùy chỉnh xmlns: ibutton = "http://schemas.android.com/apk/res/com.test.android.xxx" trong đó com.test.android.xxx là gói gốc của ứng dụng.

Chỉ cần đặt nó bên dưới xmlns: android = "http://schemas.android.com/apk/res/android".

Điều cuối cùng bạn cần là các thuộc tính tùy chỉnh trong attrs.xml.

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

Để định vị tốt hơn, hãy bọc Nút tùy chỉnh bên trong LinearLayout, nếu bạn muốn tránh các sự cố tiềm ẩn với định vị RelativeLayout.

Thưởng thức!


2

Gặp vấn đề tương tự nhưng muốn có trung tâm có thể vẽ được mà không có văn bản và không có bố cục được bao bọc. Giải pháp là tạo nút tùy chỉnh và thêm một nút có thể vẽ khác ngoài LEFT, RIGHT, TOP, BOTTOM. Người ta có thể dễ dàng sửa đổi vị trí có thể vẽ và đặt nó ở vị trí mong muốn so với văn bản.

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>

sử dụng

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

Cảm ơn! Đó là những gì tôi đang tìm kiếm.
MistaGreen

u sẽ hài lòng giúp đỡ tôi trong câu hỏi này, stackoverflow.com/questions/35912539/... , với câu trả lời của bạn tôi rất gần gũi với nó nhưng hai drawables xuất hiện
Reprator

Giải pháp này đặt có thể vẽ vào giữa một nút, ngay trên văn bản được căn giữa.
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>

Đặt FrameLayout trong LinearLayout và đặt hướng thành Horizontal.


1

Bạn có thể đặt nút trên 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

Điều gì xảy ra nếu bạn dùng thử android :vity = "center_horizontal"?


5
Nó không hoạt động. Văn bản được căn giữa một chút nhưng drawableLeft dính ở phía bên trái.
Peter Ajtai

0

Tôi nghĩ android :vity = "center" sẽ hoạt động


6
Không hiệu quả với tôi. Nó căn giữa văn bản, nhưng drawableLeft vẫn ở bên trái.
Peter Ajtai

Bạn phải khai báo vào biểu tượng và văn bản dưới cùng phụ huynh, sử dụng Android: trọng lực = "center" cho phụ huynh
devanshu_kaushik

0

Theo đề xuất của Rodja, trước 4.0 không có cách nào trực tiếp để căn giữa văn bản với bảng vẽ. Và thực sự việc đặt giá trị padding_left sẽ di chuyển có thể vẽ ra khỏi đường viền. Do đó, đề xuất của tôi là trong thời gian chạy, bạn tính toán chính xác bao nhiêu pixel từ đường viền bên trái có thể vẽ của bạn cần và sau đó chuyển nó bằng cách sử dụng setPadding Tính toán của bạn có thể giống như

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

Chiều rộng của tệp có thể vẽ của bạn là cố định và bạn có thể tra cứu nó và bạn cũng có thể tính toán hoặc đoán chiều rộng văn bản.

Cuối cùng, bạn sẽ cần nhiều giá trị đệm theo mật độ màn hình, bạn có thể thực hiện điều này bằng cách sử dụng DisplayMetrics



0

public class DrawableCenterTextView mở rộng 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);
}

}


Điều này không hiệu quả với tôi cả. Bạn có thể vui lòng cho một ví dụ? Có lẽ tôi không sử dụng nó một cách chính xác
android phát triển

0

Sửa chữa bẩn.

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

Xác định phần đệm bên phải giải quyết được mục đích. Tuy nhiên, đối với các màn hình khác nhau, hãy sử dụng các phần đệm khác nhau và đặt nó vào tài nguyên kích thước trong thư mục giá trị tương ứng.


0

Sử dụng RelativeLayout (container) và android: layout_centerHorizontal = "true" , mẫu của tôi:

                <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

Khả năng khác để giữ chủ đề Nút.

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

Với giải pháp này nếu bạn thêm @ color / your_color @ color / your_highlight_color vào chủ đề hoạt động của mình, bạn có thể có chủ đề Toán học trên Lollipop với bóng mờ và gợn sóng, và đối với phiên bản trước nút phẳng với màu của bạn và tô sáng khi bạn nhấn nó.

Hơn nữa, với giải pháp này sẽ tự động kích thước hình ảnh

Kết quả: Thứ nhất trên thiết bị Lollipop Thứ hai: Trên thiết bị pre-lollipop Thứ 3: Nút bấm trên thiết bị pre-lollipop

nhập mô tả hình ảnh ở đây


0

Tôi đã căn giữa textViewvới biểu tượng bằng cách sử dụng paddingLeftvà căn chỉnh textView sang trái | centerVertical . và để có một khoảng cách nhỏ giữa chế độ xem và biểu tượng mà tôi đã sử dụngdrawablePadding

         <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
Điều này sẽ không hoạt động trên nhiều màn hình, chỉ trên một màn hình android:paddingLefthoạt động.
soshial

0

Đây có thể là một chuỗi cũ / đã đóng nhưng tôi đã tìm kiếm khắp nơi không tìm thấy thứ gì hữu ích, cho đến khi tôi quyết định tạo ra giải pháp của riêng mình. Nếu có ai đó ở đây đang cố gắng tìm kiếm câu trả lời, hãy thử câu này, có thể giúp bạn tiết kiệm một phút suy nghĩ

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

Bởi vì bố cục tuyến tính đóng vai trò là vùng chứa và là người có bộ chọn, khi bạn nhấp vào toàn bộ bố cục tuyến tính, nó sẽ trông như thế nào. nếu bạn muốn nó được căn giữa cả hai, hãy sử dụng insteaf tương đối. Nếu bạn muốn nó căn giữa theo chiều ngang, hãy thay đổi hướng sang ngang.

Lưu ý ĐỪNG quên thêm android: clickable = "true" vào vùng chứa chính của bạn (tương đối hoặc tuyến tính) để hành động diễn ra.

Một lần nữa, đây có thể là chủ đề cũ nhưng vẫn có thể giúp ích cho ai đó ở đó.

-các bạn hy vọng nó có ích- happycodings.


0

Nếu bạn sử dụng một trong các giải pháp của chế độ xem tùy chỉnh , hãy cẩn thận vì chúng thường không thành công trên văn bản dài hoặc nhiều dòng . Tôi đã viết lại một số câu trả lời, thay thế onDraw()và hiểu rằng đó là một cách sai.


0

Tôi đã thấy các giải pháp để căn chỉnh có thể kéo được ở đầu / trái nhưng không có gì cho cuối / phải có thể vẽ, vì vậy tôi đã đưa ra giải pháp này. Nó sử dụng các khoảng đệm được tính toán động để căn chỉnh văn bản và văn bản có thể vẽ ở cả bên trái và bên phải.

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

Điều quan trọng là đặt trọng lực trong bố cục của bạn thành "center_vertical | start" hoặc "center_vertical | end" tùy thuộc vào vị trí bạn đặt biểu tượng. Ví dụ:

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

Chỉ có một vấn đề với việc triển khai này là nút chỉ có thể có một dòng văn bản, nếu không thì diện tích văn bản lấp đầy nút và phần đệm sẽ bằng 0.


-5

dùng cái này android:background="@drawable/ic_play_arrow_black_24dp"

chỉ cần đặt nền thành biểu tượng bạn muốn căn giữa

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.