如何探索造型的机器人 [英] How to explore styling in android

查看:130
本文介绍了如何探索造型的机器人的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我的主题,在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