Як центрувати піктограму та текст за допомогою кнопки Android із шириною, встановленою на "заповнення батьків"


118

Я хочу мати кнопку Android з піктограмою + текстом, зосередженим всередині неї. Я використовую атрибут dravableLeft для встановлення зображення, це добре працює, якщо кнопка має ширину, "wrap_content"але мені потрібно розтягнутись до максимальної ширини, тому я використовую ширину "fill_parent". Це переміщує мій значок прямо ліворуч від кнопки, і я хочу, щоб іконка, і текст були по центру всередині кнопки.

Я спробував налаштувати прокладку, але це дозволяє лише дати фіксовану величину, тому це не те, що мені потрібно. Мені потрібно вирівняти піктограму + текст у центрі.

<Button 
    android:id="@+id/startTelemoteButton" 
    android:text="@string/start_telemote"
    android:drawableLeft="@drawable/start"
    android:paddingLeft="20dip"
    android:paddingRight="20dip"            
    android:width="fill_parent"
    android:heigh="wrap_content" />

Будь-які пропозиції щодо того, як я міг цього досягти?


Можливо, для цього немає простого рішення? Чи потрібно спробувати із зображенням кнопки 9patch із значком там?
jloriente

Це може бути рішенням. Текст кнопки буде локалізованим чи статичним?
Октавіан А. Дам’ян

Це локалізовано. Немає іншого рішення для цього? Мені вдалося це зробити з 9 патчем, але виникли проблеми при зміні мови.
jloriente

А як щодо використання кнопки з витягнутим TOP і додавання до неї трохи накладок?
Франческо

поганий дизайн рамки
Мухаммед Бабар

Відповіді:


75

android: dravableLeft завжди зберігає android: paddingLeft як відстань від лівої межі. Якщо кнопка не встановлена ​​на android: width = "wrap_content", вона завжди буде звисати зліва!

За допомогою Android 4.0 (рівень API 14) ви можете використовувати атрибут android: dravableStart, щоб розмістити текст, що виводиться на початку тексту. Єдине сумісне відстале рішення, яке я придумав, - це використання ImageSpan для створення тексту + зображення, що розгортається:

