Android: объединение текста и изображения в Button или ImageButton

Я пытаюсь использовать изображение (в качестве фона) на кнопке и динамически добавлять, в зависимости от того, что происходит во время выполнения, некоторый текст над / поверх изображения.

Если я использую ImageButton, у меня даже нет возможности добавлять текст. Если я использую Button, я могу добавить текст, но определять изображение только с android:drawableBottom и аналогичными атрибутами XML, как определено здесь.

Однако эти атрибуты объединяют текст и изображение только в размерах x и y, что означает, что я могу рисовать изображение вокруг моего текста, но не под / под моим текстом (с осью z, определяемой как выходящая из дисплея).

Есть предложения, как это сделать? Одна из идей - расширить Button или ImageButton и переопределить draw()-метод. Но с моим нынешним уровнем знаний я действительно не знаю, как это сделать (2D-рендеринг). Может быть, кто-то с большим опытом знает решение или хотя бы несколько указателей для начала?


person znq    schedule 07.10.2009    source источник
comment
используйте 9Patch, умное решение   -  person Hossein Kurd    schedule 25.07.2015
comment
привет @Charu ක проверьте, можете ли вы stackoverflow.com/questions/42968587/   -  person Mohamed Rihan    schedule 26.03.2017
comment
Лучше всего использовать CardView ›› Просто поместите LinearLayout внутрь CardView, установите image в качестве фона для LinearLayout и используйте textView внутри в этом LinearLayout. Для получения дополнительных сведений ознакомьтесь с этимstackoverflow.com/a/65172123/12750160. Спасибо, удачного кодирования :)   -  person AG-Developer    schedule 06.12.2020


Ответы (18)


Вы можете вызвать setBackground() на Button, чтобы установить фон кнопки.

Любой текст появится над фоном.

Если вы ищете что-то подобное в xml, есть: android:background атрибут, который работает таким же образом.

person m_vitaly    schedule 07.10.2009
comment
Если вы пойдете по этому пути, вы не захотите просто использовать простой рисунок для фона. Используйте StateListDrawable (обычно через XML-файл ‹selector› в res / drawable /), чтобы вы могли определять фон для различных состояний (нормальный, нажатый, сфокусированный, отключенный и т. Д.). - person CommonsWare; 07.10.2009
comment
Согласитесь с вами, ищите этот вопрос и мой ответ: stackoverflow.com/questions/1533038/ - person m_vitaly; 07.10.2009
comment
Как глупо. Как я мог пропустить это в документации. Спасибо за быстрый ответ, а также за подсказку с помощью ‹selector›. Это то, что я определенно хочу реализовать в будущем. - person znq; 08.10.2009
comment
Правильно на версиях ICS 4.0+ не работает, изображение растягивается. Я использовал TextView с фоном. - person meh; 25.09.2012

Для пользователей, которые просто хотят поместить фон, изображение значка и текст в один Button из разных файлов: установите Button фон, 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

person OneWorld    schedule 17.09.2010
comment
Чтобы сделать это программно, используйте b.setCompoundDrawablesWithIntrinsicBound(null,R.drawable.home_icon_test,null,null) вместо android:drawableTop и b.setPadding(0,32,0,0) вместо android:paddingTop. - person Alex Jasmin; 30.11.2010
comment
Использование макета в качестве кнопки на самом деле является довольно гибким подходом. - person sstn; 27.05.2011
comment
Просто замените null на 0, если вы используете идентификаторы ресурсов для своих чертежей. - person Ran; 28.05.2013
comment
Как я могу масштабировать фоновое изображение, чтобы оно соответствовало кнопке? - person Alston; 25.04.2014
comment
@Stallman Существует решение для масштабирования на основе XML и кода: stackoverflow.com/questions/8223936/ - person OneWorld; 12.02.2015
comment
есть ли способ XML изменить изображение при нажатии? - person Buddy; 28.08.2015
comment
@EnesBattal да, назначьте его StateListDrawable developer.android.com / guide / themes / resources / - person OneWorld; 28.08.2015
comment
@OneWorld, попробовал, но не вышло. Он не показывает изображений. Я задал этот вопрос в SO, если у вас есть ответ, вы можете опубликовать? stackoverflow.com/questions/32264654/ - person Buddy; 28.08.2015
comment
@AlexandreJasmin Вашему комментарию пять лет, и он получил 61 благодарность, но у меня с ним проблемы. Для начала следует установить имя методаCompoundDrawablesWithIntrinsicBounds () с s в конце, не так ли? И после того, как я внесу это изменение, он все еще не работает для меня, если я не изменю три нулевых аргумента на 0, поэтому он вызывает версию метода, которая принимает четыре аргумента int. - person RenniePet; 18.01.2016

