如何探索造型的机器人 [英] How to explore styling in android
问题描述
我想我的主题,在Android应用程序。然而,每个插件本身就是一个excrutiating痛苦:我有搜索主题化特定插件,然后创建一个风格,希望从同一个样式的Widget使用派生
I'm trying to theme my app in Android. However, each widget is an excrutiating pain in itself: I have to search for theming that particular widget and then create a style that hopefully derives from same style that widget uses.
当然,关于主题化的特定部件并不总是包含有关基本样式,只是在特定的颜色信息的答案。
Of course, answers about theming a particular widget don't always contain info about base style, just the particular colors.
因此,而不是接受鱼吃,你能不能教我钓鱼呢?
So, instead of accepting fish to eat, can you teach me to fish instead?
我如何跨preT那些 ObtainStyledAttributes()
的部件构造和提取的款式可供调用?我如何递归呢?
How do I interpret those ObtainStyledAttributes()
calls in widget constructors and extract styles from that? How do I recurse that?
在特定的,可你通过 AlertDialog
走在我按钮颜色?什么样式定义棒棒糖平键+青色文字的颜色?我如何得到这种风格,如果我从AlertDialog源头抓起,并ObtainStyledAttributes打电话?
In particular, can you walk me through AlertDialog
button color? What style defines lollipop flat button + teal text color? How do I get to that style if I start from AlertDialog source and ObtainStyledAttributes call?
推荐答案
我觉得这造型是关于通过框架sherlocking自己的方式。在什么的(几乎总是)来自小部件的实现。在其中的,我觉得是所有的地方。我会尽我所能,通过特定用例来解释这个过程 - AlertDialog的按钮(S)
I find that styling is about sherlocking your way through the framework. The what (almost always) comes from the widget's implementation. The where, I find is all over the place. I will try my best to explain the process through your particular use-case - AlertDialog's button(s).
出发
您已经有这个想通了:我们开始与小部件的源$ C $ C。我们是专门试图寻找 - 在AlertDialog按钮得到他们的文字颜色。所以,我们开始寻找在那里这些按钮来的。难道他们被在运行时明确创建?或者,他们在一个XML布局中定义,这是被夸大?
You already have this figured out: we start with the widget's source code. We are specifically trying to find - where AlertDialog buttons get their text-color. So, we start with looking at where these buttons come from. Are they being explicitly created at runtime? Or are they defined in an xml layout, which is being inflated?
在源$ C $ C,我们发现, mAlert
处理按钮选项除其他事项外:
In source code, we find that mAlert
handles the button options among other things:
public void setButton(int whichButton, CharSequence text, Message msg) {
mAlert.setButton(whichButton, text, null, msg);
}
mAlert
是 AlertController
的实例。在它的构造,我们发现属性 alertDialogStyle
定义XML布局:
mAlert
is an instance of AlertController
. In its constructor, we find that the attribute alertDialogStyle
defines the xml layout:
TypedArray a = context.obtainStyledAttributes(null,
com.android.internal.R.styleable.AlertDialog,
com.android.internal.R.attr.alertDialogStyle, 0);
mAlertDialogLayout =
a.getResourceId(
com.android.internal.R.styleable.AlertDialog_layout,
com.android.internal.R.layout.alert_dialog);
因此,布局要考虑的是 alert_dialog.xml
- [sdk_folder] /平台/ Android为21 /数据/ RES /布局/alert_dialog.xml
:
的布局XML是相当长的。这是有关部分:
The layout xml is quite long. This is the relevant part:
<LinearLayout>
....
....
<LinearLayout android:id="@+id/buttonPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="54dip"
android:orientation="vertical" >
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="4dip"
android:paddingStart="2dip"
android:paddingEnd="2dip"
android:measureWithLargestChild="true">
<LinearLayout android:id="@+id/leftSpacer"
android:layout_weight="0.25"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone" />
<Button android:id="@+id/button1"
android:layout_width="0dip"
android:layout_gravity="start"
android:layout_weight="1"
style="?android:attr/buttonBarButtonStyle"
android:maxLines="2"
android:layout_height="wrap_content" />
<Button android:id="@+id/button3"
android:layout_width="0dip"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
style="?android:attr/buttonBarButtonStyle"
android:maxLines="2"
android:layout_height="wrap_content" />
<Button android:id="@+id/button2"
android:layout_width="0dip"
android:layout_gravity="end"
android:layout_weight="1"
style="?android:attr/buttonBarButtonStyle"
android:maxLines="2"
android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/rightSpacer"
android:layout_width="0dip"
android:layout_weight="0.25"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone" />
</LinearLayout>
我们现在知道的按钮获得由属性持有的风格 buttonBarButtonStyle
。
We now know that the buttons get the style held by attribute buttonBarButtonStyle
.
头部到 [sdk_folder] /platforms/android-21/data/res/values/themes.material.xml
并搜索 buttonBarButtonStyle
:
<!-- Defined under `<style name="Theme.Material">` -->
<item name="buttonBarButtonStyle">@style/Widget.Material.Button.ButtonBar.AlertDialog</item>
<!-- Defined under `<style name="Theme.Material.Light">` -->
<item name="buttonBarButtonStyle">@style/Widget.Material.Light.Button.ButtonBar.AlertDialog</item>
根据你的活动的父主题是, buttonBarButtonStyle
将参考这两种风格之一。现在,让我们假设你的活动主题延伸 Theme.Material
。我们来看看 @风格/ Widget.Material.Button.ButtonBar.AlertDialog
:
Depending on what your activity's parent theme is, buttonBarButtonStyle
will refer to one of these two styles. For now, let's assume your activity's theme extends Theme.Material
. We'll look at @style/Widget.Material.Button.ButtonBar.AlertDialog
:
打开 [sdk_folder] /platforms/android-21/data/res/values/styles_material.xml
并搜索 Widget.Material.Button .ButtonBar.AlertDialog
:
<!-- 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="maxLines">2</item>
<item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
</style>
好。但是,这些值不帮助我们确定该按钮的文本颜色。我们应该看看旁边的父样式 - Widget.Material.Button.Borderless.Colored
:
<!-- Colored borderless ink button -->
<style name="Widget.Material.Button.Borderless.Colored">
<item name="textColor">?attr/colorAccent</item>
<item name="stateListAnimator">@anim/disabled_anim_material</item>
</style>
最后,我们找到了文字颜色
- 它由 ATTR / colorAccent
提供的<$ C $初始化C> Theme.Material :
At last, we find the textColor
- and its supplied by attr/colorAccent
initialized in Theme.Material
:
<item name="colorAccent">@color/accent_material_dark</item>
有关 Theme.Material.Light
, colorAccent
定义为:
<item name="colorAccent">@color/accent_material_light</item>
浏览 [sdk_folder] /platforms/android-21/data/res/values/colors_material.xml
并找到这些颜色:
<color name="accent_material_dark">@color/material_deep_teal_200</color>
<color name="accent_material_light">@color/material_deep_teal_500</color>
<color name="material_deep_teal_200">#ff80cbc4</color>
<color name="material_deep_teal_500">#ff009688</color>
这是AlertDialog的屏幕截图和相应的文字颜色:
Screenshot of an AlertDialog and the corresponding text-color:
快捷方式
有时,它更容易阅读的颜色值(如上图),并寻找它使用 AndroidXRef 。这种方法不会在你的情况,因为#80cbc4
是有益的将只有人士指出,其强调色。你仍然必须找到 Widget.Material.Button.Borderless.Colored
和属性比分扳成 buttonBarButtonStyle
。
Sometimes, its easier to read the color value (as in the picture above) and search for it using AndroidXRef. This approach would not have been useful in your case since #80cbc4
would have only pointed out that its the accent color. You would still have to locate Widget.Material.Button.Borderless.Colored
and tie it with attribute buttonBarButtonStyle
.
更改按钮的文字颜色
在理想情况下,我们应该创建一个扩展的样式 Widget.Material.Button.ButtonBar.AlertDialog
,覆盖安卓文字颜色
里面,并将其分配给属性 buttonBarButtonStyle
。但是,这是不行的 - 你的项目将无法编译。这是因为 Widget.Material.Button.ButtonBar.AlertDialog
是一个非公开的风格,因此不能扩展。您可以通过检查链接证实了这一点。
Ideally, we should create a style that extends Widget.Material.Button.ButtonBar.AlertDialog
, override android:textColor
inside it, and assign it to attribute buttonBarButtonStyle
. But, this won't work - your project won't compile. This is because Widget.Material.Button.ButtonBar.AlertDialog
is a non-public style and hence cannot be extended. You can confirm this by checking Link.
我们会做一个最好的事情 - 延长 Widget.Material.Button.ButtonBar.AlertDialog
的父样式 - Widget.Material。 Button.Borderless.Colored
这是公开的。
We'll do the next best thing - extend the parent style of Widget.Material.Button.ButtonBar.AlertDialog
- Widget.Material.Button.Borderless.Colored
which is public.
<style name="CusButtonBarButtonStyle"
parent="@android:style/Widget.Material.Button.Borderless.Colored">
<!-- Yellow -->
<item name="android:textColor">#ffffff00</item>
<!-- From Widget.Material.Button.ButtonBar.AlertDialog -->
<item name="android:minWidth">64dp</item>
<item name="android:maxLines">2</item>
<item name="android:minHeight">@dimen/alert_dialog_button_bar_height</item>
</style>
请注意,我们覆盖后增加3个以上的项目安卓文字颜色
。这些都是从非公有制风格的 Widget.Material.Button.ButtonBar.AlertDialog
。既然我们不能直接扩展它,我们必须将其定义的项目。注:扪的值(S)将不得不抬起头来并转移到相应的 RES /值(-xxxxx)/dimens.xml
文件(收费)项目。
Note that we add 3 more items after overriding android:textColor
. These are from non-public style Widget.Material.Button.ButtonBar.AlertDialog
. Since we cannot extend it directly, we must include the items it defines. Note: the dimen value(s) will have to be looked up and transferred to appropriate res/values(-xxxxx)/dimens.xml
files(s) in your project.
样式 CusButtonBarButtonStyle
将被分配到属性 buttonBarButtonStyle
。但问题是,如何将一个AlertDialog知道吗?从源头code:
The style CusButtonBarButtonStyle
will be assigned to attribute buttonBarButtonStyle
. But the question is, how will an AlertDialog know of this? From the source code:
protected AlertDialog(Context context) {
this(context, resolveDialogTheme(context, 0), true);
}
传递 0
作为第二个参数 resolveDialogTheme(背景下,INT)
将结束在其他
子句:
Passing 0
as the second argument for resolveDialogTheme(Context, int)
will end up in the else
clause:
static int resolveDialogTheme(Context context, int resid) {
if (resid == THEME_TRADITIONAL) {
....
} else {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(
com.android.internal.R.attr.alertDialogTheme,
outValue, true);
return outValue.resourceId;
}
}
我们现在知道,这个主题是由 alertDialogTheme
属性举行。接下来,我们看看 alertDialogTheme
点。此属性的值将取决于您的活动的父主题。浏览到您的SDK文件夹,找到值/ themes_material.xml
里面的android-21。搜索 alertDialogTheme
。结果:
We now know that the theme is held by alertDialogTheme
attribute. Next, we look at what alertDialogTheme
points to. The value of this attribute will depend on your activity's parent theme. Browse to your sdk folder and find the values/themes_material.xml
inside android-21. Search for alertDialogTheme
. Results:
<!-- Defined under `<style name="Theme.Material">` -->
<item name="alertDialogTheme">@style/Theme.Material.Dialog.Alert</item>
<!-- Defined under `<style name="Theme.Material.Light">` -->
<item name="alertDialogTheme">@style/Theme.Material.Light.Dialog.Alert</item>
<!-- Defined under `<style name="Theme.Material.Settings">` -->
<item name="alertDialogTheme">@style/Theme.Material.Settings.Dialog.Alert</item>
那么,根据你的活动的基本主题是, alertDialogTheme
将持有这三个值中的一个。为了让AlertDialog知道 CusButtonBarButtonStyle
,我们需要覆盖在我们的应用程序的主题属性 alertDialogTheme
。比方说,我们使用 Theme.Material
作为基本主题。
So, based on what your activity's base theme is, alertDialogTheme
will hold one of these 3 values. To let AlertDialog know of CusButtonBarButtonStyle
, we need to override attribute alertDialogTheme
in our app's theme. Say, we're using Theme.Material
as the base theme.
<style name="AppTheme" parent="android:Theme.Material">
<item name="android:alertDialogTheme">@style/CusAlertDialogTheme</item>
</style>
从以上,我们知道, alertDialogTheme
指向 Theme.Material.Dialog.Alert
的当你应用程序的基本主题是 Theme.Material
的。因此, CusAlertDialogTheme
应 Theme.Material.Dialog.Alert
作为它的父:
From above, we know that alertDialogTheme
points to Theme.Material.Dialog.Alert
when your app's base theme is Theme.Material
. So, CusAlertDialogTheme
should have Theme.Material.Dialog.Alert
as its parent:
<style name="CusAlertDialogTheme"
parent="android:Theme.Material.Dialog.Alert">
<item name="android:buttonBarButtonStyle">@style/CusButtonBarButtonStyle</item>
</style>
结果:
因此,而不是接受鱼吃,你能不能教我的鱼 呢?
So, instead of accepting fish to eat, can you teach me to fish instead?
在最起码,我希望已经解释那里的鱼。
In the very least, I hope to have explained where the fish are.
P.S。我知道我已经发布一个庞大的。
P.S. I realize I have posted a mammoth.
这篇关于如何探索造型的机器人的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!