Як програмно встановити атрибут стилю у поданні


107

Я переглядаю XML із кодом нижче:

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

Я хотів би встановити "стиль" для кнопки, як я можу це зробити в Java, оскільки хочу використовувати кілька стилів для кожної кнопки, яку я буду використовувати.

Відповіді:


52

Як правило, ви не можете змінити стилі програмно; ви можете встановити вигляд екрана, або частини макета, або окремої кнопки у вашому макеті XML, використовуючи теми чи стилі . Проте теми можна застосувати програмно .

Існує також така річ, StateListDrawableщо дозволяє вам визначати різні витяги для кожного стану, в якому ви Buttonможете знаходитись, будь то зосереджений, вибраний, натиснутий, відключений тощо.

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

<?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>

Потім ви можете застосувати цей селектор до а Button, встановивши властивість android:background="@drawable/my_button".


4
Моя проблема полягає в тому, що я завантажую дані з веб-сервісу, який описує інформацію про мою кнопку. Кнопки повинні мати різний стиль залежно від категорії, до якої вони належать. Ось чому я хотів би встановити стиль динамічно.
— Lint_

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

Я просто думав про це, безпосередньо перед тим, як перевірити, чи є у мене нові відповіді. Дуже дякую.
— Lint_

5
Чи не можливо створити стиль для кнопки, яка визначає розмір тексту, поля тощо тощо, а потім застосувати це до кнопки програмно. Напевно, це можливо сказати, якщо у мене є шість кнопок, які хочуть мати той самий стиль?
— Ведмідь

який атрибут ми можемо надути? чи можемо ми завищити поля, набивки?
— Android Man

49

Перш за все, вам не потрібно використовувати надувний макет для створення простої кнопки. Ви можете просто використовувати:

button = new Button(context);

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

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);

Цей останній не можна використовувати для зміни всіх атрибутів; наприклад, щоб змінити прокладки, ви повинні використовувати a 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
Слід створити хорошу відповідь щодо розгляду кнопки. Було б добре подивитися, як це зробити для наявної кнопки.
— Якісний каталізатор

Дивіться відповідь з карток.
— Крісті Валлійська

10

Якщо ви використовуєте бібліотеку підтримки, ви можете просто її використовувати

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

для TextViews та кнопок. Для решти переглядів є схожі класи :-)


який пакет R потрібно використовувати для отримання цього стилю?
— htafoya

6

Для всіх, хто шукає матеріальної відповіді, дивіться цю публікацію ТА: ТА Розмальовки кнопок в Android з Матеріал дизайну та 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: Я виявив, що пристрої, що працюють перед льодяником, не працюють із наведеним вище кодом. Дивіться цю публікацію про те, як додати підтримку для пристроїв, що попередньо використовуються: 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

Залежно від того, які атрибути стилю ви хочете змінити, ви можете використовувати паризьку бібліотеку:

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

Підтримуються багато атрибутів, таких як фон, набивання, розмір тексту, 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);
    }
}

Заявіть про стилі в своєму attrs.xml, стилі для цього прикладу є:

<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.