Как программно установить атрибут стиля в представлении


107

Я получаю представление из XML с кодом ниже:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);

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

Ответы:


52

Обычно вы не можете изменять стили программно; вы можете установить внешний вид экрана, или части макета, или отдельной кнопки в макете XML, используя темы или стили . Тем не менее, темы можно применять программно .

Существует также такая вещь, как a, StateListDrawableкоторая позволяет вам определять разные чертежи для каждого состояния, в котором вы Buttonможете находиться, будь то сфокусированный, выбранный, нажатый, отключенный и так далее.

Например, чтобы ваша кнопка меняла цвет при нажатии, вы можете определить XML-файл с именем res/drawable/my_button.xmldirectory следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item
    android:state_pressed="true"
    android:drawable="@drawable/btn_pressed" />
  <item
    android:state_pressed="false"
    android:drawable="@drawable/btn_normal" />
</selector>

Затем вы можете применить этот селектор к a Button, установив свойство android:background="@drawable/my_button".


4
Моя проблема в том, что я загружаю данные из веб-сервиса, которые описывают информацию о моей кнопке. Кнопки должны иметь разный стиль в зависимости от категории, к которой они принадлежат. Вот почему я хотел бы динамически задавать стиль.
Lint_ 07

3
Ну, вы не можете изменить styleатрибут Android , но вы можете программно установить фон, Buttonкак вы можете с любым другим представлением, если этого будет достаточно. Кроме того, в качестве Buttonнаследования от TextViewможно изменять свойства текста. Просто посмотрите документацию по API для этих элементов ... developer.android.com/reference/android/view/…
Кристофер Орр,

Я просто думал об этом, прямо перед тем, как проверить, есть ли у меня новые ответы. Большое спасибо.
Lint_ 07

5
Невозможно создать стиль для кнопки, который определяет размер текста, поля и т. Д., А затем программно применить его к кнопке. Конечно, можно сказать, есть ли у меня шесть кнопок, которые хотят иметь один стиль?
Bear

какой атрибут мы можем надуть? можем ли мы увеличить поля, отступы?
Android Man

49

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

button = new Button(context);

Если вы хотите стилизовать кнопку, у вас есть 2 варианта: самый простой - просто указать все элементы в коде, как предлагают многие другие ответы:

button.setTextColor(Color.RED);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);

Другой вариант - определить стиль в XML и применить его к кнопке. В общем случае ContextThemeWrapperдля этого можно использовать :

ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle);
button = new Button(newContext);

Чтобы изменить атрибуты, связанные с текстом, в TextView (или его подклассах, таких как Button), существует специальный метод:

button.setTextAppearance(context, R.style.MyTextStyle);

Последний не может использоваться для изменения всех атрибутов; например, чтобы изменить отступы, вам нужно использовать ContextThemeWrapper. Но для цвета текста, размера и т. Д. Можно использовать setTextAppearance.


1
Просто гениально. ContextThemeWrapper - это то, что я так долго искал.
Аяз Алифов

Это работает фантастически. Давно искал это решение.
jasonjwwilliams

14

Да, вы можете использовать, например, в кнопке

Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);

5
Это установит фон, но стиль может указывать не только фон. Многие представления (включая кнопку) имеют конструктор, который принимает идентификатор стиля в качестве параметра. Однако у меня проблемы с тем, чтобы это работало для меня - кнопка отображается как текст без рамки или чего-то еще. Вместо этого я мог бы создать макет только с кнопкой (с указанным стилем), надуть этот макет, затем установить текст кнопки и еще много чего.
spaaarky21

11

Вы можете сделать такие атрибуты стиля:

Button myButton = new Button(this, null,android.R.attr.buttonBarButtonStyle);

на месте:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btn"
    style="?android:attr/buttonBarButtonStyle"

    />

7
Хороший ответ, учитывая, что кнопка должна быть создана. Было бы неплохо увидеть, как это сделать для существующей кнопки.
Quality Catalyst