Button button = (Button) findViewById(R.id.button);
Spannable buttonLabel = new SpannableString(" Button Text");
buttonLabel.setSpan(new ImageSpan(getApplicationContext(), R.drawable.icon,      
    ImageSpan.ALIGN_BOTTOM), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
button.setText(buttonLabel);

У моєму випадку мені потрібно було також відрегулювати атрибут Android: гравітація кнопки, щоб вона виглядала по центру:

<Button
  android:id="@+id/button"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:minHeight="32dp"
  android:minWidth="150dp"
  android:gravity="center_horizontal|top" />

Приємно. Останній рядок повинен бутиbutton.setText(buttonLabel)
AlexD

1
У Unicode є великий набір символьних значків, сумісних із рядками в Android. Якщо ви можете знайти прийнятне, це просте рішення, і він має додатковий бонус, який він буде масштабуватись з розміром тексту. Наприклад, він має конверт для піктограми електронної пошти та пару різних телефонів для кнопки виклику.
GLee

1
Мене бентежить, як це працювало для когось, для мене він малює 2 піктограми ... один шлях ліворуч і один прямо в центрі, який відображається вгорі тексту.
Джастін

11
dravableStart не працюватиме. Дивіться цю тему: stackoverflow.com/questions/15350990/… Також здається, що коли ви встановлюєте текст за допомогою перемикаючого стилю, стиль ігнорується.
Дапп

11
dravableStart не працює, і він був доданий в рівні API 17 для підтримки rtl
Silvia H

35

Я знаю, що спізнююсь відповісти на це питання, але це допомогло мені:

<FrameLayout
            android:layout_width="match_parent"
            android:layout_height="35dp"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="10dp"
            android:background="@color/fb" >

            <Button
                android:id="@+id/fbLogin"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:background="@null"
                android:drawableLeft="@drawable/ic_facebook"
                android:gravity="center"
                android:minHeight="0dp"
                android:minWidth="0dp"
                android:text="FACEBOOK"
                android:textColor="@android:color/white" />
        </FrameLayout>

Тут я знайшов таке рішення: Android UI бореться: створює кнопку з центрованим текстом та піктограмою

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


6
Проблема в цьому полягає в тому, що кнопка - це не ширина макета кадру.
Клайв Джеффріс

29

Я використовував LinearLayout замість кнопки . OnClickListener , що мені потрібно використовувати добре працює і для LinearLayout.

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

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="15dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:src="@drawable/icon" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Text" />

</LinearLayout>

29

Усі попередні відповіді здаються застарілими

Ви можете використовувати MaterialButtonтепер, що дозволяє встановити силу піктограми.

 <com.google.android.material.button.MaterialButton
        android:id="@+id/btnDownloadPdf"
        android:layout_width="0dp"
        android:layout_height="56dp"
        android:layout_margin="16dp"
        android:gravity="center"
        android:textAllCaps="true"
        app:backgroundTint="#fc0"
        app:icon="@drawable/ic_pdf"
        app:iconGravity="textStart"
        app:iconPadding="10dp"
        app:iconTint="#f00"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:text="Download Pdf" />

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

Для використання матеріальних компонентів вам, очевидно, потрібно:

Додайте залежність implementation 'com.google.android.material:material:1.3.0-alpha01' (використовуйте останню версію)

Зробіть тему розширеною темою Матеріальні компоненти

<style name="AppTheme" parent="Theme.MaterialComponents.Light">
...
</style>

Якщо ви не можете цього зробити, розгорніть його з теми Матеріал мосту

<style name="AppTheme" parent="Theme.MaterialComponents.Light.Bridge">
...
</style>

Дякую! Ти врятував мій день!
Добре

9

Я налаштовую його, додаючи накладки зліва і справа таким чином:

<Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/btn_facebookact_like"
            android:text="@string/btn_facebookact_like"
            android:textColor="@color/black"
            android:textAllCaps="false"
            android:background="@color/white"
            android:drawableStart="@drawable/like"
            android:drawableLeft="@drawable/like"
            android:gravity="center"
            android:layout_gravity="center"
            android:paddingLeft="40dp"
            android:paddingRight="40dp"
            />

PaddingLeft та paddingRight допомогли мені в центрі. запрошення на просте рішення.
Аррі

2
Як ви керуєте тим, що ваша ширина динамічна? Якщо ви обертаєте екран, усі ваші значки не будуть по центру, чи не так? Я стикаюся з цим питанням фактично
Джек

це найкраща відповідь!
Dody Rachmat Wicaksono

8

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

   <LinearLayout
        android:id="@+id/linearButton"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/selector_button_translucent_ab_color"
        android:clickable="true"
        android:descendantFocusability="blocksDescendants"
        android:gravity="center"
        android:orientation="horizontal" >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher" />

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

Тоді просто зателефонуйте OnClickListenerна LinearLayout.

Сподіваюся, це допомагає комусь, оскільки це здається дуже поширеною проблемою. :)


1
Це хороша ідея, але погане рішення. Те ж саме можна досягти лише одним TextView, використовуючи атрибут dravableLeft. Це дає змогу переглянути ліворуч від тексту, що малюється.
muetzenflo

@muetzenflo так, це правильно. але коли ви зрівняєте textView з батьківською шириною, ваш малюнок переміститься в крайній лівий бік, навіть якщо ви центрируєте текст. будь ласка, дайте мені знати, якщо я помиляюся. і питання лише про це.
Анкіт Поплі

Ах вибачте ... Я прийшов сюди саме за цю проблему і втратив фокус після спробу занадто багато речей :) Здогадайтесь, я не бачив лісу для дерев. Моя провина!
muetzenflo

7

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

public class DrawableAlignedButton extends Button {

    public DrawableAlignedButton(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public DrawableAlignedButton(Context context) {
    super(context);
}

public DrawableAlignedButton(Context context, AttributeSet attrs, int style) {
    super(context, attrs, style);
}

private Drawable mLeftDrawable;

@Override
    //Overriden to work only with a left drawable.
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left,
        Drawable top, Drawable right, Drawable bottom) {
    if(left == null) return;
    left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight());
    mLeftDrawable = left;
}

@Override
protected void onDraw(Canvas canvas) {
    //transform the canvas so we can draw both image and text at center.
    canvas.save();
    canvas.translate(2+mLeftDrawable.getIntrinsicWidth()/2, 0);
    super.onDraw(canvas);
    canvas.restore();
    canvas.save();
    int widthOfText = (int)getPaint().measureText(getText().toString());
    int left = (getWidth()+widthOfText)/2 - mLeftDrawable.getIntrinsicWidth() - 2;
    canvas.translate(left, (getHeight()-mLeftDrawable.getIntrinsicHeight())/2);
    mLeftDrawable.draw(canvas);
    canvas.restore();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int height = getMeasuredHeight();
    height = Math.max(height, mLeftDrawable.getIntrinsicHeight() + getPaddingTop() + getPaddingBottom());
    setMeasuredDimension(getMeasuredWidth(), height);
}
}

