如何专业地组织按钮的样式?(SDK 26 +,min SDK 21)

Blc*_*knx 10 android android-layout android-fonts android-studio android-color

组织专业Android应用程序按钮样式的最佳实践是什么?假设更大的当代应用程序(SDK 26 +,min SDK 21).

这个问题是可以回答的,因为它们的来源Material Design和设置都Android Studio提供了足够的线索和预期专业用途模式的例子.当然,用户不仅限于这种模式,而是遵循它们,使应用程序与源代码一起发挥良好Material Design并提供最佳可维护性.

我找到了几个与按钮造型相关的成分.

  • @style/Widget.AppCompat.Button
  • @style/Widget.AppCompat.Button.Colored
  • @style/TextAppearance.AppCompat.Button
  • @style/TextAppearance.AppCompat.Widget.Button
  • @color/foreground_material_dark
  • ?colorAccent
  • ?textColorPrimary
  • ?android:colorForeground
  • ?textAppearanceButton

可能会有更多.

  • 所有成分如何相关?
  • 它们如何在专业主题中一起使用?

您可以查找来源.但是,即使知道所有细节也无法全面了解预期用途.这个问题要求绘制图片.

Blc*_*knx 5

(Min SDK 21)

一般的做法

粒度

我认为这是一种将文本外观与背景分开的细粒度方法.这提供了将不同背景与不同文本外观组合的选项.它还匹配由ButtonMaterial Design 提供的两种样式设置和组织.因此,它解决了如何使用它的问题.

价格是,每个都Button需要两个设置:

  • 按钮文字: android:textAppearance
  • 按钮背景: style

甚至降低这个价格styles_material.xml实际上采取了一种先进的方法.每个按钮都style包含默认文本外观.所以在正常情况下我只需要应用按钮style.

<Button
 style="?defaultButtonStyle"
Run Code Online (Sandbox Code Playgroud)

我按照这种模式进行自己的按钮样式,因为问题是针对预期用途.如果我想修改默认值,我会通过将其设置为添加替代文本外观android:textAppearance.

<Button
 style="?defaultButtonStyle"
 android:textAppearance="?smallButtonTextAppearance"
Run Code Online (Sandbox Code Playgroud)

对于非常特殊的按钮,我仍然可以在布局文件的级别上调整样式.这是最低级别的粒度.

提示:请注意,android:textAppearance优先级非常低.如果在主题(或样式)中的某处设置文本属性,则将覆盖所有内容中的相同属性android:textAppearance.它与CSS中的"!important"注释类似的力量一起工作,这可能是一个相当大的陷阱.

灵活的主题

没有

如果我不打算使用不同的主题,我可以直接将样式设置到布局中.

<Button
 style="@style/My.DefaultButtonStyle"
 android:textAppearance="@style/My.SmallButtonTextAppearance"
 ...
Run Code Online (Sandbox Code Playgroud)

如果想要能够交换主题,我首先将所有类型的样式映射到属性.然后我通过使用属性间接设置样式.这使我可以选择连接其他主题的其他样式,而无需重复布局.

<Button
 style="?defaultButtonStyle"
 android:textAppearance="?smallButtonTextAppearance"
 ...
Run Code Online (Sandbox Code Playgroud)

我个人不喜欢使用或混合给定的属性,而是完全定义我自己的一组属性来解决我的设计问题.所以洋葱的水平保持干净分离.

<?xml version="1.0" encoding="utf-8" ?>
<resources>

    <!-- button text appearance -->
    <attr name="defaultButtonTextAppearance" format="reference" />
    <attr name="smallButtonTextAppearance" format="reference" />

    <!-- button backgrounds -->
    <attr name="defaultButtonStyle" format="reference" />
    <attr name="alarmButtonStyle" format="reference" />
Run Code Online (Sandbox Code Playgroud)

在主题中,属性映射到主题特定样式.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="OtherTheme" parent="Theme.AppCompat">

        <!-- button text appearance -->
        <item name="defaultButtonTextAppearance">@style/OtherTheme.DefaultButtonTextAppearance</item>
        ...

        <!-- button backgrounds -->
        <item name="defaultButtonStyle">@style/OtherTheme.DefaultButtonStyle</item>
        ...
Run Code Online (Sandbox Code Playgroud)

按钮文字