Смотрите ответ от cesards.
Кристи Уэлш

10

Если вы используете библиотеку поддержки, вы можете просто использовать

TextViewCompat.setTextAppearance(textView, R.style.AppTheme_TextStyle_ButtonDefault_Whatever);

для TextViews и кнопок. Аналогичные классы есть и для остальных видов :-)


какой пакет R вам нужно использовать, чтобы получить этот стиль?
htafoya,

6

Для тех, кто ищет ответ по материалам, см. Этот пост SO: Раскрашивание кнопок в Android с помощью Material Design и AppCompat

Я использовал комбинацию этого ответа, чтобы установить белый цвет текста кнопки по умолчанию для моей кнопки: https://stackoverflow.com/a/32238489/3075340

Затем этот ответ https://stackoverflow.com/a/34355919/3075340, чтобы программно установить цвет фона. Код для этого:

ViewCompat.setBackgroundTintList(your_colored_button,
 ContextCompat.getColorStateList(getContext(),R.color.your_custom_color));

your_colored_button может быть просто обычным Button кнопкой или кнопкой AppCompat, если хотите - я протестировал приведенный выше код с обоими типами кнопок, и он работает.

EDIT: я обнаружил, что устройства pre-lollipop не работают с приведенным выше кодом. См. Этот пост о том, как добавить поддержку устройств до леденца на палочке: https://stackoverflow.com/a/30277424/3075340

В основном это делают:

