如何在视图中以编程方式设置样式属性

122

我正在使用以下代码从XML中获取视图:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);

我想为按钮设置"style",由于我要使用几种不同的样式来区分每个按钮,请问在Java中如何实现这一点。

11个回答

65

首先,你不需要使用布局膨胀器来创建一个简单的按钮。你只需要使用:

button = new Button(context);

如果您想为按钮设置样式,有两个选择:最简单的方法是只需在代码中指定所有元素,就像其他答案所建议的那样:

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(R.style.MyTextStyle);

或者,如果您需要支持 API-23 之前的设备(Android 6.0)

button.setTextAppearance(context, R.style.MyTextStyle);

此方法无法用于更改所有属性;例如,要更改填充(padding),您需要使用ContextThemeWrapper。但对于文本颜色、大小等,您可以使用setTextAppearance


2
太棒了。ContextThemeWrapper - 这就是我长期寻找的东西。 - Ayaz Alifov
这个非常好用。我已经寻找这个解决方案有一段时间了。 - jasonjwwilliams
setTextAppearance的那个版本已经被弃用了。你可以直接使用button.setTextAppearance(R.style.MyTextStyle)。 - Sasquatch
2
ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle); button = new Button(newContext); 在创建按钮时选择样式。如果我需要在创建按钮后更改样式怎么办? - blow

54
通常情况下,你无法通过编程来更改样式;但是,你可以使用主题或样式在XML布局中设置屏幕、部分布局或单个按钮的外观。然而,主题可以通过编程应用
此外,还有一种名为StateListDrawable的东西,它允许你为Button可能处于的每个状态(如聚焦、选定、按下、禁用等)定义不同的可绘制项。
例如,要使按钮在按下时更改颜色,你可以像这样定义一个名为res/drawable/my_button.xml的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>

您可以通过设置属性android:background="@drawable/my_button",将此选择器应用于Button


4
我的问题是我从 Web 服务中加载数据,这些数据描述了我的按钮信息。这些按钮需要根据它们所属的类别具有不同的样式。因此,我希望能够动态设置按钮样式。 - Lint_
3
你不能更改Android的style属性,但是你可以像任何其他视图一样以编程方式设置Button的背景,如果这足够满足你的需求的话。此外,由于Button继承自TextView,你可以更改文本属性。只需要查看这些项的API文档...http://developer.android.com/reference/android/view/View.html#setBackgroundResource%28int%29 - Christopher Orr
我刚想着要这么做,就在检查是否有新答案之前。非常感谢。 - Lint_
6
能否为一个按钮创建一种样式,定义文本大小、边距等,并将其适用于程序中的一个按钮?如果我想让六个按钮使用相同的样式,这是可能的吗? - Bear
我们可以膨胀哪些属性?我们能够膨胀边距、填充吗? - K Guru

16

您可以这样设置样式属性:

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"

    />

9
考虑到需要创建一个按钮,你的回答很好。如果能够展示如何对已有的按钮进行操作就更好了。 - Quality Catalyst
请参考cesards的答案。 - Kristy Welsh

15

是的,你可以在按钮中使用例如(for example)

Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);

6
这将设置背景,但样式可以指定不止背景。很多视图(包括按钮)似乎都有一个构造函数,该函数以样式ID作为参数。但是,我在使用时遇到了问题 - 按钮显示为没有边框或任何东西的文本。相反,我可以创建一个只包含一个带有指定样式的按钮的布局,然后填充该布局,再设置按钮文本等内容。 - spaaarky21

12

如果您正在使用支持库,您可以简单地使用以下方法

TextViewCompat.setTextAppearance(textView, R.style.AppTheme_TextStyle_ButtonDefault_Whatever);

对于TextView和Button,其余视图也有类似的类 :-)


你需要使用哪个R包才能获得这种样式? - htafoya

7

根据您想要修改的样式属性,您可能可以使用Paris库:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Paris.style(view).apply(R.style.YourStyle);

支持许多属性,例如背景、内边距、文本大小、文本颜色等。

免责声明:本人是该库的作者。


6
@Dayerman和@h_rules的回答是正确的。 为了举例说明,可以创建一个名为button_disabled.xml的xml文件并放在drawable文件夹中。
<?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>

4
@Pacerier:这个问题并没有明确说明使用的是XML还是Java样式,只是询问如何以编程方式设置样式。请问需要翻译什么语言? - Harvey

6

如果有人想要 Material 的答案,请参考这篇 Stack Overflow 帖子:Android 中使用 Material Design 和 AppCompat 给按钮上色

我使用了这篇答案的结合体,将我的按钮的默认文本颜色设置为白色:https://dev59.com/R18d5IYBdhLWcg3wt0EQ#32238489

然后,在此答案https://dev59.com/R18d5IYBdhLWcg3wt0EQ#34355919中找到通过编程方式设置背景颜色的方法。 代码如下:

ViewCompat.setBackgroundTintList(your_colored_button,
 ContextCompat.getColorStateList(getContext(),R.color.your_custom_color));

您可以使用Button或者AppCompat按钮作为your_colored_button - 我已经测试过这两种按钮类型,它们都可以使用上述代码。请注意:在Android 5.0以下的设备上,上述代码可能无法正常工作。您可以参考此文内的内容来添加对这些设备的支持:https://dev59.com/DYrda4cB1Zd3GeqPSu3F#30277424

具体操作步骤如下:

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

3
在运行时,您知道想要让按钮具有什么样式。因此,在布局文件夹中的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);

在创建fragment时,如果要重写onCreateView方法,其中container参数是与之关联的ViewGroup容器。

需要再添加两个按钮?您可以按照以下方式创建它们:

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

这就是如何动态地使用样式化按钮。

0
我使用holder模式为此创建了一个辅助接口。
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);

我发现这非常有帮助,因为它可以轻松地重复使用并保持代码的简洁和冗长,我建议仅将其用作本地变量,以便我们在设置所有样式后允许垃圾收集器完成其工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接