Використання

<com.mypackage.DrawableAlignedButton
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:drawableLeft="@drawable/my_drawable"
        android:gravity="center"
        android:padding="7dp"
        android:text="My Text" />

Ви можете включити у свою відповідь код, який повинен бути кращим способом (якщо він не надто довгий), оскільки посилання можуть загинути з часом
Лукаш Кнут

2
Не дуже точний, але я вважаю
Олексій Семенюк

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

5

Це моє рішення я написав 3 роки тому. Кнопка має текст та ліву піктограму і знаходиться у кадрі, який є фактичною кнопкою тут, і її можна розтягнути fill_parent. Я не можу перевірити його знову, але він працював тоді. Напевно, Кнопку не потрібно використовувати і її можна замінити TextView, але я не перевіряю її зараз, і вона не надто змінює функціональність.

<FrameLayout
    android:id="@+id/login_button_login"
    android:background="@drawable/apptheme_btn_default_holo_dark"
    android:layout_width="fill_parent"
    android:layout_gravity="center"
    android:layout_height="40dp">
    <Button
        android:clickable="false"
        android:drawablePadding="15dp"
        android:layout_gravity="center"
        style="@style/WhiteText.Small.Bold"
        android:drawableLeft="@drawable/lock"
        android:background="@color/transparent"
        android:text="LOGIN" />
</FrameLayout>

1
Тепер я бачу, що я не був на самоті з цим рішенням :)
Renetik

4

Я знаю, що це питання трохи старше, але, можливо, ви все ще відкриті для підказки або обходу:

Створіть відносний макет "wrap_content" із зображенням кнопки у якості фону або самої кнопки як першого елемента макета. Отримайте LinearLayout та встановіть його на "layout_centerInParent" та "wrap_content". Потім встановіть графічний малюнок як перегляд зображення. Нарешті встановіть TextView разом із текстом (мовою).

так що у вас є така структура:

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

або так:

RelativeLayout with "android-specific" button image as background
  LinearLayout
    ImageView
    TextView

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


Такий підхід може добре працювати. У моєму випадку мені потрібно було лише відносний макет, що містить TextView. У RelativeLayout з'явився фон, TextView отримує значок DravableLeft. Потім у коді: прикріпіть onClickListener до RelativeLayout та знайдітьViewById для TextView окремо, якщо потрібно
Stan Kurdziel

Перша запропонована структура дає виняток "Кнопку не можна передавати в ViewGroup".
Youngjae

4

Мій спосіб її вирішення стосувався оточення кнопки легкими <View ../>елементами, що динамічно змінюють розмір. Нижче наведено кілька прикладів того, що можна досягти за допомогою цього:

Демонстрація від Dev-iL

Зауважимо, що область натискання кнопок у прикладі 3 така сама, як у 2 (тобто з пробілами), що відрізняється від прикладу 4, коли між ними немає проміжків, що не можна "натискати".

Код:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 1: Button with a background color:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:layout_weight="0.3"/>
        <!-- Play around with the above 3 values to modify the clickable 
             area and image alignment with respect to text -->
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 2: Button group + transparent layout + spacers:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 3: Button group + colored layout:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 4 (reference): Button group + no spacers:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray">
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>   
    </LinearLayout>
</LinearLayout>


2

Ви можете створити спеціальний віджет:

Клас Java IButton:

public class IButton extends RelativeLayout {

private RelativeLayout layout;
private ImageView image;
private TextView text;

public IButton(Context context) {
    this(context, null);
}

public IButton(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public IButton(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.ibutton, this, true);

    layout = (RelativeLayout) view.findViewById(R.id.btn_layout);

    image = (ImageView) view.findViewById(R.id.btn_icon);
    text = (TextView) view.findViewById(R.id.btn_text);

    if (attrs != null) {
        TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.IButtonStyle);

        Drawable drawable = attributes.getDrawable(R.styleable.IButtonStyle_button_icon);
        if(drawable != null) {
            image.setImageDrawable(drawable);
        }

        String str = attributes.getString(R.styleable.IButtonStyle_button_text);
        text.setText(str);

        attributes.recycle();
    }

}