Button b = (Button) findViewById(R.id.button);
ColorStateList c = ContextCompat.getColorStateList(mContext, R.color.your_custom_color;
Drawable d = b.getBackground();
if (b instanceof AppCompatButton) {
    // appcompat button replaces tint of its drawable background
    ((AppCompatButton)b).setSupportBackgroundTintList(c);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Lollipop button replaces tint of its drawable background
    // however it is not equal to d.setTintList(c)
    b.setBackgroundTintList(c);
} else {
    // this should only happen if 
    // * manually creating a Button instead of AppCompatButton
    // * LayoutInflater did not translate a Button to AppCompatButton
    d = DrawableCompat.wrap(d);
    DrawableCompat.setTintList(d, c);
    b.setBackgroundDrawable(d);
}

6

В зависимости от того, какие атрибуты стиля вы хотите изменить, вы можете использовать библиотеку Paris:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Paris.style(view).apply(R.style.YourStyle);

Поддерживаются многие атрибуты, такие как background, padding, textSize, textColor и т. Д.

Отказ от ответственности: я создал библиотеку.


5

Ответ @Dayerman и @h_rules правильный. Чтобы дать подробный пример с кодом, в папке с возможностью рисования создайте файл xml с именем button_disabled.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">   
 <solid android:color="@color/silver"/>
<corners
   android:bottomRightRadius="20dp"
   android:bottomLeftRadius="20dp"
   android:topLeftRadius="20dp"
   android:topRightRadius="20dp"/>
</shape>

Затем в Java

((Button) findViewById(R.id.my_button)).setEnabled(false);
((Button) findViewById(R.id.my_button)).setBackgroundResource(R.drawable.button_disabled);

Это отключит свойство кнопки и установит серебряный цвет.

[Цвет определяется в color.xml как:

<resources>

    <color name="silver">#C0C0C0</color>

</resources>

4
@Pacerier: вопрос вовсе не об этом. Неясно, какой это стиль - XML ​​или java. Он только спрашивает, как программно установить стиль.
Харви

3

Во время выполнения вы знаете, какой стиль вы хотите, чтобы ваша кнопка имела. Итак, заранее в xml в папке макета вы можете иметь все готовые кнопки с нужными стилями. Итак, в папке макета у вас может быть файл с именем button_style_1.xml. Содержимое этого файла может выглядеть так:

<?xml version="1.0" encoding="utf-8"?>
<Button
    android:id="@+id/styleOneButton"
    style="@style/FirstStyle" />

Если вы работаете с фрагментами, то в onCreateView вы раздуваете эту кнопку, например:

Button firstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

где контейнер - это контейнер ViewGroup, связанный с методом onCreateView, который вы переопределяете при создании фрагмента.

Нужны еще две такие кнопки? Вы создаете их так:

Button secondFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
Button thirdFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

Вы можете настроить эти кнопки:

secondFirstStyleBtn.setText("My Second");
thirdFirstStyleBtn.setText("My Third");

Затем вы добавляете свои настраиваемые стилизованные кнопки в контейнер макета, который вы также раздули в методе onCreateView:

_stylizedButtonsContainer = (LinearLayout) rootView.findViewById(R.id.stylizedButtonsContainer);

_stylizedButtonsContainer.addView(firstStyleBtn);
_stylizedButtonsContainer.addView(secondFirstStyleBtn);
_stylizedButtonsContainer.addView(thirdFirstStyleBtn);

Вот так можно динамически работать со стилизованными кнопками.


0

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

public interface StyleHolder<V extends View> {
    void applyStyle(V view);
}

Теперь для каждого стиля, который вы хотите использовать прагматично, просто реализуйте интерфейс, например:

public class ButtonStyleHolder implements StyleHolder<Button> {

    private final Drawable background;
    private final ColorStateList textColor;
    private final int textSize;

    public ButtonStyleHolder(Context context) {
        TypedArray ta = context.obtainStyledAttributes(R.style.button, R.styleable.ButtonStyleHolder);

        Resources resources = context.getResources();

        background = ta.getDrawable(ta.getIndex(R.styleable.ButtonStyleHolder_android_background));

        textColor = ta.getColorStateList(ta.getIndex(R.styleable.ButtonStyleHolder_android_textColor));

        textSize = ta.getDimensionPixelSize(
                ta.getIndex(R.styleable.ButtonStyleHolder_android_textSize),
                resources.getDimensionPixelSize(R.dimen.standard_text_size)
        );

        // Don't forget to recycle!
        ta.recycle();
    }

    @Override
    public void applyStyle(Button btn) {
        btn.setBackground(background);
        btn.setTextColor(textColor);
        btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    }
}

Объявите styleable в вашем attrs.xml, styleable для этого примера:

<declare-styleable name="ButtonStyleHolder">
    <attr name="android:background" />
    <attr name="android:textSize" />
    <attr name="android:textColor" />
</declare-styleable>

Вот стиль, заявленный в styles.xml:

<style name="button">
    <item name="android:background">@drawable/button</item>
    <item name="android:textColor">@color/light_text_color</item>
    <item name="android:textSize">@dimen/standard_text_size</item>
</style>

И наконец реализация держателя стиля:

Button btn = new Button(context);    
StyleHolder<Button> styleHolder = new ButtonStyleHolder(context);
styleHolder.applyStyle(btn);

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


-1

Недавно я столкнулся с той же проблемой. вот как я это решил.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <!-- This is the special two colors background START , after this LinearLayout, you can add all view that have it for main background-->
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:weightSum="2"

    android:background="#FFFFFF"
    android:orientation="horizontal"
    >

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#0000FF" />

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#F000F0" />
    </LinearLayout>
    <!-- This is the special two colors background END-->

   <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:text="This Text is centered with a special backgound,
    You can add as much elements as you want as child of this RelativeLayout"
    android:textColor="#FFFFFF"
    android:textSize="20sp" />
</RelativeLayout>
  • Я использовал LinearLayout с android: weightSum = "2"
  • Я дал двум дочерним элементам android: layout_weight = "1" (каждому я выделил 50% родительского пространства (ширину и высоту))
  • И, наконец, я дал двум дочерним элементам разные цвета фона для окончательного эффекта.

Спасибо !

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