วิธีตั้งค่าไอคอนและข้อความตรงกลางในปุ่ม Android โดยตั้งค่าความกว้างเป็น "เติมแม่"


118

ฉันต้องการมีปุ่ม Android ที่มีไอคอน + ข้อความอยู่ตรงกลาง ฉันใช้แอตทริบิวต์ drawableLeft การตั้งค่าภาพนี้ทำงานได้ดีถ้าปุ่มมีความกว้างของแต่ฉันต้องการที่จะยืดความกว้างสูงสุดดังนั้นฉันจะใช้ความกว้าง"wrap_content" "fill_parent"สิ่งนี้จะย้ายไอคอนของฉันไปทางซ้ายของปุ่มตรงและฉันต้องการให้ทั้งไอคอนและข้อความอยู่กึ่งกลางภายในปุ่ม

ฉันลองตั้งค่าช่องว่างภายใน แต่อนุญาตให้ให้ค่าคงที่เท่านั้นดังนั้นจึงไม่ใช่สิ่งที่ฉันต้องการ ฉันต้องการให้ไอคอน + ข้อความอยู่ตรงกลาง

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

ข้อเสนอแนะใด ๆ เกี่ยวกับวิธีที่ฉันจะบรรลุเป้าหมายนั้น?


เป็นไปได้ว่าไม่มีวิธีง่ายๆสำหรับสิ่งนี้? ฉันต้องลองด้วยปุ่ม 9patch img ที่มีไอคอนอยู่ในนั้นหรือไม่?
jloriente

นี่อาจเป็นวิธีแก้ปัญหา ข้อความของปุ่มจะถูกแปลเป็นภาษาท้องถิ่นหรือคงที่?
Octavian A. Damiean

เป็นภาษาท้องถิ่น ไม่มีทางออกอื่นสำหรับสิ่งนี้? ฉันจัดการมันด้วยแพทช์ 9 แต่มีปัญหาเมื่อเปลี่ยนสถานที่
jloriente

สิ่งที่เกี่ยวกับการใช้ปุ่มที่มี TOP ที่ดึงได้และเพิ่มช่องว่างภายใน?
Francesco

การออกแบบกรอบที่ไม่ดี
มูฮัมหมัดบาบาร์

คำตอบ:


75

android: drawableLeft มักจะทำให้ android: paddingLeft เป็นระยะห่างจากเส้นขอบด้านซ้าย เมื่อไม่ได้ตั้งค่าปุ่มเป็น android: width = "wrap_content" ปุ่มจะค้างไปทางซ้ายเสมอ!

ด้วย Android 4.0 (API ระดับ 14) คุณสามารถใช้android: drawableStartแอตทริบิวต์เพื่อวาง drawable ที่จุดเริ่มต้นของข้อความ โซลูชันเดียวที่เข้ากันได้แบบย้อนหลังที่ฉันคิดขึ้นคือการใช้ImageSpanเพื่อสร้าง 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);

ในกรณีของฉันฉันจำเป็นต้องปรับคุณลักษณะ android: แรงโน้มถ่วงของปุ่มเพื่อให้ดูอยู่ตรงกลาง:

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

ดี บรรทัดสุดท้ายควรเป็นbutton.setText(buttonLabel)
AlexD

1
Unicode มีชุดไอคอนอักขระมากมายที่เข้ากันได้กับสตริงใน Android หากคุณสามารถหาสิ่งที่ยอมรับได้นี่เป็นวิธีง่ายๆและมีโบนัสเพิ่มเติมที่จะปรับขนาดตามขนาดตัวอักษร ตัวอย่างเช่นมีซองจดหมายสำหรับไอคอนอีเมลและโทรศัพท์สองสามเครื่องสำหรับปุ่มโทร
GLee

1
ฉันสับสนว่าสิ่งนี้ใช้ได้ผลกับทุกคนอย่างไรสำหรับฉันมันวาด 2 ไอคอน ... ทางเดียวไปทางซ้ายและอีกอันอยู่ตรงกลางซึ่งแสดงอยู่ด้านบนของข้อความ
จัสติน

11
drawableStart จะไม่ทำงาน ดูหัวข้อนี้: stackoverflow.com/questions/15350990/… นอกจากนี้ดูเหมือนว่าเมื่อคุณตั้งค่าข้อความโดยใช้ spannable สไตล์จะถูกละเว้น
Dapp

11
drawableStart ไม่ทำงานและถูกเพิ่มใน API ระดับ 17 เพื่อรองรับ rtl
Silvia H

