上周看过这样一段代码
TypedArray sa = obtainStyledAttributes(null,
com.android.internal.R.styleable.PreferenceActivity,
com.android.internal.R.attr.preferenceActivityStyle,
0);
发现特别神奇,之前都是用前两个参数在自定义View中进行应用,发现还有四个参数的写法,于是就查看了一下Android系统控件里面,是如何应用的。
系统如何自定义属性
这里就拿TextView举例吧:
public TextView(Context context) {
this(context, null);
}
public TextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.textViewStyle);
}
public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
@SuppressWarnings("deprecation")
public TextView(
Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
我介绍的几个目录你可能一开始看的时候感觉没啥关联,但是你往后看就知道了,学习技术要有耐心。
1. TextView自定义的属性所在目录
/***/***/SDK/platforms/android-22/data/res/values/attrs.xml
<declare-styleable name="TextView">
<!-- Determines the minimum type that getText() will return.
The default is "normal".
Note that EditText and LogTextBox always return Editable,
even if you specify something less powerful here. -->
<attr name="bufferType">
<!-- Can return any CharSequence, possibly a
Spanned one if the source text was Spanned. -->
<enum name="normal" value="0" />
<!-- Can only return Spannable. -->
<enum name="spannable" value="1" />
<!-- Can only return Spannable and Editable. -->
<enum name="editable" value="2" />
</attr>
<!-- Text to display. -->
<attr name="text" format="string" localization="suggested" />
<!-- Hint text to display when the text is empty. -->
<attr name="hint" format="string" />
<!-- Text color. -->
<attr name="textColor" />
<!-- Color of the text selection highlight. -->
<attr name="textColorHighlight" />
<!-- Color of the hint text. -->
<attr name="textColorHint" />
<!-- Base text color, typeface, size, and style. -->
<attr name="textAppearance" />
<!-- Size of the text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp). -->
<attr name="textSize" />
<!-- Sets the horizontal scaling factor for the text. -->
<attr name="textScaleX" format="float" />
<!-- Typeface (normal, sans, serif, monospace) for the text. -->
<attr name="typeface" />
<!-- Style (bold, italic, bolditalic) for the text. -->
<attr name="textStyle" />
<!-- Font family (named by string) for the text. -->
<attr name="fontFamily" />
<!-- Text color for links. -->
<attr name="textColorLink" />
<!-- Makes the cursor visible (the default) or invisible. -->
<attr name="cursorVisible" format="boolean" />
<!-- Makes the be at most this many lines tall.
When used on an editable text, the <code>inputType</code> attribute's value must be
combined with the <code>textMultiLine</code> flag for the maxLines attribute to apply. -->
<attr name="maxLines" format="integer" min="0" />
<!-- Makes the TextView be at most this many pixels tall. -->
<attr name="maxHeight" />
<!-- Makes the TextView be exactly this many lines tall. -->
<attr name="lines" format="integer" min="0" />
<!-- Makes the TextView be exactly this many pixels tall.
You could get the same effect by specifying this number in the
layout parameters. -->
<attr name="height" format="dimension" />
<!-- Makes the TextView be at least this many lines tall.
When used on an editable text, the <code>inputType</code> attribute's value must be
combined with the <code>textMultiLine</code> flag for the minLines attribute to apply. -->
<attr name="minLines" format="integer" min="0" />
<!-- Makes the TextView be at least this many pixels tall. -->
<attr name="minHeight" />
<!-- Makes the TextView be at most this many ems wide. -->
这里跟我们平时自定义属性是完全一样的。
2. textViewStyle
<attr name="textViewStyle" format="reference" />
这个参数的定义也同样是在attrs.xml里面进行定义的,你可以自己搜索下
3. themes
/***/***/SDK/platforms/android-22/data/res/values/themes.xml
这个是系统的theme文件,一般我们自己定义一个theme的时候都会采用继承,有两种写法。
a:通过parent继承
类似这种
<style name="Theme.AppCompat.Light.DarkActionBar" parent="Base.Theme.AppCompat.Light.DarkActionBar"/>
前面是子类名字,后面是父类名字
b:通过 父类.子类的方式
<style name="Theme.Light">
Theme是父类,Light是自己定义的子类。
在manifest文件中我的applicationandroid:theme="@style/AppTheme"
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="MyViewStyle">@style/buzhidao</item>
</style>
最后的结构是这样的:
Theme
–Theme.Light
—android:Theme.Holo.Light
—-Platform.AppCompat.Light
—–Base.V7.Theme.AppCompat.Light
——Base.Theme.AppCompat.Light
——-Base.Theme.AppCompat.Light.DarkActionBar
——–Theme.AppCompat.Light.DarkActionBar
———AppTheme
而在themes.xml这个文件的跟节点就是<style name="Theme">
在它的里面定义了
<item name="textViewStyle">@style/Widget.TextView</item>
也就是跟刚才attrs.xml里面定义的textViewStyle的name一样,但是其值指向的styles.xml文件。
4. styles.xml目录
/***/***/SDK/platforms/android-22/data/res/values/styles.xml
<style name="Widget.TextView">
<item name="textAppearance">?attr/textAppearanceSmall</item>
<item name="textSelectHandleLeft">?attr/textSelectHandleLeft</item>
<item name="textSelectHandleRight">?attr/textSelectHandleRight</item>
<item name="textSelectHandle">?attr/textSelectHandle</item>
<item name="textEditPasteWindowLayout">?attr/textEditPasteWindowLayout</item>
<item name="textEditNoPasteWindowLayout">?attr/textEditNoPasteWindowLayout</item>
<item name="textEditSidePasteWindowLayout">?attr/textEditSidePasteWindowLayout</item>
<item name="textEditSideNoPasteWindowLayout">?attr/textEditSideNoPasteWindowLayout</item>
<item name="textEditSuggestionItemLayout">?attr/textEditSuggestionItemLayout</item>
<item name="textCursorDrawable">?attr/textCursorDrawable</item>
</style>
这里面主要是给自定义的属性设置默认的属性值。
通过上面我们就已经了解了系统自定义属性的步骤,然后下面我们自己模仿系统去写一个
例子
a:先定义attr
<resources>
<declare-styleable name="yaoyan">
<attr name="jingzhuiteng" format="boolean"></attr>
<attr name="msg" format="string"></attr>
<attr name="shuaibushuai" format="dimension"></attr>
</declare-styleable>
</resources>
b:在attr中声明View的style名字
<attr name="MyViewStyle" format="reference"></attr>
a和b结合之后
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="yaoyan">
<attr name="jingzhuiteng" format="boolean"></attr>
<attr name="msg" format="string"></attr>
<attr name="shuaibushuai" format="dimension"></attr>
</declare-styleable>
<attr name="MyViewStyle" format="reference"></attr>
</resources>
c:在子类AppTheme(根据你项目实际情况)中添加你自己声明的style
<item name="MyViewStyle">@style/buzhidao</item>
d:为你自己定义的style设置默认值
<style name="buzhidao">
<item name="jingzhuiteng">true</item>
<item name="msg">我在广东已经嫖到失联</item>
<item name="shuaibushuai">@dimen/title_textview_size</item>
<item name="android:background">#000000</item>
</style>
c和d结合之后
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="MyViewStyle">@style/buzhidao</item>
</style>
<style name="buzhidao">
<item name="jingzhuiteng">true</item>
<item name="msg">我在广东已经嫖到失联</item>
<item name="shuaibushuai">@dimen/title_textview_size</item>
<item name="android:background">#000000</item>
</style>
</resources>
自定义View
public class MyView extends View {
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, R.attr.MyViewStyle);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.yaoyan, defStyleAttr, defStyleRes);
String string = a.getString(R.styleable.yaoyan_msg);
System.out.println("string = " + string);
float dimension = a.getDimension(R.styleable.yaoyan_shuaibushuai, 1);
System.out.println("dimension = " + dimension);
}
}
结果
05-06 23:04:38.955 3082-3082/com.example.customattr I/System.out: string = 我在广东已经嫖到失联
dimension = 30.0
当然了,你也可以这么写
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="yaoyan">
<attr name="jingzhuiteng" format="boolean"></attr>
<attr name="msg" format="string"></attr>
<attr name="shuaibushuai" format="dimension"></attr>
</declare-styleable>
//删掉一行
</resources>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
//删掉一行
</style>
<style name="buzhidao">
<item name="jingzhuiteng">true</item>
<item name="msg">我在广东已经嫖到失联</item>
<item name="shuaibushuai">@dimen/title_textview_size</item>
<item name="android:background">#000000</item>
</style>
</resources>
都删掉
public class MyView extends View {
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
//注意对比
this(context, attrs, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
//注意对比
this(context, attrs, defStyleAttr, R.style.buzhidao);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.yaoyan, defStyleAttr, defStyleRes);
String string = a.getString(R.styleable.yaoyan_msg);
System.out.println("string = " + string);
float dimension = a.getDimension(R.styleable.yaoyan_shuaibushuai, 1);
System.out.println("dimension = " + dimension);
} .
}
第三个参数是默认的style属性,可以写0,代表没有,第四个是默认的style资源,这样改完和之前运行一样。
05-06 23:13:28.167 6732-6732/com.example.customattr I/System.out: string 改后= 我在广东已经嫖到失联
dimension 改后= 30.0
微信公众号
QQ群:365473065
代码地址