@Override
public void setOnClickListener(final OnClickListener l) {
    super.setOnClickListener(l);
    layout.setOnClickListener(l);
}

public void setDrawable(int resId) {
    image.setImageResource(resId);
}

}

Макет ibutton.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/btn_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" >

<ImageView
    android:id="@+id/btn_icon"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_marginRight="2dp"
    android:layout_toLeftOf="@+id/btn_text"
    android:duplicateParentState="true" />

<TextView
    android:id="@+id/btn_text"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:duplicateParentState="true"
    android:gravity="center_vertical"
    android:textColor="#000000" />
</RelativeLayout>

Щоб скористатися цим користувальницьким віджетом:

<com.test.android.widgets.IButton
     android:id="@+id/new"
     android:layout_width="fill_parent"         
     android:layout_height="@dimen/button_height"
     ibutton:button_text="@string/btn_new"
     ibutton:button_icon="@drawable/ic_action_new" />

Ви повинні надати простір імен для спеціальних атрибутів xmlns: ibutton = "http://schemas.android.com/apk/res/com.test.android.xxx", де com.test.android.xxx - кореневий пакет додаток.

Просто поставте його нижче xmlns: android = "http://schemas.android.com/apk/res/android".

Останнє, що вам знадобиться - це власні атрибути в attrs.xml.

У attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="IButtonStyle">
        <attr name="button_text" />
        <attr name="button_icon" format="integer" />
    </declare-styleable>

    <attr name="button_text" />

</resources>

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

Насолоджуйтесь!


2

Мав подібну проблему, але хотів мати центр для малювання без тексту та без загортання макетів. Рішенням було створити користувацьку кнопку та додати ще одну схему для малювання на додаток до лівого, правого, верхнього, нижнього. Можна легко змінювати розміщувані місця, що розміщуються, і розміщувати їх у потрібному положенні щодо тексту.

CenterDravableButton.java

public class CenterDrawableButton extends Button {
    private Drawable mDrawableCenter;

    public CenterDrawableButton(Context context) {
        super(context);
        init(context, null);
    }

    public CenterDrawableButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }


    private void init(Context context, AttributeSet attrs){
        //if (isInEditMode()) return;
        if(attrs!=null){
            TypedArray a = context.getTheme().obtainStyledAttributes(
                    attrs, R.styleable.CenterDrawableButton, 0, 0);

            try {
                setCenterDrawable(a.getDrawable(R.styleable.CenterDrawableButton_drawableCenter));

            } finally {
                a.recycle();
            }

        }
    }

    public void setCenterDrawable(int center) {
        if(center==0){
            setCenterDrawable(null);
        }else
        setCenterDrawable(getContext().getResources().getDrawable(center));
    }
    public void setCenterDrawable(@Nullable Drawable center) {
        int[] state;
        state = getDrawableState();
        if (center != null) {
            center.setState(state);
            center.setBounds(0, 0, center.getIntrinsicWidth(), center.getIntrinsicHeight());
            center.setCallback(this);
        }
        mDrawableCenter = center;
        invalidate();
        requestLayout();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(mDrawableCenter!=null) {
            setMeasuredDimension(Math.max(getMeasuredWidth(), mDrawableCenter.getIntrinsicWidth()),
                    Math.max(getMeasuredHeight(), mDrawableCenter.getIntrinsicHeight()));
        }
    }
    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if (mDrawableCenter != null) {
            int[] state = getDrawableState();
            mDrawableCenter.setState(state);
            mDrawableCenter.setBounds(0, 0, mDrawableCenter.getIntrinsicWidth(),
                    mDrawableCenter.getIntrinsicHeight());
        }
        invalidate();
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);

        if (mDrawableCenter != null) {
            Rect rect = mDrawableCenter.getBounds();
            canvas.save();
            canvas.translate(getWidth() / 2 - rect.right / 2, getHeight() / 2 - rect.bottom / 2);
            mDrawableCenter.draw(canvas);
            canvas.restore();
        }
    }
}

attrs.xml

<resources>
    <attr name="drawableCenter" format="reference"/>
    <declare-styleable name="CenterDrawableButton">
        <attr name="drawableCenter"/>
    </declare-styleable>
</resources>

використання

<com.virtoos.android.view.custom.CenterDrawableButton
            android:id="@id/centerDrawableButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:drawableCenter="@android:drawable/ic_menu_info_details"/>

Дякую! Ось що я шукав.
MistaGreen