Есть гораздо лучшее решение этой проблемы.

Просто возьмите обычный Button и используйте атрибуты drawableLeft и gravity.

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

Таким образом вы получите кнопку, которая отображает значок в левой части кнопки и текст в правой части значка по центру по вертикали.

person schlingel    schedule 14.05.2011
comment
Проблема возникает с этим решением, если вы выбрали цвет фона на кнопке (что, вероятно, в данном случае). Тогда не будет графического отклика на щелчок или выбор. Вы можете написать селектор, чтобы справиться с этим, но тогда вы не получите цвета телефона по умолчанию. - person Vanja; 14.07.2011
comment
Просто хотел добавить, что свойство Drawable padding очень полезно, если используется это решение. - person Nikola Malešević; 16.02.2012
comment
Есть ли способ установить высоту и ширину для значка с возможностью рисования в xml? - person penguru; 13.04.2012
comment
Это отличное решение, которое также официально одобрено на сайте разработчиков Android: developer.android.com/guide/topics/ui/controls/button.html - person twaddington; 19.07.2012
comment
если кнопка большая, а текст переменный длинный, это выглядит некрасиво: значок не выше слева, а текст где-то посередине - person ; 25.09.2013
comment
@ user529543 можно задать выравнивание текста. это решает эту проблему - person schlingel; 18.03.2014
comment
Изображение рисуется слева, независимо от силы тяжести и заполнения. - person CoolMind; 15.08.2016
comment
@CoolMind - если вы используете drawableRight, он находится справа. Гравитация предназначена для выравнивания текста. - person schlingel; 15.08.2016

введите описание изображения здесь

     <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" />
person Dhina k    schedule 10.09.2015
comment
Простое и неправильное решение. Только для выравнивания по левому краю. - person CoolMind; 15.08.2016
comment
@ CoolMind Я объясняю только изображение выше, которое я прикрепил .. если вы хотите, чтобы выровнять по правому краю, используйте drawableRight - person Dhina k; 16.08.2016
comment
Я даже не думал об этом, пока не прочитал этот ответ. Это работает как шарм! - person sud007; 20.02.2020

Просто используйте LinearLayout и представьте, что это Button - параметр background и clickable является ключом:

<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>
person Kieran    schedule 04.01.2012
comment
Как добавить эффект нажатия? - person frankish; 26.02.2013
comment
Лучший ответ: таким образом вы управляете 100% внешнего вида и вам не нужно прикреплять значок к границе. - person Climbatize; 16.12.2013
comment
откровенно говоря, добавьте android:onClick к своему обзору - person Giora Guttsait; 04.03.2016
comment
Единственное реальное решение. Какая неприятность! - person Fattie; 04.03.2021

просто замените

android:background="@drawable/icon"

с участием

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

izz неплохой трюк ..;)

person CMA    schedule 24.05.2011

Я использовал подход, отличный от изложенного здесь, и он работает очень хорошо, поэтому я хотел им поделиться.

Я использую стиль для создания настраиваемой кнопки с изображением слева и текстом в правом центре. Просто выполните 4 "простых шага" ниже:

I. Создайте свои 9 патчей, используя как минимум 3 разных файла PNG и имеющийся у вас инструмент: /YOUR_OWN_PATH/android-sdk-mac_x86/tools/./draw9patch. После этого у вас должно быть:

button_normal.9.png, button_focused.9.png и button_pressed.9.png

Затем загрузите или создайте значок PNG 24x24.

ic_your_icon.png

Сохраните все в папке drawable / вашего проекта Android.

II. Создайте XML-файл с именем button_selector.xml в своем проекте в папке drawable /. Состояния должны быть такими:

<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 («родительский стиль»).

Обратите внимание, что изменив drawableLeft в стиле ButtonNormalTextWithIcon на drawableRight, drawableTop или drawableBottom, вы можете разместить значок в другом месте относительно текста.

IV. Перейдите в папку / макет, где у вас есть XML для пользовательского интерфейса, и перейдите к кнопке, к которой вы хотите применить стиль, и сделать его таким:

<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 с использованием стилей.

Вы также можете создать тему для своего приложения и добавить к нему «родительский стиль», чтобы все кнопки выглядели одинаково, и применить «дочерний стиль» со значком только там, где он вам нужен.

