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


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.