如果我跟踪源的样式,我会找到一个文件data/res/values/styles_material.xml,它定义了所有按钮文本外观的根.TextAppearance.Material.Button继承自TextAppearance.Material,但按钮的四个相关属性被覆盖.

<style name="TextAppearance.Material">
    <item name="textColor">?attr/textColorPrimary</item>
    <item name="textColorHint">?attr/textColorHint</item>
    <item name="textColorHighlight">?attr/textColorHighlight</item>
    <item name="textColorLink">?attr/textColorLink</item>
    <item name="textSize">@dimen/text_size_body_1_material</item>
    <item name="fontFamily">@string/font_family_body_1_material</item>
    <item name="lineSpacingMultiplier">@dimen/text_line_spacing_multiplier_material</item>
</style>

<style name="TextAppearance.Material.Button">
    <item name="textSize">@dimen/text_size_button_material</item>
    <item name="fontFamily">@string/font_family_button_material</item>
    <item name="textAllCaps">true</item>
    <item name="textColor">?attr/textColorPrimary</item>
</style>
Run Code Online (Sandbox Code Playgroud)

它可以被我自己的继承样式覆盖.它还表明,在不使用继承的情况下编写自己的文本外观样式会很容易.

颜色

了解Androids文本色彩管理系统是他们最容易混淆的部分,因为系统功能非常强大.这里有一些启示.

在上面TextAppearance.Material.Button我发现文本颜色是由属性指定的?textColorPrimary.此属性再次基于该属性?android:colorForeground.

该属性?android:colorForeground是用于设置文本颜色的中央开关.默认情况下,所有文本颜色都是根据此设置计算的,也是按钮的颜色.例如,针对禁用按钮,正文文本等计算不同等级的灰色或不透明变体.

不要触摸几十个不同的地方,最好在这里设置常见的默认文本颜色,并尽可能依赖默认的Android颜色计算系统.详细调整一下.

<item name="android:colorForeground">@color/orange_700</item>
Run Code Online (Sandbox Code Playgroud)

此设置默认为@color/foreground_material_dark.

提示1:如果使用编辑设置Android Studio Theme Editor,则可能会更改值@color/foreground_material_dark.对我而言,改变材料暗的价值并不是一个好主意,因为它不是我的领域.更好地使用之前显示的参考.

提示2:Theme Editor是发现颜色属性系统关系的合适工具.当您通过实验尝试使用编辑器编辑不同的属性时,这种关系会显示出来.

如果我想要一个与整体文本颜色不同的按钮文本颜色,我将其设置在文本外观样式的级别上.

提示3:使用?android:colorForeground不能
在API 26下面开箱即用.有关解决方法,请参阅此处.

字体大小

文本大小是文本外观的因素,我通常希望在自定义文本外观样式中直接调整到我自己的设计.

<style name="My.SmallButtonTextAppearance" parent="My.DefaultButtonTextAppearance">
    <item name="android:textSize">16sp</item>
</style>
Run Code Online (Sandbox Code Playgroud)

TextAppearance.Material.Button从资源中获取文本大小默认值@dimen/text_size_button_material.没有与文本颜色设置系统相当的中央文本大小设置的系统.

全部大写

根样式TextAppearance.Material.Button集的全部大写true.甚至没有资源,价值取自.它只是硬编码.

<item name="textAllCaps">true</item>
Run Code Online (Sandbox Code Playgroud)

很有可能,我想false在我的自定义按钮样式中设置它.

<item name="android:textAllCaps">false</item>
Run Code Online (Sandbox Code Playgroud)

字体系列

与文本颜色一样,字体系列通常是具有共同中心性质的系统.如何管理按钮?根样式TextAppearance.Material.Button使用字符串资源@string/font_family_button_material.

<item name="fontFamily">@string/font_family_button_material</item>
Run Code Online (Sandbox Code Playgroud)

在文件data/res/values/donttranslate_material.xml中设置为sans-serif-medium,而在文件data/res/values-watch/donttranslate_material.xml中设置为sans-serif-condensed.

<string name="font_family_button_material">sans-serif-medium</string>
<string name="font_family_button_material">sans-serif-condensed</string>
Run Code Online (Sandbox Code Playgroud)

sans-serif设置将映射到字体设置中我选择的字体系列.通常sans-serif适用于按钮文字.为了进一步定制字体,我指出了这个问题.

按钮样式

