Android:如何在Button或ImageButton上组合文本和图像

578

我想在按钮上添加一个背景图片,并根据运行时发生的情况动态地添加一些文本。如果使用ImageButton,甚至无法添加文本。如果使用Button,可以添加文本,但仅能定义一个图片,例如android:drawableBottom和类似的XML属性,如此处所定义。然而,这些属性只能在x轴和y轴维度上组合文本和图像,也就是说,我可以围绕我的文本绘制一个图像,但不能在我的文本下面或下方绘制图像(其中z轴被定义为从显示器中出来)。

有关如何解决此问题的任何建议吗?一种想法是扩展ButtonImageButton并覆盖draw()方法。但是,凭借我的目前的知识水平,我不知道如何做到这一点(2D渲染)。也许有经验的人知道解决方案或至少有一些开始的指针?


1
使用9Patch,智能解决方案 - Hossein Kurd
1
嗨@Charuක,请查看一下这个链接,如果可以的话:https://dev59.com/MaDia4cB1Zd3GeqPAkHt - Mohamed Rihan
1
最好的方法是使用CardView >> 只需将LinearLayout放入CardView中,将image设置为LinearLayout的背景,并在此LinearLayout中使用textView。有关更多详细信息,请查看此链接> https://dev59.com/AW855IYBdhLWcg3wPBz6#65172123。谢谢,编码愉快 :) - AG-Developer
19个回答

635

对于只想要在一个按钮中放置来自不同文件的背景、图标和文本的用户:在一个上设置背景、drawableTop/Bottom/Rigth/Left和padding属性。

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/home_btn_test"
        android:drawableTop="@drawable/home_icon_test"
        android:textColor="#FFFFFF"
        android:id="@+id/ButtonTest"
        android:paddingTop="32sp"
        android:drawablePadding="-15sp"
        android:text="this is text"></Button>

如果您想进行更复杂的排列,还可以使用RelativeLayout(或任何其他布局)并将其设为可点击。

教程:这篇很好的教程覆盖了两种情况:http://izvornikod.com/Blog/tabid/82/EntryId/8/Creating-Android-button-with-image-and-text-using-relative-layout.aspx


74
要以编程方式完成此操作,使用b.setCompoundDrawablesWithIntrinsicBounds(null,R.drawable.home_icon_test,null,null)替代android:drawableTop,并使用b.setPadding(0,32,0,0)替代android:paddingTop - Alex Jasmin
4
将布局用作按钮实际上是一种非常灵活的方法。 - sstn
4
如果你在使用资源id来绘制可绘制对象,只需将null替换为0即可。 - Ran
3
如何将背景图片缩放以适应按钮? - Alston
2
@Stallman 这里有一个基于 XML 和代码的解决方案来进行缩放:https://dev59.com/zl3Va4cB1Zd3GeqPA3_8 - OneWorld
显示剩余5条评论

359

这个问题其实有一个更好的解决方案。

只需要使用普通的Button,并且使用drawableLeftgravity属性即可。

<Button
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:drawableLeft="@drawable/my_btn_icon"
  android:gravity="left|center_vertical" />

这种方法可以获得一个按钮,其在按钮的左侧显示图标,在图标右侧显示文本,并且文本垂直居中


3
如果您选择在按钮上设置背景颜色(这在这种情况下很可能),则该解决方案会出现问题。那么,点击或选择将没有图形响应。您可以编写一个选择器来处理此问题,但是这样做将无法获得手机的默认颜色。 - Vanja
11
只想补充一点,如果使用这种解决方案,Drawable padding 属性非常有用。 - Nikola Malešević
6
在XML中,有没有一种方法可以为可绘制的图标设置高度和宽度? - penguru
19
这是一个很棒的解决方案,也在Android开发者网站上得到了官方认可:http://developer.android.com/guide/topics/ui/controls/button.html - twaddington
5
如果按钮很大而文本长度可变,则看起来会很丑:图标最左边,文本在中间某个位置。 - user529543
显示剩余3条评论