person Oscar Salguero    schedule 15.09.2011
comment
Хорошая работа. Я использовал подход просмотра FrameLayout с ImageView и TextView внутри, но этот подход лучше. - person pilcrowpipe; 27.01.2013
comment
Отличный подход. Facebook SDK (версия 3) использует тот же подход для кнопки входа в систему. - person Someone Somewhere; 20.06.2013

Важное обновление

Не используйте обычные android:drawableLeft и т. Д. С векторными рисунками, иначе это приведет к сбою в более ранних версиях API. (Я столкнулся с этим в живом приложении)

Для векторной графики

Если вы используете векторную графику, вы должны

  • Вы перешли на AndroidX? в противном случае вы должны сначала перейти на AndroidX. Это очень просто, см. что такое androidx и как перейти на него?
  • Он был выпущен в версии 1.1.0-alpha01, поэтому версия appcompat должна быть не менее 1.1.0-alpha01. Текущая последняя версия - 1.1.0-alpha02, для большей надежности используйте последние версии, см. Примечания к выпуску - ссылка.

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

  • Используйте _6 _ / _ 7 _ / _ 8_

  • Используйте app:drawableLeftCompat, app:drawableTopCompat, app:drawableRightCompat, app:drawableBottomCompat, app:drawableStartCompat и app:drawableEndCompat

Для обычного вытягивания

Если вам не нужна векторная графика, вы можете

  • используйте android:drawableLeft, android:drawableRight, android:drawableBottom, android:drawableTop
  • Вы можете использовать обычные классы TextView, Button & EditText или AppCompat.

Вы можете получить Выход, как показано ниже -

output

person Khemraj Sharma    schedule 04.02.2019
comment
Я использую пространство имен xmlns:app="http://schemas.android.com/apk/res-auto" и не вижу, чтобы эти приложения были совместимы. - person Dale; 09.03.2019
comment
@Dale ваше пространство имен правильное, я обновил свой ответ, снова см. Пункт For vector drawable. - person Khemraj Sharma; 09.03.2019
comment
@Khemraj Как вы центрируете как рисование, так и текст в одном представлении (либо TextView, либо Button, либо что-то еще), как показано на прикрепленном вами изображении? - person Ambar Jain; 27.03.2019

Вы можете использовать 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" />
person Kalai.G    schedule 22.10.2013

Наверное, мое решение подойдет многим, надеюсь.

Я предлагаю создать TextView в вашем стиле. Он отлично работает у меня и имеет все функции, например кнопку.

Прежде всего, давайте сделаем стиль кнопки, который вы можете использовать везде ... Я создаю button_with_hover.xml

    <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" >
        <shape android:shape="rectangle"  >
            <corners android:radius="3dip" />
            <stroke android:width="1dip" android:color="#8dbab3" />
            <gradient android:angle="-90" android:startColor="#48608F" android:endColor="#48608F"  />
        </shape>

        <!--#284682;-->
        <!--border-color: #223b6f;-->
    </item>
    <item android:state_focused="true">
        <shape android:shape="rectangle"  >
            <corners android:radius="3dip" />
            <stroke android:width="1dip" android:color="#284682" />
            <solid android:color="#284682"/>
        </shape>
    </item>
    <item >
        <shape android:shape="rectangle"  >
            <corners android:radius="3dip" />
            <stroke android:width="1dip" android:color="@color/ControlColors" />
            <gradient android:angle="-90" android:startColor="@color/ControlColors" android:endColor="@color/ControlColors" />
        </shape>
    </item>

</selector>

Во-вторых, давайте создадим кнопку текстового просмотра.

    <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="20dip"
    android:layout_gravity="right|bottom"
    android:gravity="center"
    android:padding="12dip"
    android:background="@drawable/button_with_hover"
    android:clickable="true"
    android:drawableLeft="@android:drawable/btn_star_big_off"
    android:textColor="#ffffffff"
    android:text="Golden Gate" />

И это результат. Затем стилизуйте свою пользовательскую кнопку с любыми цветами или любыми другими свойствами и полями. Удачи

введите описание изображения здесь

