Установить стиль для TextView программно

249

Я пытаюсь использовать TextViewконструктор со стилем, как это:

TextView myText = new TextView(MyActivity.this, null, R.style.my_style);

Однако, когда я делаю это, текстовое представление, кажется, не принимает стиль (я проверил стиль, установив его на статический объект).

Я также пытался использовать, myText.setTextAppearance(MyActivity.this, R.style.my_style)но это также не работает.

Бен
источник

Ответы:

318

Я не верю, что вы можете установить стиль программно. Чтобы обойти это, вы можете создать XML-файл макета шаблона с назначенным стилем, например, в res / layout создайте файл tvtemplate.xml, как показано ниже:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="This is a template"
        style="@style/my_style" />

затем надуйте это, чтобы создать экземпляр вашего нового TextView:

TextView myText = (TextView)getLayoutInflater().inflate(R.layout.tvtemplate, null);

Надеюсь это поможет.

Дэн Килпатрик
источник
1
Ответ Дандре Эллисон в том, что он не требует API v11.
Мартин Каподичи
2
Это могло бы сработать, но это не имеет смысла. Как это можно установить с помощью XML-файла? если не программно . Есть причины не использовать XML-файлы, одна из них заключается в том, что я привык писать код для создания пользовательского интерфейса, поэтому я не хочу изучать новый способ сделать это, так как моя память ограничена, и я хочу оставить немного места для другие вещи.
Ихароб Аль Асими
@IharobAlAsimi все верно, все можно сделать программно, а LayoutInflater знает все о превращении XML в объекты. К сожалению, многие такие вещи скрыты под частными API, и единственный способ создания некоторых объектов - это предоставление AttributeSet конструктору.
Miha_x64
В отличие от всех других ответов, это на самом деле сработало со счетчиками, так что золотая звезда для вас
Роуэн Берри
121

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

textView.setTextAppearance(this, R.style.MyTextStyle);

Изменить: это относится к контексту

Shahul3D
источник
50
Ваш ответ работает до тех пор, пока все ваши действия связаны с «стилем» текста. Это не работает, если вы пытаетесь делать другие вещи с TextView, такие как добавление отступов или полей. Итак, я не говорю, что вы не правы, но ваш ответ ограничен. Раздувание представления во время выполнения - единственный способ применить всеобъемлющий стиль.
Билл Мот
1
Оба решения использования раздутого шаблона и использования setTextAppearance являются разумными. Чтобы решить проблему заполнения / отступов для 2-го решения, вы можете вызвать textView.setLayoutParams (layoutParams)
AlanKley,
Этот метод устарел на уровне API 23. Используйте setTextAppearance (int) вместо этого в API 23+.
Сергей
Убедитесь, что версия не ниже API 23 (M)
Br0thazS0ul
4
использовать метод из библиотеки поддержки,TextViewCompat.setTextAppearance
Rubin Yoo
97

Вы можете передать ContextThemeWrapper в конструктор следующим образом:

TextView myText = new TextView(new ContextThemeWrapper(MyActivity.this, R.style.my_style));
maxcanna
источник
1
отличный материал! единственный способ, которым я мог бы устанавливать стили программно, поддерживая API 8.
tbraun
По какой-то причине это не влияет на стиль моей кнопки. Я определил свой стиль как: <style name="TabButton"><item name="android:background">@drawable/tabbar_button_bkgnd</item>...</style>. И тогда я призываю это с конструкцией new Button(new ContextThemeWrapper(context, R.style.TabButton));. Но кнопка просто игнорирует мои настройки. Я что-то здесь не так делаю?
Алекс Н.
@ AlaksiejN. Вы должны унаследовать от стиля Widget.Button, как этоparent="@android:style/Widget.Button"
maxcanna
@maxcanna По некоторым причинам добавление parentне изменилось немного. Так что я просто пошел дальше с inflateрешением.
Алекс Н.
11
@AliakseiN. Вам нужно использовать 3-аргументный конструктор, например new Button(new ContextThemeWrapper(context, R.style.TabButton), null, 0). В противном случае будет применен стиль кнопки по умолчанию, и этот стиль будет переопределять стиль кнопки, который вы добавили в тему через ContextThemeWrapper.
Ньютон
17

Вы можете установить стиль в конструкторе (но стили не могут быть динамически изменены / установлены).

View(Context, AttributeSet, int)( intатрибут текущей темы, содержащий ссылку на стиль)

Ответ от Ромена Гая

ссылка