211

您可以在 Button 上调用 setBackground() 方法来设置按钮的背景。

任何文本都将显示在背景上方。

如果您想在 XML 中实现类似的效果,可以使用 android:background 属性,它的工作方式与此相同。


51
如果你选择这个方案,你不应该仅仅使用简单的drawable作为背景。而是应该使用StateListDrawable(通常通过res/drawable/中的<selector> XML文件),这样你就可以为各种状态(正常、按下、聚焦、禁用等)定义不同的背景。 - CommonsWare
1
同意你的看法,可以查看这个问题和我的答案: https://dev59.com/5HI_5IYBdhLWcg3wFu7L - m_vitaly
2
太愚蠢了。我怎么会在文档中错过那个。感谢您的快速回答,以及关于<selector>的提示。这是我未来一定要实现的东西。 - znq
4
在ICS 4.0+版本上它不能正常工作,图片会被拉伸。我使用了一个带背景的TextView。 - meh

68

输入图像描述

     <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:background="@drawable/home_button"
            android:drawableLeft="@android:drawable/ic_menu_edit"
            android:drawablePadding="6dp"
            android:gravity="left|center"
            android:height="60dp"
            android:padding="6dp"
            android:text="AndroidDhina"
            android:textColor="#000"
            android:textStyle="bold" />

7
一个简单但错误的解决方案。仅适用于左对齐。 - CoolMind
2
@CoolMind,我只是在解释上面我附加的图片...如果你想要右对齐,请使用drawableRight。 - Dhina k
直到我看到这个答案,我才想到要这样做。这个方法非常有效! - sud007

64

只需使用LinearLayout,并假装它是一个Button - 设置backgroundclickable是关键:

<LinearLayout
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:drawable/btn_default"
    android:clickable="true"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="5dp"
        android:src="@drawable/image" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_margin="5dp"
        android:text="Do stuff" />
</LinearLayout>

1
如何添加点击效果? - frankish
3
最佳答案是这样,您可以完全掌控外观和感觉,而且不必把图标固定在边框上。 - Climbatize
请给您的视图添加 android:onClick 属性。 - Giora Guttsait
唯一真正的解决方案。真是麻烦! - Fattie

46
只需替换。
android:background="@drawable/icon"

使用

android:background="@android:color/transparent"
android:drawableTop="@drawable/[your background image here]"

这是个相当不错的技巧.. ;)


22

我采用了不同的方法来创建自定义按钮,并且它运行得非常好,所以我想分享给大家。

我使用样式来创建一个左侧带有图像、中右侧带有文本的自定义按钮。只需按照以下4个“简单步骤”:

I. 使用至少3个不同的PNG文件和 /YOUR_OWN_PATH/android-sdk-mac_x86/tools/./draw9patch 工具创建你的九宫格图形。在此之后,你应该会得到:

button_normal.9.png,button_focused.9.png 和 button_pressed.9.png

然后下载或创建一个 24x24 的 PNG 图标。

ic_your_icon.png

把所有文件都保存在 Android 项目的 drawable/ 文件夹下。

II. 在 drawable/ 文件夹下创建一个名为 button_selector.xml 的 XML 文件。状态应该如下:

<item android:state_pressed="true" android:drawable="@drawable/button_pressed" />
<item android:state_focused="true" android:drawable="@drawable/button_focused" />
<item android:drawable="@drawable/button_normal" />

III. 进入values/文件夹并打开或创建styles.xml文件,然后创建以下XML代码:

<style name="ButtonNormalText" parent="@android:style/Widget.Button">
    <item name="android:textColor" >@color/black</item>
    <item name="android:textSize" >12dip</item>
    <item name="android:textStyle" >bold</item>
    <item name="android:height" >44dip</item>
    <item name="android:background" >@drawable/button_selector</item>
    <item name="android:focusable" >true</item>
    <item name="android:clickable" >true</item>