person Jevgenij Kononov    schedule 22.02.2017
comment
Хотя мне еще предстоит протестировать ваш код, поскольку подход кажется правильным, но я не понимаю причину появления эффекта зависания в мобильном приложении. - person Mohammed Akhtar Zuberi; 30.01.2018
comment
Я создал эффект наведения для своего приложения, и во время сборки этого приложения мне понадобился эффект наведения. Но решать только вам :) Вы можете удалить эффект наведения, если в этом нет необходимости. - person Jevgenij Kononov; 30.01.2018
comment
Я проголосовал за ваш ответ, так как это очень хороший подход. Моя единственная точка зрения - мобильный интерфейс, как вы можете навести курсор мыши? - person Mohammed Akhtar Zuberi; 30.01.2018
comment
Оо ... Теперь понятно ..: D Ага, ты прав. Это невозможно. Этот эффект наведения в основном предназначен для эффекта нажатия. Просто неправильное имя для класса xml - person Jevgenij Kononov; 30.01.2018

<Button
     android:id="@+id/groups_button_bg"
     android:layout_height="wrap_content"
     android:layout_width="wrap_content"
     android:text="Groups"
     android:drawableTop="@drawable/[image]" />


android:drawableLeft
android:drawableRight
android:drawableBottom
android:drawableTop

http://www.mokasocial.com/2010/04/create-a-button-with-an-image-and-text-android/

person Sam    schedule 14.03.2013

Этот код отлично работает у меня

<LinearLayout
    android:id="@+id/choosePhotosView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="center"
    android:clickable="true"
    android:background="@drawable/transparent_button_bg_rev_selector">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/choose_photo"/>

     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:text="@string/choose_photos_tv"/>

</LinearLayout>
person eyal    schedule 23.03.2015
comment
Я пробовал ваш код ... он работает, но основная проблема вашего кода, если у вас есть набор кнопок с разными размерами текста на каждой кнопке. Ваш макет будет изменен. Таким образом, каждое изображение кнопки будет расположено в другом месте. При этом он должен быть прямо по центру. Вот что происходит с кнопкой. - person Jevgenij Kononov; 24.02.2017

MaterialButton поддерживает установку значка и выравнивание его по тексту:

<com.google.android.material.button.MaterialButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="My button"
        app:icon="@drawable/your_icon"
        app:iconGravity="textStart"
        />

app:iconGravity также может быть start / end, если вы хотите выровнять значок по кнопке вместо текста внутри нее.

person Cristan    schedule 03.07.2020

<Button android:id="@+id/myButton" 
    android:layout_width="150dp"
    android:layout_height="wrap_content"
    android:text="Image Button"
    android:drawableTop="@drawable/myimage"         
    />  

Или программно:

Drawable drawable = getResources.getDrawable(R.drawable.myimage);
drawable.setBounds(0, 0, 60, 60);
myButton.setCompoundDrawables(null, drawable, null, null);//to the Top of the Button
person Kerim FIRAT    schedule 14.05.2020

Вы можете использовать это:

  <Button
                    android:id="@+id/reset_all"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginRight="5dp"
                    android:layout_weight="1"
                    android:background="@drawable/btn_med"
                    android:text="Reset all"
                    android:textColor="#ffffff" />

                <Button
                    android:id="@+id/undo"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="5dp"
                    android:layout_weight="1"
                    android:background="@drawable/btn_med"
                    android:text="Undo"
                    android:textColor="#ffffff" />

в этом я поместил изображение как background, а также добавил текст ..!

person jigar    schedule 28.06.2013

Сделайте фальшивую пуговицу.

Это действительно единственный способ

  <FrameLayout
        android:id="@+id/fake_button"

        android:layout_width=" .. "
        android:layout_height=" .. "

        android:background="@android:color/transparent"

        android:clickable="true"
        android:onClick="tappedNext">

        <ImageView
            android:id="@+id/fake_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"

            android:src="@drawable/your_amazing_drawable" />

        <TextView
            android:id="@+id/fake_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"

            android:text="Next"
            android:fontFamily="@font/ .. "
            android:textColor="@color/ .. "
            android:textSize=" .. " />
    </FrameLayout>
person Fattie    schedule 03.03.2021

Чтобы объединить Button и drawableTop и по-прежнему получать реакцию на нажатие, вы можете использовать стиль кнопки @style/Widget.AppCompat.Button.Borderless, чтобы сделать ее прозрачной.

введите описание изображения здесь

<Button
    android:id="@+id/settings"
    style="@style/Widget.AppCompat.Button.Borderless"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableTop="@drawable/ic_baseline_settings_24"
    android:drawableTint="?attr/colorPrimary"
    android:text="@string/settings"
    android:textColor="?attr/colorPrimary" />
person Emmanuel Osimosu    schedule 17.05.2021

person    schedule
comment
Это неправильный ответ, потому что представление изображения не поддерживает текст - person Muhammed Fasil; 30.11.2018