以编程方式设置 TextView 的样式

Posted

技术标签:

【中文标题】以编程方式设置 TextView 的样式【英文标题】:Set style for TextView programmatically 【发布时间】:2011-03-09 16:42:30 【问题描述】:

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

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

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

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

【问题讨论】:

【参考方案1】:

我不相信您可以以编程方式设置样式。为了解决这个问题,您可以创建一个指定样式的模板布局 xml 文件,例如在 res/layout create tvtemplate.xml 中,内容如下:

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

然后将其膨胀以实例化您的新 TextView:

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

【讨论】:

这胜过 Dandre Allison 的回答是它不需要 API v11。 它可能有效,但这没有意义。怎么可能用 xml 文件来设置呢?如果不是以编程方式。不使用 xml 文件是有原因的,其中一个原因是我习惯于编写代码来构建 UI,所以我不想学习一种新的方法,因为我的内存有限,我想保留一些空间其他事情。 @IharobAlAsimi 没错,所有事情都可以通过编程方式完成,而且 LayoutInflater 知道将 XML 转换为对象的一切。可悲的是,很多这样的东西都隐藏在私有 API 下,创建一些对象的唯一方法是向构造函数提供 AttributeSet。 与所有其他答案不同,这实际上适用于微调器,因此对您来说是一颗金星 只有此解决方案适用于我的样式中定义的所有属性,这与具有 4 参数构造函数的解决方案不同(例如,textAppearance 定义为样式)。【参考方案2】:

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

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

编辑:this指上下文

【讨论】:

只要您所做的一切都是在模仿文本的“风格”,您的答案就有效。如果您尝试对 TextView 执行其他操作,例如添加填充或边距,则它不起作用。所以,我不是说你错了,但你的答案是有限的。在运行时膨胀视图是应用综合样式的唯一方法。 使用膨胀模板和使用setTextAppearance这两种方案都是合理的。要解决第二种解决方案的填充/边距问题,您可以调用 textView.setLayoutParams(layoutParams) 此方法在 API 级别 23 中已弃用。在 API 23+ 中使用 setTextAppearance(int) 代替。 确保版本至少为 API 23 (M) 使用支持库中的方法,TextViewCompat.setTextAppearance【参考方案3】:

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

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

【讨论】:

好东西!在支持 API 8 的同时以编程方式设置样式的唯一方法。 出于某种原因,它不会影响我按钮的样式。我已将我的风格定义为:&lt;style name="TabButton"&gt;&lt;item name="android:background"&gt;@drawable/tabbar_button_bkgnd&lt;/item&gt;...&lt;/style&gt;。然后我用一个构造来调用它:new Button(new ContextThemeWrapper(context, R.style.TabButton));。但是该按钮只是忽略了我的设置。我在这里做错了吗? @AlaksiejN.You 应该像这样继承 Widget.Button 样式parent="@android:style/Widget.Button" @maxcanna 出于某种原因添加parent 并没有改变一点。所以我只是继续使用inflate 解决方案。 @AliakseiN。您需要使用 3-arg 构造函数,例如new Button(new ContextThemeWrapper(context, R.style.TabButton), null, 0)。否则,将应用默认按钮样式,并且此样式将覆盖您通过 ContextThemeWrapper 合并到主题中的按钮样式。【参考方案4】:

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

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

Answer from Romain Guy

reference

【讨论】:

您的回答具有误导性 - 您是否尝试将本主题阅读到最后? 如何误导?接受的答案具有误导性,因为 Romain Guy 明确表示您可以以编程方式“设置”样式。只是没有工具可以动态更改它。不过,这个帖子似乎并不认为是这种情况。 注意,此调用需要 API 级别 11。 @PaulVerest 这不是报价单。 最后一个 int 不是样式资源。它是“当前主题中的一个属性,包含对为视图提供默认值的样式资源的引用。”【参考方案5】:

参数 int defStyleAttr 没有指定样式。来自 Android 文档:

defStyleAttr - 当前主题中包含 对样式资源的引用,该资源为 看法。可以为 0 以不查找默认值。

要在 View 构造函数中设置样式,我们有两种可能的解决方案:

    使用 ContextThemeWrapper:

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

    使用四参数构造函数(从 LOLLIPOP 开始可用):

    TextView textView = new TextView(yourContext, null, 0, R.style.your_style);
    
两种解决方案的

关键 - defStyleAttr 参数应为 0 以将我们的样式应用于视图。

【讨论】:

感谢您的回答。我可以确认这对我有用。特别感谢您在回答末尾的注释。 样式不知何故不适用于边距属性。为什么?【参考方案6】:

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

【讨论】:

其实是一样的 @njzk2 谢谢...显然在发布之前没有考虑他的评论。在构建 UI 之前无法以编程方式设置样式,因此将使用相同的代码以编程方式更改或设置样式。【参考方案7】:

接受的答案对我来说是很好的解决方案。唯一要补充的是inflate()方法。

在接受的答案中,所有android:layout_* 参数都不会被应用。

原因是无法调整,因为null被传递为ViewGroup parent

你可以这样使用它:

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

parentViewGroup,您可以从中调整android:layout_*

在这种情况下,将设置所有相关属性。

希望它对某人有用。

【讨论】:

【参考方案8】:

当使用可能使用样式继承(或事件样式属性)的自定义视图时,您必须修改第二个构造函数以免丢失样式。这对我有用,无需使用 setTextAppearence()

public CustomView(Context context, AttributeSet attrs) 
    this(context, attrs, attrs.getStyleAttribute());

【讨论】:

【参考方案9】:

我也遇到了这个问题,我找到了以编程方式设置样式的方法。也许你们都需要它,所以我在那里更新。

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

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

你可以试一试,希望它能完美地为你工作。

【讨论】:

【参考方案10】:

我们可以使用TextViewCompact.setTextAppearance(textView, R.style.xyz)

Android doc 供参考。

【讨论】:

【参考方案11】:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
    textView.setTextAppearance(R.style.yourStyle)

【讨论】:

【参考方案12】:

我只测试了EditText,但是你可以使用方法

public void setBackgroundResource (int resid)

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

这个方法属于 View 我相信它适用于任何 UI 元素。

问候。

【讨论】:

根据the documentation,这只适用于可绘制对象,而不适用于样式。因此,如果这真的有效,那只是“偶然”,你不应该依赖它。

以上是关于以编程方式设置 TextView 的样式的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 以编程方式居中 UITextView

Android - 以编程方式设置 TextView TextStyle?

以编程方式设置 TextView 的布局权重

以编程方式设置TextView的布局权重

以编程方式将文本颜色设置为主要的 android textview

动态生成的 TextView 中的默认样式