35

ฉันรู้ว่าฉันตอบคำถามนี้ช้า แต่สิ่งนี้ช่วยฉันได้:

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

ฉันพบวิธีแก้ปัญหานี้จากที่นี่: การต่อสู้ UI ของ Android: การสร้างปุ่มที่มีข้อความและไอคอนตรงกลาง

ใส่คำอธิบายภาพที่นี่


6
ปัญหานี้คือปุ่มไม่ใช่ความกว้างของเค้าโครงเฟรม
Clive Jefferies

30

คำตอบก่อนหน้านี้ทั้งหมดดูเหมือนจะล้าสมัย

คุณสามารถใช้MaterialButtonตอนนี้ซึ่งช่วยในการตั้งค่าแรงโน้มถ่วงของไอคอน

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

ใส่คำอธิบายภาพที่นี่

สำหรับการใช้ส่วนประกอบวัสดุคุณจะต้อง:

เพิ่มการอ้างอิง implementation 'com.google.android.material:material:1.3.0-alpha01'(ใช้เวอร์ชันล่าสุด)

ทำให้ธีมของคุณขยายธีมส่วนประกอบวัสดุ

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

ในกรณีที่คุณไม่สามารถทำได้ให้ขยายจากธีม Material Bridge

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

ขอบคุณ! คุณช่วยวันของฉัน! ใช้งานได้ดี
Black_Zerg

29

ผมใช้LinearLayoutแทนปุ่ม OnClickListenerซึ่งผมจำเป็นต้องใช้การทำงานที่ดียัง 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>

9

ฉันปรับโดยเพิ่มช่องว่างด้านซ้ายและขวาดังนี้:

<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 และ paddingRight ช่วยให้ฉันอยู่ตรงกลางได้ การโหวตเพื่อแก้ปัญหาที่ง่าย
Arrie

2
คุณจัดการกับความจริงที่ว่าความกว้างของคุณเป็นแบบไดนามิกได้อย่างไร? หากคุณหมุนหน้าจอไอคอนทั้งหมดของคุณจะไม่อยู่ตรงกลางใช่ไหม ฉันประสบปัญหานี้จริง
Jacks

นี่คือคำตอบที่ดีที่สุด!
Dody Rachmat Wicaksono

8

ฉันเพิ่งเจอปัญหาเดียวกัน พยายามหาวิธีแก้ปัญหาที่ถูกกว่าจึงคิดสิ่งนี้ขึ้นมา

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

จากนั้นก็โทรไปOnClickListenerที่LinearLayoutบน

หวังว่านี่จะช่วยใครบางคนได้เพราะดูเหมือนว่าจะเป็นปัญหาที่พบบ่อยมาก :)


1
นี่เป็นความคิดที่ดี แต่เป็นวิธีแก้ปัญหาที่ไม่ดี คุณสามารถบรรลุสิ่งเดียวกันได้ด้วย TextView เดียวโดยใช้ drawableLeft-attribute สิ่งนี้ช่วยให้คุณสามารถดูวาดได้ทางด้านซ้ายของข้อความ
muetzenflo

@muetzenflo ใช่แล้ว แต่เมื่อคุณทำให้ textView ตรงกับความกว้างหลักที่วาดได้ของคุณจะเลื่อนไปทางซ้ายสุดแม้ว่าคุณจะจัดข้อความไว้ตรงกลางก็ตาม โปรดแจ้งให้เราทราบหากฉันผิด และคำถามเกี่ยวกับเรื่องนี้เท่านั้น
Ankit Popli

อาขอโทษ.. ฉันมาที่นี่เพื่อแก้ไขปัญหานี้และเสียสมาธิหลังจากลองทำหลาย ๆ อย่างมากเกินไป :) เดาว่าฉันไม่เห็นป่าสำหรับต้นไม้ ความผิดของฉัน!
muetzenflo

7

คุณสามารถใช้ปุ่มที่กำหนดเองซึ่งวัดและดึงตัวเองเพื่อรองรับการดึงด้านซ้าย โปรดดูตัวอย่างและการใช้งานที่นี่

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

การใช้

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

คุณสามารถใส่รหัสในคำตอบของคุณซึ่งควรเป็นวิธีที่ต้องการ (หากไม่ยาวเกินไป) เนื่องจากลิงก์อาจหายไปเมื่อเวลาผ่านไป -
Lukas Knuth

2
ไม่ค่อยถูกต้อง แต่ฉันเข้าใจ
Alex Semeniuk

