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.