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


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.