มันเลื่อนข้อความไปทางขวา แต่ไม่เพียงพอ (รูปภาพซ้อนทับข้อความ) นอกจากนี้ในฐานะโซลูชันของมุมมองแบบกำหนดเองอื่น ๆ จะไม่ยอมรับข้อความที่ยาวทางขวา
CoolMind

5

นี่คือวิธีแก้ปัญหาของฉันที่ฉันเขียนเมื่อ 3 ปีก่อน ปุ่มมีข้อความและไอคอนด้านซ้ายและอยู่ในกรอบซึ่งเป็นปุ่มจริงที่นี่และสามารถขยายได้โดย Fill_parent ฉันไม่สามารถทดสอบได้อีก แต่ตอนนั้นใช้งานได้ อาจไม่จำเป็นต้องใช้ปุ่มและสามารถแทนที่ด้วย TextView ได้ แต่ฉันจะไม่ทดสอบในตอนนี้และจะไม่เปลี่ยนฟังก์ชันการทำงานมากเกินไปที่นี่

<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
ตอนนี้ฉันเห็นว่าฉันไม่ได้อยู่คนเดียวกับโซลูชันนี้ :)
Renetik

4

ฉันรู้ว่าคำถามนี้เก่ากว่าเล็กน้อย แต่บางทีคุณอาจยังเปิดกว้างสำหรับคำแนะนำหรือวิธีแก้ปัญหา:

สร้าง RelativeLayout "wrap_content" โดยให้ภาพปุ่มเป็นพื้นหลังหรือปุ่มเป็นองค์ประกอบแรกของเค้าโครง รับ LinearLayout และตั้งค่าเป็น "layout_centerInParent" และ "wrap_content" จากนั้นตั้งค่า Drawable ของคุณเป็น Imageview ในที่สุดตั้ง TextView ด้วยข้อความของคุณ (โลแคล)

โดยพื้นฐานแล้วคุณมีโครงสร้างนี้:

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

หรือเช่นนี้:

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

ฉันรู้ว่าโซลูชันนี้มีองค์ประกอบมากมายที่ต้องจัดการ แต่คุณสามารถสร้างปุ่มที่กำหนดเองของคุณเองได้อย่างง่ายดายและยังกำหนดตำแหน่งที่แน่นอนของข้อความและสิ่งที่วาดได้ :)


แนวทางนี้สามารถใช้ได้ดี ในกรณีของฉันสิ่งที่ฉันต้องการคือ RelativeLayout ที่มี TextView RelativeLayout มีพื้นหลัง TextView ได้รับไอคอน drawableLeft จากนั้นในโค้ด: แนบ onClickListener กับ RelativeLayout และ findViewById สำหรับ TextView แยกกันหากจำเป็น
Stan Kurdziel

โครงสร้างที่แนะนำครั้งแรกให้ข้อยกเว้น "ไม่สามารถส่งปุ่มไปยัง ViewGroup"
Youngjae

4

วิธีการแก้ปัญหาของฉันเกี่ยวข้องกับปุ่มที่มี<View ../>องค์ประกอบน้ำหนักเบา ที่ปรับขนาดแบบไดนามิก ด้านล่างนี้เป็นตัวอย่างของสิ่งที่สามารถทำได้ด้วยสิ่งนี้:

สาธิตโดย Dev-iL

โปรดทราบว่าพื้นที่ที่คลิกได้ของปุ่มในตัวอย่างที่ 3 จะเหมือนกับใน 2 (เช่นมีช่องว่าง) ซึ่งแตกต่างจากตัวอย่างที่ 4 ตรงที่ไม่มีช่องว่าง "ไม่สามารถคลิกได้" อยู่ระหว่าง

รหัส:

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

คุณสามารถสร้างวิดเจ็ตแบบกำหนดเอง:

IButton คลาส 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);
}

}

เค้าโครง 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>

ในการใช้วิดเจ็ตที่กำหนดเองนี้:

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

คุณต้องระบุเนมสเปซสำหรับแอตทริบิวต์ที่กำหนดเอง xmlns: ibutton = "http://schemas.android.com/apk/res/com.test.android.xxx" โดยที่ com.test.android.xxx เป็นแพ็กเกจรากของ แอปพลิเคชัน

เพียงวางไว้ด้านล่าง xmlns: android = "http://schemas.android.com/apk/res/android"

สิ่งสุดท้ายที่คุณต้องมีคือแอตทริบิวต์ที่กำหนดเองใน attrs.xml

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