</style>

<style name="ButtonNormalTextWithIcon" parent="ButtonNormalText">
    <item name="android:drawableLeft" >@drawable/ic_your_icon</item>
</style>

ButtonNormalTextWithIcon是一个“子样式”,因为它扩展了ButtonNormalText(“父样式”)。

请注意,通过在ButtonNormalTextWithIcon样式中更改drawableLeft到drawableRight、drawableTop或drawableBottom,您可以将图标放置在文本相对于其他位置。

IV. 转到存储UI的XML文件的layout/文件夹,并进入要应用样式并使其呈现如下所示的Button:

<Button android:id="@+id/buttonSubmit" 
android:text="@string/button_submit" 
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
style="@style/ButtonNormalTextWithIcon" ></Button>

而且... 奇迹发生了!你得到了一个左侧带有图片的按钮。

对我来说,这是更好的方法!因为用这种方式做,可以单独管理按钮文本的大小和所要显示的图标,并使用相同的背景可绘制对象为多个带有不同图标的按钮服务,遵循 Android UI Guidelines 使用样式。

您还可以为应用程序创建主题,并将“父样式”添加到其中,以便所有按钮看起来都相同,并在需要时仅应用带有图标的“子样式”。


干得好。我之前使用的是FrameLayout视图方法,里面包含了ImageView和TextView,但这种方法更好。 - pilcrowpipe
很棒的方法。Facebook SDK(版本3)采用相同的方法来处理登录按钮。 - Someone Somewhere

14

重要更新

不要使用普通的android:drawableLeft等与矢量图标一起使用,否则会在低版本API中崩溃。(我在现有应用中遇到过此问题)

关于矢量图标

如果您正在使用矢量图标,则必须:

  • 首先迁移至 AndroidX。如果没有,请参阅什么是Android X,以及如何进行迁移?
  • 此功能是在版本1.1.0-alpha01中发布的,所以appcompat版本应至少为1.1.0-alpha01。目前最新版本为1.1.0-alpha02,使用最新版本可获得更好的可靠性,请参阅发行说明-链接

    implementation 'androidx.appcompat:appcompat:1.1.0-alpha02'

  • 使用AppCompatTextView/AppCompatButton/AppCompatEditText

  • 使用app:drawableLeftCompatapp:drawableTopCompatapp:drawableRightCompatapp:drawableBottomCompatapp:drawableStartCompatapp:drawableEndCompat

针对常规的可绘制对象

如果您不需要矢量绘图,则可以:

  • 使用android:drawableLeftandroid:drawableRightandroid:drawableBottomandroid:drawableTop属性
  • 您可以使用普通的TextViewButton&EditTextAppCompat类。

您可以获得以下输出结果 -

output


我正在使用 xmlns:app="http://schemas.android.com/apk/res-auto" 命名空间,但没有看到那些 app compat 的东西。 - Dale
1
@Dale,你的命名空间是正确的,我已经更新了我的答案,请再次查看“对于矢量可绘制”这一点。 - Khemraj Sharma
1
@Khemraj,你是如何将单个视图(无论是TextView、Button还是其他什么)中的可绘制和文本居中对齐的,就像你附加的图片所显示的那样? - Ambar Jain

13
 <Button android:id="@+id/imeageTextBtn" 
        android:layout_width="240dip"
        android:layout_height="wrap_content"
        android:text="Side Icon With Text Button"
        android:textSize="20sp"
        android:drawableLeft="@drawable/left_side_icon"         
        />   

12

您可以使用drawableTop(还有drawableLeft等)来添加图片,并通过添加gravity属性 left|center_vertical将文本设置在图片下方。

<Button
            android:id="@+id/btn_video"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:background="@null"
            android:drawableTop="@drawable/videos"
            android:gravity="left|center_vertical"
            android:onClick="onClickFragment"
            android:text="Videos"
            android:textColor="@color/white" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接