допоможіть мені, будь ласка, у цьому питанні, stackoverflow.com/questions/35912539/… , з вашою відповіддю я дуже близький до цього, але з'являються дві
промотки

Це рішення розміщує графічний текст у центрі кнопки, трохи більше по центру тексту.
CoolMind

1
<style name="captionOnly">
    <item name="android:background">@null</item>
    <item name="android:clickable">false</item>
    <item name="android:focusable">false</item>
    <item name="android:minHeight">0dp</item>
    <item name="android:minWidth">0dp</item>
</style>

<FrameLayout
   style="?android:attr/buttonStyle"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" >

    <Button
       style="@style/captionOnly"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center"
       android:drawableLeft="@android:drawable/ic_delete"
       android:gravity="center"
       android:text="Button Challenge" />
</FrameLayout>

Помістіть FrameLayout у LinearLayout та встановіть орієнтацію на горизонтальну.


1

Ви можете поставити кнопку над LinearLayout

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/activity_login_fb_height"
        android:background="@mipmap/bg_btn_fb">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/lblLoginFb"
                android:textColor="@color/white"
                android:drawableLeft="@mipmap/icon_fb"
                android:textSize="@dimen/activity_login_fb_textSize"
                android:text="Login with Facebook"
                android:gravity="center" />
        </LinearLayout>
        <Button
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/btnLoginFb"
            android:background="@color/transparent"
            />
    </RelativeLayout>

0

Що станеться, якщо спробувати Android: gravity = "center_horizontal"?


5
Це не працює. Текст дещо по центру, але DravableLeft дотримується лівої сторони.
Пітер Айтай

0

Я думаю, що android: gravity = "центр" повинен працювати


6
Не працює для мене. Він центрирує текст, але файл, що малюється, залишається ліворуч.
Peter Ajtai

Ви повинні оголосити піктограму та текст під одним і тим же батьком, використовувати android: gravity = "центр" для батьків
devanshu_kaushik

0

За пропозицією Роджа, до 4.0 не існує прямого способу централізувати текст із малюнком. І дійсно встановлення значення padding_left дійсно відсуває вікно від межі. Тому моя пропозиція полягає в тому, що під час виконання ви обчислюєте, скільки саме пікселів від лівої межі має бути ваш графічний малюнок, а потім передаєте їх за допомогою setPadding. Ваш розрахунок може бути чимось на зразок

int paddingLeft = (button.getWidth() - drawableWidth - textWidth) / 2;

Ширина ваших графічних зображень є фіксованою, і ви можете переглянути її, а також можете обчислити або відгадати ширину тексту.

Нарешті, вам знадобиться помножити значення прокладки на щільність екрана, що можна зробити за допомогою DisplayMetrics



0

публічний клас DravableCenterTextView розширює TextView {

public DrawableCenterTextView(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
}

public DrawableCenterTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public DrawableCenterTextView(Context context) {
    super(context);
}

@Override
protected void onDraw(Canvas canvas) {
    Drawable[] drawables = getCompoundDrawables();
    if (drawables != null) {
        Drawable drawableLeft = drawables[0];
        Drawable drawableRight = drawables[2];
        if (drawableLeft != null || drawableRight != null) {
            float textWidth = getPaint().measureText(getText().toString());
            int drawablePadding = getCompoundDrawablePadding();
            int drawableWidth = 0;
            if (drawableLeft != null)
                drawableWidth = drawableLeft.getIntrinsicWidth();
            else if (drawableRight != null) {
                drawableWidth = drawableRight.getIntrinsicWidth();
            }
            float bodyWidth = textWidth + drawableWidth + drawablePadding;
            canvas.translate((getWidth() - bodyWidth) / 2, 0);
        }
    }
    super.onDraw(canvas);
}

}


Це взагалі не працювало для мене. Ви можете, будь ласка, показати приклад? Можливо, я не використовую його правильно
андроїд розробник

0

Брудне виправлення.

android:paddingTop="10dp"
android:drawableTop="@drawable/ic_src"

Визначення правильної підкладки вирішить мету. Однак для різноманітного екрана використовуйте різні накладки і помістіть їх у ресурс розмірів у відповідну папку значень.


0

Використовуйте RelativeLayout (контейнер) та android: layout_centerHorizontal = "true" , мій зразок:

                <RelativeLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1" >

                    <CheckBox
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:layout_centerHorizontal="true"
                        android:layout_gravity="center"
                        android:layout_marginBottom="5dp"
                        android:layout_marginLeft="10dp"
                        android:layout_marginTop="5dp"
                        android:button="@drawable/bg_fav_detail"
                        android:drawablePadding="5dp"
                        android:text=" Favorite" />
                </RelativeLayout>