เพื่อให้ได้ตำแหน่งที่ดีขึ้นให้รวมปุ่มที่กำหนดเองไว้ใน LinearLayout หากคุณต้องการหลีกเลี่ยงปัญหาที่อาจเกิดขึ้นกับตำแหน่ง RelativeLayout

สนุก!


2

มีปัญหาที่คล้ายกัน แต่ต้องการให้วาดตรงกลางได้โดยไม่มีข้อความและไม่มีเค้าโครงที่ห่อหุ้ม วิธีแก้ปัญหาคือการสร้างปุ่มที่กำหนดเองและเพิ่มอีกหนึ่งปุ่มที่วาดได้นอกเหนือจาก LEFT, RIGHT, TOP, BOTTOM เราสามารถปรับเปลี่ยนตำแหน่งที่วาดได้อย่างง่ายดายและกำหนดให้อยู่ในตำแหน่งที่ต้องการเมื่อเทียบกับข้อความ

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>

การใช้

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

ขอบคุณ! นั่นคือสิ่งที่ฉันกำลังมองหา
MistaGreen

คุณช่วยฉันได้ไหมในคำถามนี้stackoverflow.com/questions/35912539/…ด้วยคำตอบของคุณฉันอยู่ใกล้มันมาก แต่มีสอง drawables ปรากฏขึ้น
รายงาน

โซลูชันนี้วางไว้ตรงกลางปุ่มโดยวางไว้เหนือข้อความที่อยู่ตรงกลาง
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>

วาง FrameLayout ใน LinearLayout และตั้งค่าการวางแนวเป็นแนวนอน


1

คุณสามารถวางปุ่มไว้เหนือ 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

จะเกิดอะไรขึ้นถ้าคุณลองใช้ android: แรงโน้มถ่วง = "center_horizontal"


5
มันใช้ไม่ได้ ข้อความค่อนข้างอยู่กึ่งกลาง แต่ drawableLeft ติดไปทางด้านซ้าย
Peter Ajtai

0

ฉันคิดว่า android: แรงโน้มถ่วง = "center" น่าจะใช้ได้


6
ไม่ได้ผลสำหรับฉัน มันอยู่ตรงกลางข้อความ แต่ drawableLeft ยังคงอยู่ทางซ้ายสุด
Peter Ajtai

คุณต้องประกาศไอคอนและข้อความภายใต้พาเรนต์เดียวกันใช้ android: แรงโน้มถ่วง = "center" สำหรับผู้ปกครอง
devanshu_kaushik

0

ตามคำแนะนำของ Rodja ก่อนหน้า 4.0 ไม่มีวิธีโดยตรงในการจัดกึ่งกลางข้อความด้วยสิ่งที่วาดได้ และแน่นอนว่าการตั้งค่า padding_left จะทำให้สิ่งที่ดึงได้ออกไปจากเส้นขอบ ดังนั้นคำแนะนำของฉันคือในรันไทม์คุณคำนวณจำนวนพิกเซลจากเส้นขอบด้านซ้ายที่คุณต้องการจากนั้นจึงส่งผ่านโดยใช้setPadding การ คำนวณของคุณอาจเป็นเช่น

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

ความกว้างของ drawable ของคุณได้รับการแก้ไขและคุณสามารถค้นหาได้และคุณยังสามารถคำนวณหรือคาดเดาความกว้างของข้อความได้

สุดท้ายคุณจะต้องเพิ่มค่าช่องว่างภายในหลาย ๆ ค่าตามความหนาแน่นของหน้าจอซึ่งคุณสามารถทำได้โดยใช้DisplayMetrics



0

คลาสสาธารณะ DrawableCenterTextView ขยาย 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);
}

}


สิ่งนี้ไม่ได้ผลสำหรับฉันเลย ช่วยแสดงตัวอย่างได้ไหม บางทีฉันอาจใช้ไม่ถูกต้อง
นักพัฒนา android

0

แก้ไขสกปรก

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

การหาช่องว่างภายในที่ถูกต้องช่วยแก้จุดประสงค์ อย่างไรก็ตามสำหรับหน้าจอที่แตกต่างกันให้ใช้ช่องว่างภายในที่แตกต่างกันและวางไว้ในทรัพยากรลดขนาดในโฟลเดอร์ค่าที่เกี่ยวข้อง


0

ใช้RelativeLayout (คอนเทนเนอร์) และandroid: layout_centerHorizontal = "true" ตัวอย่างของฉัน:

                <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

ความเป็นไปได้อื่น ๆ ในการเก็บธีมปุ่ม

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

