UPDATE:正如注释中指出的,'Widget.AppCompat.EditText'是AppCompatEditText子类的正确父样式。 就我而言,真正的问题是我忘记在主题中为控件的默认样式属性分配值,因此我们的控件没有任何样式可用作默认值。
但是,这个问题仍然可以使用一个答案,即在子类化标准控件时定义自己的默认样式时,如何正确标识要用作父样式的样式。因此,我也重命名了它的标题。
因此,我对此保持开放,希望有人可以回答这个问题,因为它将帮助任何希望做类似事情的人。
我们正在尝试为整个应用中使用的所有 AppCompatEditText 控件定义通用的外观。 因此,我们不必在每次使用时手动应用 'style' 属性,而是尝试用我们自己的样式替换默认样式。
替换默认样式实际上是简单的部分。 不知道的是知道我们样式的父样式应该设置为什么,这样我们仍然拥有原始样式的所有方面,我们没有明确地用我们中的样式覆盖这些方面。
挖掘AppCompatEditText的源代码,它显示了要存储在R.attr.editTextStyle
中的默认样式,但我不确定现在在哪里查看其中存储的值。
实验也没有让我们取得任何进展。 无论我们到目前为止尝试了什么,我们都会完全失去默认外观。 没有下划线,没有背景,没有填充,什么都没有。只是我们设置的值,这意味着它不会选取父样式。
我们尝试了以下方法,但没有成功...
<style name="ZinEditText" parent="android:Widget.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">@dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">@dimen/defaultLineSpacing</item>
</style>
<style name="ZinEditText" parent="Widget.AppCompat.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">@dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">@dimen/defaultLineSpacing</item>
</style>
<style name="ZinEditText" parent="Base.V7.Widget.AppCompat.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">@dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">@dimen/defaultLineSpacing</item>
</style>
<style name="ZinEditText" parent="Widget.Holo.EditText">
<item name="zinTypeface">light</item>
<item name="android:textSize">@dimen/defaultTextSize</item>
<item name="android:lineSpacingMultiplier">@dimen/defaultLineSpacing</item>
</style>
正如我所说,以上似乎都不起作用。
那么如何找到要使用的实际父样式呢?
为了解决眼前的问题,AppCompatEditText
的默认样式是Widget.AppCompat.EditText
。您展示的第二个示例是正确的:
<style name="ZinEditText" parent="Widget.AppCompat.EditText">
...
这需要设置为应用主题中的editTextStyle
。
<style name="AppTheme" parent="@style/Theme.AppCompat">
<item name="editTextStyle">@style/ZinEditText</item>
...
据我所知,找到这些默认样式和属性在任何地方都没有很好的记录。样式和主题的官方文档只是将人们引导到框架和支持包的各个R.attr
页面,以"发现"可用的内容。但是,对于大多数允许默认样式的View
,通常可靠的方法是检查源代码。
一个View
子类通常会实现至少三个构造函数:一个只接受Context
;一个接受Context
和AttributeSet
;另一个接受Context
、AttributeSet
和defStyleAttr
int
,一个默认的样式属性。此属性就是我们正在寻找的。它通常有一个合理的名称,如editTextStyle
、textViewStyle
、checkboxStyle
等。如果您已经知道该名称,则可以跳过检查View
类以获取它。
在链接其构造函数的View
中,此属性通常位于从双参数构造函数调用三参数构造函数中。在AppCompatEditText
中,我们可以看到此属性的名称是editTextStyle
。
public AppCompatEditText(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.editTextStyle);
}
获得属性的名称后,我们转到View
所在的平台或支持包的res/values/
目录。默认值将位于应用父主题的相关themes*.xml
文件中。
对于平台主题,有一个基本themes.xml
,还有一些其他主题版本,例如Holo和Material。
对于支持库View
,这些主题文件将位于特定于包的res/values/
目录下,默认属性值可能在themes.xml
或themes_base.xml
中。
在 v7 appcompat 中,我们应用程序的确切父主题可能在v7/appcompat/res/values/themes.xml
中,尽管大多数主题只是基本主题的直接别名;即,它们不会覆盖任何父主题的属性值。AppCompatEditText
的默认值实际上是v7/appcompat/res/values/themes_base.xml
.不同的主题(常规和灯光(有单独的条目,但它们都是相同的。
<item name="editTextStyle">@style/Widget.AppCompat.EditText</item>
这足以确定使用哪种样式作为我们的父样式,但是如果我们想查看样式细节,我们可以参考v7/appcompat/res/values/styles.xml
,我们在其中找到该样式的父级:
<style name="Widget.AppCompat.EditText" parent="Base.Widget.AppCompat.EditText"/>
这导致我们v7/appcompat/res/values/styles_base.xml
:
<style name="Base.Widget.AppCompat.EditText" parent="Base.V7.Widget.AppCompat.EditText" />
<style name="Base.V7.Widget.AppCompat.EditText" parent="android:Widget.EditText">
<item name="android:background">?attr/editTextBackground</item>
<item name="android:textColor">?attr/editTextColor</item>
<item name="android:textAppearance">?android:attr/textAppearanceMediumInverse</item>
</style>