以编程方式设置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);

parentViewGroup您想要调整的地方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.