ด้วยวิธีนี้หากคุณเพิ่ม @ color / your_color @ color / your_highlight_color ในธีมกิจกรรมของคุณคุณสามารถมีธีม Matherial บน Lollipop ที่มีเงาและระลอกคลื่นและสำหรับปุ่มแบนเวอร์ชันก่อนหน้าพร้อมกับสีของคุณและไฮไลต์สีเมื่อคุณกด

ยิ่งไปกว่านั้นด้วยโซลูชันนี้จะปรับขนาดรูปภาพโดยอัตโนมัติ

ผลลัพธ์: อันดับแรกบนอุปกรณ์ Lollipop ประการที่สอง: บนอุปกรณ์ก่อนอมยิ้ม 3: ปุ่มกดก่อนอุปกรณ์อมยิ้ม

ใส่คำอธิบายภาพที่นี่


0

ฉันได้เป็นศูนย์กลางtextViewที่มีไอคอนใช้paddingLeftและการจัดตำแหน่งและ TextView ไปซ้าย | centerVertical และสำหรับช่องว่างเล็ก ๆ ระหว่างมุมมองและไอคอนที่ฉันใช้drawablePadding

         <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
สิ่งนี้จะใช้ไม่ได้กับหลาย ๆ หน้าจอเฉพาะในหน้าจอเดียวที่ใช้android:paddingLeftงานได้
โซเชียล

0

นี่อาจเป็นกระทู้เก่า / ปิด แต่ฉันค้นหาทุกที่แล้วไม่พบสิ่งที่เป็นประโยชน์จนกระทั่งฉันตัดสินใจสร้างโซลูชันของตัวเอง หากมีใครก็ตามที่พยายามมองหาคำตอบลองคำตอบนี้อาจช่วยให้คุณประหยัดเวลาคิดได้สักนาที

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

เนื่องจากเลย์เอาต์เชิงเส้นทำหน้าที่เป็นคอนเทนเนอร์และผู้ที่มีตัวเลือกเมื่อคุณคลิกเลย์เอาต์เชิงเส้นทั้งหมดมันจะมีลักษณะที่ควรจะเป็น หากคุณต้องการให้ทั้งคู่อยู่กึ่งกลางให้ใช้ insteaf แบบสัมพัทธ์ หากคุณต้องการให้อยู่กึ่งกลางในแนวนอนให้เปลี่ยนการวางแนวเป็นแนวนอน

โปรดทราบ อย่าลืมเพิ่มandroid: clickable = "true"ลงในคอนเทนเนอร์หลักของคุณ (สัมพัทธ์หรือเชิงเส้น) เพื่อให้การดำเนินการเกิดขึ้น

อีกครั้งนี่อาจเป็นกระทู้เก่า แต่อาจช่วยใครบางคนได้ที่นั่น

- เชียร์หวังว่ามันจะช่วยได้ - happycodings


0

หากคุณใช้หนึ่งในมุมมองที่กำหนดเองของการแก้ปัญหาต้องระวังเพราะพวกเขามักจะล้มเหลวในยาวหรือข้อความหลาย ฉันเขียนคำตอบใหม่แทนที่onDraw()และเข้าใจว่านั่นเป็นวิธีที่ผิด


0

ฉันได้เห็นวิธีแก้ปัญหาสำหรับการจัดแนว drawable ที่จุดเริ่มต้น / ซ้าย แต่ไม่มีอะไรสำหรับปลาย / ขวาที่ดึงได้ดังนั้นฉันจึงคิดวิธีแก้ปัญหานี้ ใช้การคำนวณแบบไดนามิกสำหรับการจัดแนว drawable และข้อความทั้งด้านซ้ายและด้านขวา

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

สิ่งสำคัญคือต้องตั้งค่าแรงโน้มถ่วงในเค้าโครงของคุณเป็น "center_vertical | start" หรือ "center_vertical | end" ขึ้นอยู่กับว่าคุณตั้งค่าไอคอนไว้ที่ใด ตัวอย่างเช่น:

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

ปัญหาเดียวในการใช้งานนี้คือปุ่มสามารถมีข้อความได้เพียงบรรทัดเดียวมิฉะนั้นพื้นที่ของข้อความจะเต็มปุ่มและการพายจะเป็น 0


-5

ใช้สิ่งนี้ android:background="@drawable/ic_play_arrow_black_24dp"

เพียงแค่ตั้งค่าพื้นหลังเป็นไอคอนที่คุณต้องการจัดกึ่งกลาง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.