0

Інша можливість зберегти тему кнопки.

<Button
            android:id="@+id/pf_bt_edit"
            android:layout_height="@dimen/standard_height"
            android:layout_width="match_parent"
            />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_alignBottom="@id/pf_bt_edit"
            android:layout_alignLeft="@id/pf_bt_edit"
            android:layout_alignRight="@id/pf_bt_edit"
            android:layout_alignTop="@id/pf_bt_edit"
            android:layout_margin="@dimen/margin_10"
            android:clickable="false"
            android:elevation="20dp"
            android:gravity="center"
            android:orientation="horizontal"
            >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:clickable="false"
                android:src="@drawable/ic_edit_white_48dp"/>

            <TextView
                android:id="@+id/pf_tv_edit"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginLeft="@dimen/margin_5"
                android:clickable="false"
                android:gravity="center"
                android:text="@string/pf_bt_edit"/>

        </LinearLayout>

Завдяки цьому рішенню, якщо ваш додаток @ color / your_color @ color / your_highlight_color у вашій темі активності, ви можете мати тему Matherial на Lollipop із тінню та пульсацією, а для попередньої версії - плоскою кнопкою з кольором та виділенням coor, коли ви натискаєте на нього.

Більше того, за допомогою цього рішення автореалізуйте зображення

Результат: Перший на пристрої Льодяка Другий: На пристрої попереднього льодяника 3-й: Попередньо натисніть кнопку пристрою льодяника

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


0

Я зосереджений textViewза допомогою значка за допомогою paddingLeftта вирівнювання textView вліво | centerVertical . і для невеликого розриву між поданням та значком, який я використавdrawablePadding

         <Button
            android:id="@+id/have_it_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/textbox"
            android:drawableLeft="@drawable/have_it"
            android:drawablePadding="30dp"
            android:gravity="left|center_vertical"
            android:paddingLeft="60dp"
            android:text="Owner Contact"
            android:textColor="@android:color/white" />

2
Це не спрацює на багатьох екранах, лише на тому, на якому android:paddingLeftпрацювали.
сошіал

0

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

          <LinearLayout
            android:id="@+id/llContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/selector"
            android:clickable="true"
            android:gravity="center"
            android:orientation="vertical"
            android:padding="10dp"
            android:textStyle="bold">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="This is a text" />

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


        </LinearLayout>

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

Візьміть до уваги НЕ забудьте додати андроїд: clickkable = "true" у ваш основний контейнер (відносний чи лінійний), щоб дія відбулося.

Знову це може бути стара нитка, але все ж може допомогти комусь там.

-ціри сподіваються, що це допомагає- щасливі кодировки.


0

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


0

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

class IconButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = R.attr.buttonStyle
) : AppCompatButton(context, attrs, defStyle) {

    init {
        maxLines = 1
    }

    override fun onDraw(canvas: Canvas) {
        val buttonContentWidth = (width - paddingLeft - paddingRight).toFloat()

        val textWidth = paint.measureText(text.toString())

        val drawable = compoundDrawables[0] ?: compoundDrawables[2]
        val drawableWidth = drawable?.intrinsicWidth ?: 0
        val drawablePadding = if (textWidth > 0 && drawable != null) compoundDrawablePadding else 0
        val bodyWidth = textWidth + drawableWidth.toFloat() + drawablePadding.toFloat()

        canvas.save()

        val padding = (buttonContentWidth - bodyWidth).toInt() / 2
        val leftOrRight = if (compoundDrawables[0] != null) 1 else -1
        setPadding(leftOrRight * padding, 0, -leftOrRight * padding, 0)

        super.onDraw(canvas)
        canvas.restore()
    }
}

Важливо встановити гравітацію у вашій компоновці як "center_vertical | start", так і "center_vertical | end", залежно від того, де ви встановите значок. Наприклад:

<com.stackoverflow.util.IconButton
        android:id="@+id/cancel_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:drawableStart="@drawable/cancel"
        android:drawablePadding="@dimen/padding_small"
        android:gravity="center_vertical|start"
        android:text="Cancel" />

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


-5

використовуй це android:background="@drawable/ic_play_arrow_black_24dp"

просто встановіть фон на піктограму, яку ви хочете відцентрувати

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.