除了为背景使用颜色之外,还可以应用xml资源文件来指定具有花式角,颜色渐变或其他图形效果的背景,还支持按钮的不同状态的不同背景.

这部分受到我的设计的强烈影响.我通常会使用自己的背景.

另一方面,在材料设计中有一个丰富的预定义按钮背景资源文件系统.我想在这里给出一个简短的概述,但这超出了我的技能,看起来很大,值得一个自己的话题.

style为背景不应该包含的设置width,height或者margins,因为这是属于到周围的布局.另一方面padding属于背景style.

材料设计的按钮样式

在文件中,data/res/values/styles_material.xml我找到了可以继承的九种按钮样式.如果我自己编写,不应忘记设置默认文本外观.

根元素是Widget.Material.Button.它设置为默认文本外观?textAppearanceButton.因此,设置此属性是一个选项,可直接使用材质设计按钮样式而不继承,但具有自定义的默认文本外观.

<!-- Bordered ink button -->
<style name="Widget.Material.Button">
    <item name="background">@drawable/btn_default_material</item>
    <item name="textAppearance">?attr/textAppearanceButton</item>
    <item name="minHeight">48dip</item>
    <item name="minWidth">88dip</item>
    <item name="stateListAnimator">@anim/button_state_list_anim_material</item>
    <item name="focusable">true</item>
    <item name="clickable">true</item>
    <item name="gravity">center_vertical|center_horizontal</item>
</style>
Run Code Online (Sandbox Code Playgroud)

使用该属性?colorAccent来设置颜色Widget.AppCompat.Button.Colored.见Android Studio Theme Editor.见@drawable/btn_colored_material.

请注意,默认文本外观会Widget.AppCompat.Button.Colored有所不同,并且不会由可自定义的属性设置.

<!-- Colored bordered ink button -->
<style name="Widget.Material.Button.Colored">
    <item name="background">@drawable/btn_colored_material</item>
    <item name="textAppearance">@style/TextAppearance.Material.Widget.Button.Colored</item>
</style>

<!-- Small bordered ink button -->
<style name="Widget.Material.Button.Small">
    <item name="minHeight">48dip</item>
    <item name="minWidth">48dip</item>
</style>

<!-- Borderless ink button -->
<style name="Widget.Material.Button.Borderless">
    <item name="background">@drawable/btn_borderless_material</item>
    <item name="stateListAnimator">@null</item>
</style>
Run Code Online (Sandbox Code Playgroud)

请注意,默认文本外观会Widget.Material.Button.Borderless.Colored有所不同,并且不会由可自定义的属性设置.

<!-- Colored borderless ink button -->
<style name="Widget.Material.Button.Borderless.Colored">
    <item name="textAppearance">@style/TextAppearance.Material.Widget.Button.Borderless.Colored</item>
</style>
Run Code Online (Sandbox Code Playgroud)

请注意,Widget.Material.Button.ButtonBar.AlertDialog继承自Widget.Material.Button.Borderless.Colored.应用默认文本外观的相同限制.

<!-- Alert dialog button bar button -->
<style name="Widget.Material.Button.ButtonBar.AlertDialog" parent="Widget.Material.Button.Borderless.Colored">
    <item name="minWidth">64dp</item>
    <item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
</style>

<!-- Small borderless ink button -->
<style name="Widget.Material.Button.Borderless.Small">
    <item name="minHeight">48dip</item>
    <item name="minWidth">48dip</item>
</style>

<style name="Widget.Material.Button.Inset">
    <item name="background">@drawable/button_inset</item>
</style>

<style name="Widget.Material.Button.Toggle">
    <item name="background">@drawable/btn_toggle_material</item>
    <item name="textOn">@string/capital_on</item>
    <item name="textOff">@string/capital_off</item>
</style>
Run Code Online (Sandbox Code Playgroud)

我个人会使用这个预定义的按钮样式之一或继承我自己的Widget.Material.Button.这使得继承的层次结构保持低水平,并且代码易于阅读.如果我从另一个样式继承,它最多可以节省三行代码,而代码变得不易维护.

这个经验法则有例外.例如@drawable/btn_borderless_material是私人的.所以我要么继承,Widget.Material.Button.Colored要么创建该文件的副本.

附录

相关问题

属性

颜色

字体


归档时间:

查看次数:

376 次

最近记录:

7 年,5 月 前