Дандре Эллисон
источник
ваш ответ вводит в заблуждение - вы пытались прочитать эту ветку до конца?
Андр
3
Как это ввести в заблуждение? Принятый ответ вводит в заблуждение, потому что Romain Guy прямо говорит, что вы можете «установить» стиль программно. Просто нет возможности изменить это динамически. Этот поток, кажется, не думает, что это так.
Дандре Эллисон
1
Осторожно, этот вызов требует API уровня 11.
Мартин Каподичи
1
@PaulVerest это не цитата.
Дандре Эллисон
6
Последний int не является ресурсом стиля. Это «Атрибут в текущей теме, который содержит ссылку на ресурс стиля, который предоставляет значения по умолчанию для представления».
RVE
11

Параметр int defStyleAttrне определяет стиль. Из документации Android:

defStyleAttr - Атрибут в текущей теме, который содержит ссылку на ресурс стиля, который предоставляет значения по умолчанию для представления. Может быть 0, чтобы не искать значения по умолчанию.

Для настройки стиля в конструкторе View у нас есть 2 возможных решения:

  1. С использованием ContextThemeWrapper:

    ContextThemeWrapper wrappedContext = new ContextThemeWrapper(yourContext, R.style.your_style);
    TextView textView = new TextView(wrappedContext, null, 0);
  2. С конструктором с четырьмя аргументами (доступно начиная с LOLLIPOP):

    TextView textView = new TextView(yourContext, null, 0, R.style.your_style);

Ключевая вещь для обоих решений - defStyleAttrпараметр должен быть 0, чтобы применить наш стиль к представлению.

DmitryArc
источник
5

Динамическое изменение стилей не поддерживается (пока). Вы должны установить стиль до того, как представление будет создано через XML.

Крис Кэшвелл
источник
20
что на самом деле одно и то же
njzk2
@ njzk2 спасибо ... очевидно, не думал о своем комментарии перед публикацией. Нет способа установить стиль программно до создания пользовательского интерфейса, поэтому тот же код будет использоваться для изменения или установки стиля программно.
Крис Кэшвелл
3

Принятый ответ был отличным решением для меня. Единственное, что нужно добавить, это inflate()метод.

В принятом ответе все android:layout_*параметры не будут применены.

Причина не в том, чтобы отрегулировать это, причина nullбыла передана как ViewGroup parent.

Вы можете использовать это так:

View view = inflater.inflate(R.layout.view, parent, false);

и parentэто ViewGroup, откуда вы хотели бы настроить android:layout_*.

В этом случае все относительные свойства будут установлены.

Надеюсь, это будет кому-то полезно.

Анор
источник
2

При использовании пользовательских представлений, которые могут использовать наследование стилей (или атрибуты стиля событий), вы должны изменить второй конструктор, чтобы не потерять стиль. Это сработало для меня, без необходимости использовать setTextAppearence () :

public CustomView(Context context, AttributeSet attrs) {
    this(context, attrs, attrs.getStyleAttribute());
}
saiyancoder
источник
2

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

Третий параметр конструктора View принимает тип attr в вашей теме в качестве исходного кода ниже:

public TextView(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.textViewStyle);
}

Таким образом, вы должны передать тип R.attr. ** вместо R.style. **

В своих кодах я сделал следующие шаги:

Во-первых, настройте пользовательский атрибут, который будет использоваться темами в файле attr.xml.

<attr name="radio_button_style" format="reference" />

Во-вторых, укажите свой стиль в используемой теме в style.xml.

 <style name="AppTheme" parent="android:Theme.Translucent">
    <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    <item name="radio_button_style">@style/radioButtonStyle</item>
</style>
<style name="radioButtonStyle" parent="@android:style/Widget.CompoundButton.RadioButton">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">64dp</item>
    <item name="android:background">#000</item>
    <item name="android:button">@null</item>
    <item name="android:gravity">center</item>
    <item name="android:saveEnabled">false</item>
    <item name="android:textColor">@drawable/option_text_color</item>
    <item name="android:textSize">9sp</item>
</style>

В конце используйте!

            RadioButton radioButton = new RadioButton(mContext, null, R.attr.radio_button_style);

представление, созданное программно, будет использовать указанный стиль в вашей теме.

Вы можете попробовать, и надеюсь, что это сработает для вас отлично.

mrtwo
источник
0

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

public void setBackgroundResource (int остаток)

применить стиль, определенный в файле XML.

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

С уважением.

floydaddict
источник
Согласно документации, это должно работать только с рисунками, а не со стилем. Таким образом, если это действительно работает, это только «случайно», и вы не должны полагаться на это.
Хайнци
0

Мы можем использовать TextViewCompact.setTextAppearance(textView, R.style.xyz).

Android док для справки.

Кшитий Джайн
источник