以编程方式设置TextView的样式


249

我正在尝试使用TextView具有以下样式的构造函数:

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

但是,当我这样做时,文本视图似乎没有采用样式(我通过将样式设置在静态对象上来验证了样式)。

我也尝试过使用,myText.setTextAppearance(MyActivity.this, R.style.my_style)但它也不起作用。

Answers:


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
Dandre Allison的答案之所以如此,是因为它不需要API v11。
— Martin Capodici 2014年

2
它可能起作用了,但这没有任何意义。如何用xml文件设置它?如果不是以编程方式。有一些原因不使用xml文件,其中之一是我习惯于编写代码来构建UI,因此由于内存有限,我不想学习一种新的处理方式,我想保留一些空间其他事情。
— Iharob Al Asimi

没错,@ IharobAlAsimi可以通过编程来完成所有事情,并且LayoutInflater知道将XML转换为对象的所有知识。不幸的是,许多这样的事情都隐藏在私有API下,创建某些对象的唯一方法是向构造函数提供AttributeSet。
— Miha_x64 '17

与所有其他答案不同,这实际上适用于微调器,因此为您提供了一颗金星
— Rowan Berry

121

您可以创建通用样式,然后在多个文本视图上重新使用它,如下所示:

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

编辑:这是指上下文


50
只要您所做的一切都使文本的“样式”变幻莫测,您的答案就会起作用。如果您尝试对TextView执行其他操作(例如添加填充或边距),则此方法将无效。因此,我并不是说您错了,但您的答案是有限的。在运行时膨胀视图是应用全面样式的唯一方法。
— 比尔·莫特

1
使用膨胀模板和setTextAppearance的两种解决方案都是合理的。要解决第二个解决方案的填充/边距问题,您可以调用textView.setLayoutParams(layoutParams)
— AlanKley13年

此方法在API级别23中已弃用。在API 23+中使用setTextAppearance(int)代替。
— 塞尔吉(Sergii)2015年

确保版本至少为API 23(M)
— Br0thazS0ul 2016年

4
使用支持库中的方法,TextViewCompat.setTextAppearance
— Rubin Yoo 2016年

97

您可以像这样将ContextThemeWrapper传递给构造函数:

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

1
好东西!支持API 8时,我可以通过编程方式设置样式的唯一方法
— 。– tbraun 2013年

由于某种原因,它不会影响我按钮的样式。我的风格定义如下:<style name="TabButton"><item name="android:background">@drawable/tabbar_button_bkgnd</item>...</style>。然后,我用建筑调用它:new Button(new ContextThemeWrapper(context, R.style.TabButton));。但是按钮只是忽略了我的设置。我在这里做错什么吗?
— Aleks N.

@AlaksiejN。您应该继承自Widget.Button样式,例如parent="@android:style/Widget.Button"
— maxcanna 2014年

@maxcanna由于某种原因,添加parent没有改变。因此,我只是着手inflate解决方案。
— Aleks N.

11
@AliakseiN。您需要使用3-arg构造函数,例如new Button(new ContextThemeWrapper(context, R.style.TabButton), null, 0)。否则,将应用默认的按钮样式,并且该样式将覆盖通过ContextThemeWrapper合并到主题中的按钮样式。
— Newtonx

17

您可以在构造函数中设置样式(但是不能动态更改/设置样式)。

View(Context, AttributeSet, int)(这int是当前主题中的一个属性,其中包含对样式的引用)

罗曼·盖伊的回答

参考


您的答案具有误导性-您是否尝试过阅读本主题的结尾?
— andr 2013年

3
怎么会误导?接受的答案具有误导性,因为Romain Guy明确表示您可以通过编程“设置”样式。只是没有一种可以动态更改它的工具。该线程似乎并不认为是这种情况。
— Dandre Allison

1
当心,这需要调用API级别11
— 马丁Capodici

1
@PaulVerest这不是报价。
— Dandre Allison 2014年

6
最后一个int 不是样式资源。它是“当前主题中的一个属性,其中包含对提供视图默认值的样式资源的引用。”
— rve 2015年

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才能将样式应用于视图。


5

目前尚不支持动态更改样式。您必须通过XML创建视图之前设置样式。


20
实际上恰好是同一件事
— njzk2 2012年

@ njzk2谢谢...显然在发布之前没有考虑他的评论。无法在构建UI之前以编程方式设置样式,因此将使用相同的代码以编程方式更改或设置样式。
— 克里斯·卡什韦尔

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

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。

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

以编程方式创建的视图将在主题中使用指定的样式。

您可以尝试一下,希望它可以完美地为您工作。


0

我只用EditText测试过,但是可以使用

公共无效setBackgroundResource(int resid)

应用在XML文件中定义的样式。

当然,此方法属于View,我相信它将与任何UI元素一起使用。

问候。


根据文档,这仅适用于可绘制对象,不适用于样式。因此,如果这确实可行,那只是“偶然”,您不应该依赖它。
— Heinzi 2012年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.