Android: поєднання тексту та зображення на кнопці чи кнопці зображення


540

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

Якщо я використовую, у ImageButtonмене навіть немає можливості додати текст. Якщо я використовую, Buttonя можу додати текст, але визначити лише зображення з android:drawableBottomподібними атрибутами XML, як визначено тут .

Однак ці атрибути поєднують текст і зображення лише в розмірах x і y, тобто я можу намалювати зображення навколо свого тексту, але не нижче / під моїм текстом (з віссю z, визначеною як виходить з дисплея).

Будь-які пропозиції, як це зробити? Однією з ідей було б або розширити, Buttonабо ImageButtonскасувати draw()метод-. Але, маючи сучасний рівень знань, я не знаю, як це зробити (2D-рендерінг). Можливо, хтось із більшим досвідом знає рішення або хоча б якісь покажчики для початку?


використовувати 9Patch, розумне рішення
Kaveh Garshasp

привіт @Charu ක ласка , перевірте, якщо ви можете stackoverflow.com/questions/42968587 / ...
Mohamed Рихана

Відповіді:


205

Ви можете зателефонувати setBackground()на a, Buttonщоб встановити фон кнопки.

Будь-який текст з’явиться над фоном.

Якщо ви шукаєте щось подібне в xml, є: android:backgroundатрибут, який працює так само.


49
Якщо ви йдете цим маршрутом, ви не хочете просто використовувати простий малюнок для фону. Використовуйте StateListDrawable (зазвичай через <selector> XML-файл у res / dravable /), щоб ви могли визначити фони для різних станів (звичайні, натиснуті, зосереджені, відключені тощо).
CommonsWare

Згоден з вами, подивіться на це питання і моя відповідь: stackoverflow.com/questions/1533038 / ...
m_vitaly

1
Як нерозумно. Як я міг це пропустити в документації. Дякуємо за швидку відповідь, а також підказку з <selector>. Це я точно хочу втілити в майбутньому.
znq

3
Це не працює правильно у версіях ICS 4.0+, зображення розтягується. Я використовував TextView з фоном.
meh

612

Користувачам, які просто хочуть розмістити атрибути Background, Icon-Image та Text в одномуButton з різних файлів: Встановити на Buttonфоні, атрибути dravableTop / 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
Просто замініть null на 0, якщо ви використовуєте ідентифікатори ресурсів для своїх ресурсів
Ran

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
Проблема виникає з цим рішенням, якщо ви вирішили мати колір фону на кнопці (що, ймовірно, у цьому випадку). Тоді не буде графічної відповіді на натискання чи вибір. Ви можете написати селектор для вирішення цього питання, але тоді ви не отримаєте кольори телефону за замовчуванням.
Vanja

9
Просто хотів додати, що властивість Dravable 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 Я пояснюю лише вищезазначене зображення, яке я додав .. якщо ви хочете правильно вирівняти, використовуйте
dravableRight

Я навіть не думав це робити, поки не прочитав цю відповідь. Це працює як шарм!
sud007

58

Просто використовуйте 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]"

izz досить гарна хитрість ..;)


21

Я застосував інший підхід від наведеного тут, і він працює дуже добре, тому хотів поділитися ним.

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

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

button_normal.9.png, button_focused.9.png та button_pression.9.png

Потім завантажте або створіть значок PNG розміром 24x24.

ic_your_icon.png

Збережіть все у папці, що витягується / в проекті Android.

II. Створіть у своєму проекті XML-файл під назвою button_selector.xml під папкою Dravable /. Штати повинні бути такими:

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

ІІІ. Перейдіть до значень / папки та відкрийте або створіть файл 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 ("батьківський стиль").

Зауважте, що змінивши DravableLeft у стилі ButtonNormalTextWithIcon, на dravableRight, dravableTop або dravableBottom, ви можете розмістити піктограму в іншому положенні щодо тексту.

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>

І ... вуаля! У вас є кнопка із зображенням зліва.

Для мене це кращий спосіб зробити це! тому що, роблячи це таким чином, ви можете керувати розміром тексту кнопки окремо від піктограми, яку ви хочете відобразити, і використовувати один і той же фон, який можна малювати для декількох кнопок з різними значками, дотримуючись Правил користувальницького інтерфейсу користуючись стилями.

Ви також можете створити тему для своєї програми та додати до неї "батьківський стиль", щоб усі кнопки виглядали однаково, а застосувати "дочірній стиль" із піктограмою лише там, де вам це потрібно.


Гарна робота. Я використовував підхід перегляду FrameLayout із зображенням ImageView та TextView всередині, але цей підхід приємніший.
pilcrowpipe

Дивовижний підхід. Фейсбук SDK (версія 3) застосовує той самий підхід для кнопки входу
Хтось десь

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, або кнопці чи щось інше), як відображається на зображенні, яке ви додаєте?
Ambar Jain

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.