在哪里放置 XML 样式
Where to put XML styles
问题 1
我希望所有 Toolbar
看起来都一样,而不是在所有这些中设置样式,
所以我虽然会为它设置应用程序主题。我希望他们都拥有的东西之一是 colorControlNormal
属性。这些是我的尝试:
代码示例 1:
<resources>
<style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="toolbarStyle">@style/MyTheme.ToolbarStyle</item>
</style>
<style name="MyTheme.ToolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
<item name="colorControlNormal">@color/toolbarColorControlNormal</item>
</style>
</resources>
代码示例 2:
<resources>
<style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorControlNormal">@color/toolbarColorControlNormal</item>
</style>
</resources>
在代码示例1中,我尝试为Toolbar
属性创建自定义样式,并将其设置为主题,但没有成功。
在代码示例 2 中,我全局设置了该属性并起作用了。但是,也会影响其他组件,因此无效。
- 为什么 代码示例 1 无法正常工作?
问题 2
我需要更改所有 TabLayout
的 tabTextColor
和 tabSelectedTextColor
属性,所以我尝试了这个:
代码示例 3:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:tabWidgetStyle">@style/TabsStyle</item>
</style>
<style name="TabsStyle" parent="Widget.Design.TabLayout">
<item name="tabTextColor">@color/tabTextColor</item>
<item name="tabSelectedTextColor">@color/tabSelectedTextColor</item>
</style>
</resources>
但它不起作用,我让它工作的唯一方法是在 XML:
中手动设置它们
<android.support.design.widget.TabLayout
[...]
android:background="?android:attr/colorPrimary"
app:tabTextColor="@color/tabTextColor"
app:tabSelectedTextColor="@color/tabSelectedTextColor" />
- 为什么 代码示例 3 不工作?
最后,我会对任何对好的风格和主题的引用投赞成票guides/books。我真的需要在这方面改进。
提前致谢。
全局指定Toolbar
中返回箭头的颜色
这并不像它应该的那样简单,但请尝试以下操作:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- style the back arrow -->
<item name="toolbarNavigationButtonStyle">@style/NavButtonStyle</item>
</style>
<style name="NavButtonStyle" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
<item name="android:tint">#FF0000</item>
</style>
android:tint
会改变返回箭头的颜色。
一般情况下,默认工具栏样式由属性toolbarStyle
设置。在下面的XML中,设置为@style/MyToolbarStyle
。
MyToolbarStyle
定义了将用于应用程序内所有工具栏的三个属性。这是一个的样子:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="toolbarStyle">@style/MyToolbarStyle</item>
<item name="titleTextColor">@android:color/holo_red_light</item>
</style>
<style name="MyToolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
<item name="titleTextColor">@android:color/white</item>
<item name="subtitleTextColor">@android:color/holo_green_light</item>
<item name="android:background">@color/vermillion</item>
</style>
</resources>
如您所见,MyToolbarStyle
设置了三个属性的值。不幸的是,这种方法不适用于所有属性,例如 colorControlNormal
,如果在主题中指定,将更改后退箭头的颜色。
关于TabLayout
的问题:
TabLayout
全局定义属性没有很好的解决方案。您可以执行 this 之类的操作并仅覆盖 Widget.Design.TabLayout
,但您必须重新创建在那里定义的所有属性,并且这些属性可能会根据 运行 的版本而改变。这可行,但维护起来可能是个问题。我认为这不是一个好的解决方案。
另一个解决方案是创建您自己的自定义 TabLayout
。这将非常简单,只需将 tabTextAppearance
定义为 TabLayout
的全局默认属性。整个自定义布局将如下所示:
public class MyTabLayout extends TabLayout {
public MyTabLayout(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.tabTextAppearance);
}
}
将对 TabLayout
的所有引用替换为 MyTabLayout
后,您将能够在 styles.xml
中执行以下操作:
<style name="AppTheme" parent="BaseAppTheme">
<item name="tabTextAppearance">@style/MyTabStyle</item>
</style>
<style name="MyTabStyle" parent="Widget.Design.TabLayout">
<item name="tabTextColor">#FF0000</item>
<item name="tabSelectedTextColor">#00FF00</item>
</style>
这将使选项卡文本颜色为红色和绿色,但它们可以是您选择的颜色。您现在可以在 XML 中声明 TabLayout
并应用默认样式,而无需显式指定 style/theme.
根本问题是 TabLayout
的 CTOR 不使用 defStyleResource
,它定义了应用于主题中定义的视图的默认样式,而 tabWidgetStyle
不是它..(参见 this。)自定义布局 MyTabLayout
绕过了这个问题。然而,这确实提出了一个问题,即是否存在未使用 defStyleResource
的原因,也许我们正在深入研究我们最好避免的石楠补丁。
这些方法确实有效,但我还没有完全测试过。您将不得不决定是按照此处描述的方式更好,还是简单地逐个视图地定义样式。
如果有人有一个标准的、Android 批准的全局指定 TabLayout
属性的方法,我将很高兴听到。
问题 1
主题和风格之间的区别很微妙,事情比它们应该的更混乱,因为你定义了两者其中使用 <style>
标签。但即使它们都使用 <style>
标签,它们的行为也不同。
视图的 主题 中指定的属性适用于该视图及其所有子视图。在视图的 style 中指定的属性仅适用于该视图。此外,还有一些称为 theme attributes 的属性,只有当它们是主题的一部分时才有效。 colorControlNormal
为主题属性;在样式中设置它不会有任何效果。
代码示例 1 不起作用,因为您的 <item name="colorControlNormal">
元素是在样式而非主题中定义的。
代码示例 2 改变了一切,因为现在 colorControlNormal
在您的 app 的 主题中,所以它适用于你的应用关心它。
不幸的是,我认为没有办法简单地为您的应用程序中的每个 Toolbar
指定一个主题。您将不得不满足以下条件之一:
1) 使用android:theme
属性
为此,您需要创建如下样式:
<style name="MyToolbarTheme">
<item name="colorControlNormal">@color/toolbarColorControlNormal</item>
</style>
然后,在每个 <Toolbar>
标签上,添加
android:theme="@style/MyToolbarTheme"
2) 创建 Toolbar
的自定义子 class
同样,您需要像上面那样的样式。然后你会像这样创建一个 class:
public class MyToolbar extends Toolbar {
public MyToolbar(Context context, AttributeSet attrs) {
super(wrapContext(context), attrs);
}
private static Context wrapContext(Context context) {
return new ContextThemeWrapper(context, R.style.MyToolbarTheme);
}
}
并像这样在布局文件中使用它:
<com.example.Whosebug.MyToolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
这是通过获取 Context
工具栏实例并将其主题更改为自定义工具栏主题来实现的。由于此(包装的)上下文仅用于创建您的自定义工具栏,因此不会影响您应用中的其他视图。
对于它的价值,这就是我在我的应用程序中所做的。
问题 2
在这里,为什么更简单一些:android:tabWidgetStyle
是TabWidget
的默认样式,而不是TabLayout
。事实上,我不知道 TabLayout
.
有任何定义的默认样式
同样,您有两个选择。您可以创建样式并将其应用于每个 <TabLayout>
标签,或者您可以创建自定义子 class 并使用它代替 TabLayout
:
public class MyTabLayout extends TabLayout {
public MyTabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
int normalColor = ContextCompat.getColor(context, R.color.tabTextColor);
int selectedColor = ContextCompat.getColor(context, R.color.tabSelectedTextColor);
setTabTextColors(normalColor, selectedColor);
}
}
进一步阅读
这是我在学习这些东西时阅读的一些material:
https://developer.android.com/guide/topics/ui/look-and-feel/themes.html
https://medium.com/google-developers/theming-with-appcompat-1a292b754b35
https://www.androiddesignpatterns.com/2016/08/contextcompat-getcolor-getdrawable.html
右键点击res文件夹,选择新建-->Android资源文件,为新文件设置同名"styles",在Available qualifiers:选择最后一项"Version" 最后设置 "Platform API level" 21.
问题 1
我希望所有 Toolbar
看起来都一样,而不是在所有这些中设置样式,
所以我虽然会为它设置应用程序主题。我希望他们都拥有的东西之一是 colorControlNormal
属性。这些是我的尝试:
代码示例 1:
<resources>
<style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="toolbarStyle">@style/MyTheme.ToolbarStyle</item>
</style>
<style name="MyTheme.ToolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
<item name="colorControlNormal">@color/toolbarColorControlNormal</item>
</style>
</resources>
代码示例 2:
<resources>
<style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorControlNormal">@color/toolbarColorControlNormal</item>
</style>
</resources>
在代码示例1中,我尝试为Toolbar
属性创建自定义样式,并将其设置为主题,但没有成功。
在代码示例 2 中,我全局设置了该属性并起作用了。但是,也会影响其他组件,因此无效。
- 为什么 代码示例 1 无法正常工作?
问题 2
我需要更改所有 TabLayout
的 tabTextColor
和 tabSelectedTextColor
属性,所以我尝试了这个:
代码示例 3:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:tabWidgetStyle">@style/TabsStyle</item>
</style>
<style name="TabsStyle" parent="Widget.Design.TabLayout">
<item name="tabTextColor">@color/tabTextColor</item>
<item name="tabSelectedTextColor">@color/tabSelectedTextColor</item>
</style>
</resources>
但它不起作用,我让它工作的唯一方法是在 XML:
中手动设置它们<android.support.design.widget.TabLayout
[...]
android:background="?android:attr/colorPrimary"
app:tabTextColor="@color/tabTextColor"
app:tabSelectedTextColor="@color/tabSelectedTextColor" />
- 为什么 代码示例 3 不工作?
最后,我会对任何对好的风格和主题的引用投赞成票guides/books。我真的需要在这方面改进。
提前致谢。
全局指定Toolbar
这并不像它应该的那样简单,但请尝试以下操作:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- style the back arrow -->
<item name="toolbarNavigationButtonStyle">@style/NavButtonStyle</item>
</style>
<style name="NavButtonStyle" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
<item name="android:tint">#FF0000</item>
</style>
android:tint
会改变返回箭头的颜色。
一般情况下,默认工具栏样式由属性toolbarStyle
设置。在下面的XML中,设置为@style/MyToolbarStyle
。
MyToolbarStyle
定义了将用于应用程序内所有工具栏的三个属性。这是一个的样子:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="toolbarStyle">@style/MyToolbarStyle</item>
<item name="titleTextColor">@android:color/holo_red_light</item>
</style>
<style name="MyToolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
<item name="titleTextColor">@android:color/white</item>
<item name="subtitleTextColor">@android:color/holo_green_light</item>
<item name="android:background">@color/vermillion</item>
</style>
</resources>
如您所见,MyToolbarStyle
设置了三个属性的值。不幸的是,这种方法不适用于所有属性,例如 colorControlNormal
,如果在主题中指定,将更改后退箭头的颜色。
关于TabLayout
的问题:
TabLayout
全局定义属性没有很好的解决方案。您可以执行 this 之类的操作并仅覆盖 Widget.Design.TabLayout
,但您必须重新创建在那里定义的所有属性,并且这些属性可能会根据 运行 的版本而改变。这可行,但维护起来可能是个问题。我认为这不是一个好的解决方案。
另一个解决方案是创建您自己的自定义 TabLayout
。这将非常简单,只需将 tabTextAppearance
定义为 TabLayout
的全局默认属性。整个自定义布局将如下所示:
public class MyTabLayout extends TabLayout {
public MyTabLayout(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.tabTextAppearance);
}
}
将对 TabLayout
的所有引用替换为 MyTabLayout
后,您将能够在 styles.xml
中执行以下操作:
<style name="AppTheme" parent="BaseAppTheme">
<item name="tabTextAppearance">@style/MyTabStyle</item>
</style>
<style name="MyTabStyle" parent="Widget.Design.TabLayout">
<item name="tabTextColor">#FF0000</item>
<item name="tabSelectedTextColor">#00FF00</item>
</style>
这将使选项卡文本颜色为红色和绿色,但它们可以是您选择的颜色。您现在可以在 XML 中声明 TabLayout
并应用默认样式,而无需显式指定 style/theme.
根本问题是 TabLayout
的 CTOR 不使用 defStyleResource
,它定义了应用于主题中定义的视图的默认样式,而 tabWidgetStyle
不是它..(参见 this。)自定义布局 MyTabLayout
绕过了这个问题。然而,这确实提出了一个问题,即是否存在未使用 defStyleResource
的原因,也许我们正在深入研究我们最好避免的石楠补丁。
这些方法确实有效,但我还没有完全测试过。您将不得不决定是按照此处描述的方式更好,还是简单地逐个视图地定义样式。
如果有人有一个标准的、Android 批准的全局指定 TabLayout
属性的方法,我将很高兴听到。
问题 1
主题和风格之间的区别很微妙,事情比它们应该的更混乱,因为你定义了两者其中使用 <style>
标签。但即使它们都使用 <style>
标签,它们的行为也不同。
视图的 主题 中指定的属性适用于该视图及其所有子视图。在视图的 style 中指定的属性仅适用于该视图。此外,还有一些称为 theme attributes 的属性,只有当它们是主题的一部分时才有效。 colorControlNormal
为主题属性;在样式中设置它不会有任何效果。
代码示例 1 不起作用,因为您的 <item name="colorControlNormal">
元素是在样式而非主题中定义的。
代码示例 2 改变了一切,因为现在 colorControlNormal
在您的 app 的 主题中,所以它适用于你的应用关心它。
不幸的是,我认为没有办法简单地为您的应用程序中的每个 Toolbar
指定一个主题。您将不得不满足以下条件之一:
1) 使用android:theme
属性
为此,您需要创建如下样式:
<style name="MyToolbarTheme">
<item name="colorControlNormal">@color/toolbarColorControlNormal</item>
</style>
然后,在每个 <Toolbar>
标签上,添加
android:theme="@style/MyToolbarTheme"
2) 创建 Toolbar
同样,您需要像上面那样的样式。然后你会像这样创建一个 class:
public class MyToolbar extends Toolbar {
public MyToolbar(Context context, AttributeSet attrs) {
super(wrapContext(context), attrs);
}
private static Context wrapContext(Context context) {
return new ContextThemeWrapper(context, R.style.MyToolbarTheme);
}
}
并像这样在布局文件中使用它:
<com.example.Whosebug.MyToolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
这是通过获取 Context
工具栏实例并将其主题更改为自定义工具栏主题来实现的。由于此(包装的)上下文仅用于创建您的自定义工具栏,因此不会影响您应用中的其他视图。
对于它的价值,这就是我在我的应用程序中所做的。
问题 2
在这里,为什么更简单一些:android:tabWidgetStyle
是TabWidget
的默认样式,而不是TabLayout
。事实上,我不知道 TabLayout
.
同样,您有两个选择。您可以创建样式并将其应用于每个 <TabLayout>
标签,或者您可以创建自定义子 class 并使用它代替 TabLayout
:
public class MyTabLayout extends TabLayout {
public MyTabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
int normalColor = ContextCompat.getColor(context, R.color.tabTextColor);
int selectedColor = ContextCompat.getColor(context, R.color.tabSelectedTextColor);
setTabTextColors(normalColor, selectedColor);
}
}
进一步阅读
这是我在学习这些东西时阅读的一些material:
https://developer.android.com/guide/topics/ui/look-and-feel/themes.html
https://medium.com/google-developers/theming-with-appcompat-1a292b754b35
https://www.androiddesignpatterns.com/2016/08/contextcompat-getcolor-getdrawable.html
右键点击res文件夹,选择新建-->Android资源文件,为新文件设置同名"styles",在Available qualifiers:选择最后一项"Version" 最后设置 "Platform API level" 21.