Android: объединение текста и изображения с помощью кнопки или кнопки ImageButton


540

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

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

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

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


используйте 9Patch, умное решение
Kaveh Garshasp

Привет @Charu ක, пожалуйста, проверьте это, если вы можете stackoverflow.com/questions/42968587/…
Мохамед

Ответы:


205

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

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

Если вы ищете что-то похожее в XML, есть android:backgroundатрибут :, который работает так же.


49
Если вы идете по этому пути, вы не хотите просто использовать простой рисовать для фона. Используйте StateListDrawable (обычно через XML-файл <selector> в res / drawable /), чтобы вы могли определять фоны для различных состояний (нормальное, нажатое, фокусированное, отключенное и т. Д.).
CommonsWare

Согласен с вами, поищите этот вопрос и мой ответ: stackoverflow.com/questions/1533038/…
m_vitaly

1
Как глупо. Как я мог пропустить это в документации. Спасибо за быстрый ответ, а также подсказку с <селектором>. Это то, что я определенно хочу реализовать в будущем.
Znq

3
Это не работает правильно на версиях ICS 4.0+, изображение растягивается. Я использовал TextView с фоном.
Мех

612

Для пользователей, которые просто хотят поместить Background, Icon-Image и Text в один 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


70
Для этого программно используйте b.setCompoundDrawablesWithIntrinsicBound(null,R.drawable.home_icon_test,null,null)вместо android:drawableTopи b.setPadding(0,32,0,0)вместо android:paddingTop.
Алекс Жасмин

3
Использование макета в качестве кнопки на самом деле довольно гибкий подход.
sstn

2
Просто замените ноль на 0, если вы используете идентификаторы ресурсов для рисования
Раннее

1
Как я могу масштабировать фоновое изображение, чтобы оно соответствовало кнопке?
Олстон

@Stallman Существует решение для масштабирования на основе XML и кода: stackoverflow.com/questions/8223936/…
OneWorld

346

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

Просто нормальный 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" />

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


2
Проблема возникает с этим решением, если вы решили иметь цвет фона на кнопке (что, вероятно, в этом случае). Тогда не будет графического ответа на щелчок или выделение. Вы можете написать селектор, чтобы справиться с этим, но тогда вы не получите цвета телефона по умолчанию.
Ваня

9
Просто хотел добавить, что свойство Drawable padding очень полезно, если используется это решение.
Никола Малешевич

5
Есть ли способ установить высоту и ширину для нарисованного значка в XML?
Penguru

18
Это отличное решение, которое также официально одобрено на сайте разработчиков Android: developer.android.com/guide/topics/ui/controls/button.html
twaddington

3
если кнопка большая, а текст переменный длинный, то это выглядит ужасно: иконка слева и текст где-то посередине

67

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

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

4
Простое и неправильное решение. Только для выравнивания по левому краю.
CoolMind

2
@ CoolMind Я объясняю только для вышеупомянутого изображения, которое я прикрепил .. если вы хотите, чтобы выравнивание по правому
краю

Я даже не думал об этом, пока не прочитал этот ответ. Это работает как шарм!
sud007

59

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

<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
Как добавить эффект нажатия?
Франк

3
Лучший ответ: таким образом вы управляете 100% внешним видом и вам не нужно прикреплять значок к границе.
Climbatize

Франк, добавьте android:onClickк вашему мнению
Giora Guttsait

43

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

android:background="@drawable/icon"

с

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

изж довольно хороший трюк ..;)


21

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

Я использую стиль для создания пользовательской кнопки с изображением слева и текстом в центре справа. Просто следуйте 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, вы можете поместить значок в другое положение по отношению к тексту.

Внутривенно Перейдите к макету / папке, где у вас есть 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 UI, используя стили.

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


Хорошая работа. Я использовал подход представления FrameLayout с ImageView и TextView внутри, но этот подход лучше.
Pilcrowpipe

Потрясающий подход. Facebook SDK (версия 3) использует тот же подход к кнопке входа в систему
Someone Somewhere

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

11

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

11

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

Не используйте нормальные и 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'

  • Используйте AppCompatTextView/ AppCompatButton/AppCompatEditText

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

Для регулярного рисования

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

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

Вы можете добиться выхода, как показано ниже -

вывод


Я использую xmlns:app="http://schemas.android.com/apk/res-auto"пространство имен и не вижу этих приложений совместимых вещей.
Дейл

1
@ Дейл, ваше пространство имен правильное, я обновил свой ответ, еще раз посмотрите For vector drawableпункт.
Хемрай

@Khemraj Как вы центрируете рисованный текст и текст в одном представлении (либо TextView, либо Button или что-то еще), как показано на прикрепленном изображении?
Амбар Джайн

7

Возможно, мое решение подойдет многим пользователям, я надеюсь на это.

Я предлагаю сделать 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" />

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

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


Хотя мне еще предстоит протестировать ваш код, так как подход кажется правильным, но я не понимаю, почему в мобильном приложении возникает эффект зависания.
Мохаммед Ахтар Зубери

Я создал эффект наведения для своего приложения, и во время сборки приложения мне понадобился эффект наведения. Но это зависит от вас :) Вы можете удалить эффект наведения, если в этом нет необходимости.
Евгений Кононов

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

Оо ... Теперь я вижу ..: D Да, вы правы. Это невозможно. Этот эффект парения в основном для нажатия. Просто неверное имя для класса xml
Евгений Кононов


5

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

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

Я попробовал ваш код ... он работает, но главная проблема вашего кода, если у вас есть набор кнопок, с разными размерами текста в каждой кнопке. Ваш макет будет смещен. Таким образом, каждая позиция изображения кнопки будет в другом месте. Пока это должно быть прямо в центре. Это то, что происходит с кнопкой.
Евгений Кононов

0

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

  <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также добавил текст ..!


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

-4
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/temp"
        />

Это неправильный ответ, потому что просмотр изображений не поддерживает текст
Мухаммед Фасил
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.