Как программно установить атрибут стиля в представлении
Я получаю представление из XML с кодом ниже:
Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Я хотел бы установить "стиль" для кнопки, как я могу сделать это в Java, так как хочу использовать несколько стилей для каждой кнопки, которую я буду использовать.
11 ответов
Как правило, вы не можете изменить стили программно; Вы можете установить внешний вид экрана, или части макета, или отдельной кнопки в макете XML, используя темы или стили. Темы могут, однако, применяться программно.
Существует также такая вещь, как StateListDrawable
который позволяет вам определять различные drawables для каждого состояния вашего 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"
,
Прежде всего, вам не нужно использовать разметчик для создания простой кнопки. Вы можете просто использовать:
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
,
Вы можете сделать атрибуты стиля следующим образом:
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"
/>
Да, вы можете использовать, например, в кнопке
Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);
Если вы используете библиотеку поддержки, вы можете просто использовать
TextViewCompat.setTextAppearance(getContext(), R.style.AppTheme_TextStyle_ButtonDefault_Whatever);
для TextViews и кнопок. Есть аналогичные классы для остальных видов:-)
В зависимости от того, какие атрибуты стиля вы хотите изменить, вы можете использовать парижскую библиотеку:
Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Paris.style(view).apply(R.style.YourStyle);
Поддерживаются многие атрибуты, такие как background, padding, textSize, textColor и т. Д.
Отказ от ответственности: я автор библиотеки.
Ответ @Dayerman и @h_rules правильный. Чтобы дать подробный пример с кодом, в папке drawable создайте 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>
Для тех, кто ищет ответ на материал, см. Этот пост: раскраска кнопок в Android с помощью Material Design и AppCompat
Я использовал комбинацию этого ответа, чтобы установить для белого цвета текста кнопки по умолчанию белый: /questions/29684096/raskraski-knopok-v-android-s-pomoschyu-material-design-i-appcompat/29684109#29684109
Затем этот ответ /questions/29684096/raskraski-knopok-v-android-s-pomoschyu-material-design-i-appcompat/29684100#29684100 чтобы программно установить цвет фона. Код для этого:
ViewCompat.setBackgroundTintList(your_colored_button,
ContextCompat.getColorStateList(getContext(),R.color.your_custom_color));
your_colored_button
может быть просто регулярным Button
или кнопку AppCompat, если хотите - я тестировал приведенный выше код с обоими типами кнопок, и он работает.
РЕДАКТИРОВАТЬ: я обнаружил, что устройства pre-lollipop не работают с вышеуказанным кодом. См. Этот пост о том, как добавить поддержку устройств перед леденцом на палочке: /questions/5709131/ispolzovanie-klassa-drawablecompat-dlya-primeneniya-tintlist/5709141#5709141
В основном сделайте это:
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);
}
Во время выполнения вы знаете, какой стиль вы хотите, чтобы ваша кнопка имела. Поэтому заранее, в 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);
И вот как вы можете динамически работать со стилизованными кнопками.
Я сделал вспомогательный интерфейс для этого, используя шаблон держателя.
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);
Я нашел это очень полезным, так как он может быть легко использован повторно и сохраняет код чистым и многословным, я бы рекомендовал использовать его только как локальную переменную, чтобы мы могли позволить сборщику мусора выполнять свою работу, как только мы закончим с настройкой всех стилей,
Я недавно столкнулся с той же проблемой. вот как я это решил.
<?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% родительского пространства (ширина и высота))
- И наконец, я дал двум дочерним элементам разные цвета фона, чтобы получить конечный эффект.
Спасибо!