Android自定义View获取自定义属性
2017-04-18 23:25
337 查看
首先扯点别的:今晚回家做了一个鱼香肉丝,刚学的,出锅以后,才想起没有放豆瓣酱,也是没谁了。不过吃起来还行,吃了三块煎饼。
今天记录一下自定义View的构造函数的使用,以及如何获取自定义属性。
先看一下自定义View 的构造函数
通常我们会在一个参数构造函数里面调用两个参数的构造函数,然后在两个参数的构造函数里面调用三个参数的构造函数。然后就可以在三个参数的构造函数中获取自定义属性。
当我们在代码中使用new 对象的方式创建一个自定View的时候,只能使用一个参数的构造函数。
当我们在布局文件里面使用自定义View的时候,调用的是两个参数的构造函数。三个参数的构造函数是我们在主动调用的。像上面的代码,无论是在代码中new一个CustomView实例,还是在布局文件中使用,最终都会调用三个参数的构造函数,所以我们可以在三个参数的构造函数里面,做一些初始化操作和获取自定义属性。
在上面我们声明了一个
然后在
自定义属性中 name是自定义属性的名字,format是指自定义属性的取值。
format的取值类如下所示:
boolean 表示attr取值为true或者false
color 表示attr取值是颜色类型,例如#ff3344,或者是一个指向color的资源id,例如R.color.colorAccent.
dimension 表示 attr 取值是尺寸类型,例如例如取值16sp、16dp,也可以是一个指向dimen的资源id,例如R.dimen.dp_16
float 表示attr取值是整形或者浮点型
fraction 表示 attr取值是百分数类型,只能以%结尾,例如30%
integer 表示attr取值是整型
string 表示attr取值是String类型,或者一个指向String的资源id,例如R.string.testString
reference 表示attr取值只能是一个指向资源的id。
enum 表示attr取值只能是枚举类型。
flag 表示attr取值是flag类型。
注意:
refrence , 表示attr取值只能是一个指向资源的id。
例如我们把上面的改成
那么在布局文件中
app:color=”@color/colorAccent”取值只能是引用的形式,而不能使用app:color=”#ff3344”这种方式。
flag类型的定义方式要注意
这个自定义View的实现功能就是为了显示一段文字,先把全部的代码贴出来。
我们在initCustomAttrs方法中,获取自定义属性。R.styleable.CustomView就是我们在attrs.xml文件中声明的。
obtainStyledAttributes 方法接受两个参数,第一个参数set表示属性值的集合,如果我们是在代码中通过new的方式实例化一个CustomView,那么这个set是null,如果我们在布局文件中使用CustomView,那么set不为null,set里面包括我们在xml布局文件中为CustomView指定的属性。第二个参数attrs表示我们想获取那些属性值。上面的写法就表示我们想获取View的在R.styleable.CustomView中定义的属性值。
在布局文件中使用
我们在布局文件中给CustomView指定了三个自定义属性:color,font,text。效果如下。
然后我们在代码中使用new的方式来添加一个CustomView。先把布局文件中的CustomView去掉。
然后我们在代码中添加一个CustomView.
效果图
我们再回到
我们在我们在res/valeus/styles.xml文件中定义了如下style。
然后在布局文件中使用这个CustomView_Red_Style
效果如下
我们通过给CustomView设置style的方式,也可以使用CustomView的自定义属性,但是这种方式的优先级要比直接给CustomView指定自定义属性的优先级低。在上面的代码中我们在布局文件中直接给CustomView指定了app:text=”hello world”,同时,我们在style文件中也指定了
obtainStyledAttributes有一个四个参数的构造函数
关于第三个参数 defStyleAttr。这个参数表示的是我们在attrs.xml中定义的某个属性的ID,当Android在AttributeSet和style属性所定义的style资源中都没有找到XML属性值时,就会尝试查找当前theme中属性为defStyleAttr的值,如果其值是一个style资源,那么Android就会去该style资源中再去查找XML属性值。举例说明
我们在布局文件中不给CustomView指定app:color属性。
把CustomView_Red_Style的颜色属性也去掉。
那么这时候我们就获取不到CustomView_color这个值,所以customColor 就会使用默认的颜色BLUE。
接下来,我们使用defStyleAttr。
首先在attrs.xml文件中定义一个属性
然后在styles.xml文件中定义一个style
然后修改Activity的主题。
然后使用四个参数的obtainStyledAttributes方法,第三个参数指定为R.attr.CustomView_Theme_Style
运行效果。可以看到我们从在Theme中指定的CustomView_Theme_Style所指向的CustomView_Green_Style中获取到了color这个自定义属性的值,所以显示的文字为绿色。
obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)方法的第四个参数 defStyleRes。与defStyleAttr类似,defStyleRes是前面几项的替补值,defStyleRes的优先级最低。与defStyleAttr不同的是,defStyleRes本身直接表示一个style资源,而theme要通过属性defStyleAttr间接找到style资源。
在styles.xml文件中定义style。
修改自定义属性获取方式,把第三个参数指定为0.
运行效果图。
注意只有第三个参数defStyleAttr为0或者该属性在theme中找不到时,才会使用第四个参数defStyleRes。如果第三个参数defStyleAttr不为0,但是theme的defStyleAttr所对应的属性值中的style没有定义任何XML属性值,那么第四个参数也不会defStyleRes被使用。
我们现在再修改一下。第三个参数不为0
再修改一下Activity的Theme
发现运行效果结果文字还是黄色的。图就不贴了,证实了只有第三个参数defStyleAttr为0或者该属性在theme中找不到时,才会使用第四个参数defStyleRes。
下面我们再修改一下Theme
然后修改CustomView_Green_Style,去掉color和text属性。
运行结果发现,文字的颜色是默认的BLUE,证实了如果第三个参数defStyleAttr不为0,但是theme的defStyleAttr所对应的属性值中的style没有定义任何XML属性值,那么第四个参数也不会defStyleRes被使用。
结尾:没想到写了这么长,是时候睡觉了。
参考链接
【1】http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0806/4575.html
【2】http://blog.csdn.net/iispring/article/details/50708044
【3】http://blog.csdn.net/wzy_1988/article/details/49619773
今天记录一下自定义View的构造函数的使用,以及如何获取自定义属性。
先看一下自定义View 的构造函数
public class CustomView extends View { private static final String TAG = "CustomView"; public CustomView(Context context) { this(context, null); } public CustomView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //在这里做一些初始化操作和获取自定义属性 } }
通常我们会在一个参数构造函数里面调用两个参数的构造函数,然后在两个参数的构造函数里面调用三个参数的构造函数。然后就可以在三个参数的构造函数中获取自定义属性。
当我们在代码中使用new 对象的方式创建一个自定View的时候,只能使用一个参数的构造函数。
private CustomView customView=new CustomView(context);
当我们在布局文件里面使用自定义View的时候,调用的是两个参数的构造函数。三个参数的构造函数是我们在主动调用的。像上面的代码,无论是在代码中new一个CustomView实例,还是在布局文件中使用,最终都会调用三个参数的构造函数,所以我们可以在三个参数的构造函数里面,做一些初始化操作和获取自定义属性。
自定义View属性
我们通常的做法是在res/values目录下新建一个attrs.xml文件。<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CustomView"> <attr name="color" format="color"/> <attr name="font" format="dimension"/> <attr name="text" format="string"/> <attr name="type" format="enum"> <enum name="common" value="1"/> <enum name="material" value="2"/> </attr> <attr name="flag"> <flag name="flag1" value="0x01"/> <flag name="flag2" value="0x02"/> <flag name="flag4" value="0x04"/> </attr> </declare-styleable> </resources>
在上面我们声明了一个
<declare-styleable>,name属性一般设为我们自定义View的名字即可。
然后在
<declare-styleable>内部定义了5个属性。
<attr name="color" format="color"/>
自定义属性中 name是自定义属性的名字,format是指自定义属性的取值。
format的取值类如下所示:
boolean 表示attr取值为true或者false
color 表示attr取值是颜色类型,例如#ff3344,或者是一个指向color的资源id,例如R.color.colorAccent.
dimension 表示 attr 取值是尺寸类型,例如例如取值16sp、16dp,也可以是一个指向dimen的资源id,例如R.dimen.dp_16
float 表示attr取值是整形或者浮点型
fraction 表示 attr取值是百分数类型,只能以%结尾,例如30%
integer 表示attr取值是整型
string 表示attr取值是String类型,或者一个指向String的资源id,例如R.string.testString
reference 表示attr取值只能是一个指向资源的id。
enum 表示attr取值只能是枚举类型。
flag 表示attr取值是flag类型。
注意:
refrence , 表示attr取值只能是一个指向资源的id。
<attr name="color" format="color"/>
例如我们把上面的改成
<attr name="color" format="refrence"/>
那么在布局文件中
<com.hm.viewdemo.widget.CustomView android:layout_width="match_parent" android:layout_height="100dp" app:color="@color/colorAccent" />
app:color=”@color/colorAccent”取值只能是引用的形式,而不能使用app:color=”#ff3344”这种方式。
flag类型的定义方式要注意
<!--flag属性,不能指定format格式--> <attr name="flag"> <flag name="flag1" value="0x01"/> <flag name="flag2" value="0x02"/> <flag name="flag4" value="0x04"/> </attr>
这个自定义View的实现功能就是为了显示一段文字,先把全部的代码贴出来。
public class CustomView extends View { private static final String TAG = "CustomView"; //文字内容 private String customText; //文字的颜色 private int customColor; //文字的字体大小 private int fontSize; //画笔 private TextPaint textPaint; public CustomView(Context context) { this(context, null); } public CustomView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initCustomAttrs(context, attrs); } /** 获取自定义属性 */ private void initCustomAttrs(Context context, AttributeSet attrs) { //获取自定义属性。 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView); //获取字体大小,默认大小是16dp fontSize = (int) ta.getDimension(R.styleable.CustomView_font, 16); //获取文字内容 customText = ta.getString(R.styleable.CustomView_text); //获取文字颜色,默认颜色是BLUE customColor = ta.getColor(R.styleable.CustomView_color, Color.BLUE); ta.recycle(); textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); textPaint.setColor(customColor); textPaint.setTextSize(fontSize); } @Override protected void onDraw(Canvas canvas) { Log.e(TAG, "onDraw: custom text=" + customText); canvas.drawText(customText, 0, customText.length(), 100, 100, textPaint); } public void setCustomText(String customText) { this.customText = customText; } public void setCustomColor(int customColor) { this.customColor = customColor; textPaint.setColor(customColor); } public void setFontSize(int fontSize) { this.fontSize = fontSize; textPaint.setTextSize(fontSize); } }
我们在initCustomAttrs方法中,获取自定义属性。R.styleable.CustomView就是我们在attrs.xml文件中声明的。
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
obtainStyledAttributes 方法接受两个参数,第一个参数set表示属性值的集合,如果我们是在代码中通过new的方式实例化一个CustomView,那么这个set是null,如果我们在布局文件中使用CustomView,那么set不为null,set里面包括我们在xml布局文件中为CustomView指定的属性。第二个参数attrs表示我们想获取那些属性值。上面的写法就表示我们想获取View的在R.styleable.CustomView中定义的属性值。
在布局文件中使用
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/rl_custome_view" android:layout_width="match_parent" android:layout_height="match_parent" > <com.hm.viewdemo.widget.CustomView android:id="@+id/custom_view" android:layout_width="match_parent" android:layout_height="100dp" android:layout_centerInParent="true" app:color="@color/colorAccent" app:font="16sp" app:text="hello world"/> </RelativeLayout>
我们在布局文件中给CustomView指定了三个自定义属性:color,font,text。效果如下。
然后我们在代码中使用new的方式来添加一个CustomView。先把布局文件中的CustomView去掉。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/rl_custome_view" android:layout_width="match_parent" android:layout_height="match_parent" > </RelativeLayout>
然后我们在代码中添加一个CustomView.
private CustomView customView; private RelativeLayout rlCustomeView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custome_view); rlCustomeView = (RelativeLayout) findViewById(R.id.rl_custome_view); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); //new 一个CustomView customView = new CustomView(this); customView.setCustomText("在代码中添加"); customView.setCustomColor(Color.GREEN); customView.setFontSize(60); //添加view rlCustomeView.addView(customView, params); } }
效果图
我们再回到
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
我们在我们在res/valeus/styles.xml文件中定义了如下style。
<style name="CustomView_Red_Style"> <!--颜色指定为红色--> <item name="color">#FF0000</item> <item name="text">hello red style</item> </style>
然后在布局文件中使用这个CustomView_Red_Style
<com.hm.viewdemo.widget.CustomView android:id="@+id/custom_view" android:layout_width="match_parent" android:layout_height="100dp" android:layout_centerInParent="true" app:font="16sp" style="@style/CustomView_Red_Style" app:text="hello world"/>
效果如下
我们通过给CustomView设置style的方式,也可以使用CustomView的自定义属性,但是这种方式的优先级要比直接给CustomView指定自定义属性的优先级低。在上面的代码中我们在布局文件中直接给CustomView指定了app:text=”hello world”,同时,我们在style文件中也指定了
<item name="text">hello red style</item>但是结果还是显示的在布局文件中直接指定的文字。
obtainStyledAttributes有一个四个参数的构造函数
public final TypedArray obtainStyledAttributes( AttributeSet set, @StyleableRes int[] attrs, @AttrRes int defStyleAttr,@StyleRes int defStyleRes)
关于第三个参数 defStyleAttr。这个参数表示的是我们在attrs.xml中定义的某个属性的ID,当Android在AttributeSet和style属性所定义的style资源中都没有找到XML属性值时,就会尝试查找当前theme中属性为defStyleAttr的值,如果其值是一个style资源,那么Android就会去该style资源中再去查找XML属性值。举例说明
我们在布局文件中不给CustomView指定app:color属性。
<com.hm.viewdemo.widget.CustomView android:id="@+id/custom_view" android:layout_width="match_parent" android:layout_height="100dp" android:layout_centerInParent="true" app:font="16sp" style="@style/CustomView_Red_Style" app:text="hello world"/>
把CustomView_Red_Style的颜色属性也去掉。
<style name="CustomView_Red_Style"> <item name="text">hello red style</item> </style>
那么这时候我们就获取不到CustomView_color这个值,所以customColor 就会使用默认的颜色BLUE。
customColor = ta.getColor(R.styleable.CustomView_color, Color.BLUE);
接下来,我们使用defStyleAttr。
首先在attrs.xml文件中定义一个属性
<attr name="CustomView_Theme_Style" format="reference"/>
然后在styles.xml文件中定义一个style
<style name="CustomView_Green_Style"> <!--指定为绿色--> <item name="color">#00FF00</item> <item name="text">hello green style</item> </style>
然后修改Activity的主题。
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <!--指定CustomView_Theme_Style属性--> <item name="CustomView_Theme_Style">@style/CustomView_Green_Style</item> </style>
然后使用四个参数的obtainStyledAttributes方法,第三个参数指定为R.attr.CustomView_Theme_Style
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView,R.attr.CustomView_Theme_Style,0);
运行效果。可以看到我们从在Theme中指定的CustomView_Theme_Style所指向的CustomView_Green_Style中获取到了color这个自定义属性的值,所以显示的文字为绿色。
obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)方法的第四个参数 defStyleRes。与defStyleAttr类似,defStyleRes是前面几项的替补值,defStyleRes的优先级最低。与defStyleAttr不同的是,defStyleRes本身直接表示一个style资源,而theme要通过属性defStyleAttr间接找到style资源。
在styles.xml文件中定义style。
<style name="CustomView_Yellow_Style"> <!--定义成黄色--> <item name="color">#FFFF00</item> <item name="text">hello yellow style</item> </style>
修改自定义属性获取方式,把第三个参数指定为0.
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView,0,R.style.CustomView_Yellow_Style);
运行效果图。
注意只有第三个参数defStyleAttr为0或者该属性在theme中找不到时,才会使用第四个参数defStyleRes。如果第三个参数defStyleAttr不为0,但是theme的defStyleAttr所对应的属性值中的style没有定义任何XML属性值,那么第四个参数也不会defStyleRes被使用。
我们现在再修改一下。第三个参数不为0
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView,R.attr.CustomView_Theme_Style,R.style.CustomView_Yellow_Style);
再修改一下Activity的Theme
//去掉这一行。 <item name="CustomView_Theme_Style">@style/CustomView_Green_Style</item>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
发现运行效果结果文字还是黄色的。图就不贴了,证实了只有第三个参数defStyleAttr为0或者该属性在theme中找不到时,才会使用第四个参数defStyleRes。
下面我们再修改一下Theme
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="CustomView_Theme_Style">@style/CustomView_Green_Style</item> </style>
然后修改CustomView_Green_Style,去掉color和text属性。
<style name="CustomView_Green_Style"> </style>
运行结果发现,文字的颜色是默认的BLUE,证实了如果第三个参数defStyleAttr不为0,但是theme的defStyleAttr所对应的属性值中的style没有定义任何XML属性值,那么第四个参数也不会defStyleRes被使用。
结尾:没想到写了这么长,是时候睡觉了。
参考链接
【1】http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0806/4575.html
【2】http://blog.csdn.net/iispring/article/details/50708044
【3】http://blog.csdn.net/wzy_1988/article/details/49619773
相关文章推荐
- android自定义控件(7)-获取自定义ImageView的src属性
- android自定义View构造方法以及获取自定义属性详解
- Android基础教程——在TextView中显示Html 自定义标签,获取标签属性
- Android之探究viewGroup自定义子属性参数的获取流程
- android 自定义View的属性
- Android 自定义View并添加属性
- (android)自定义View自定义属性
- Android 自定义view 基本实现方式和自定义属性
- Android 自定义View修炼-自定义View-带百分比进度的圆形进度条(采用自定义属性)
- Android自定义View以及layout属性全攻略
- Android三种Webview获取Javascript返回值/属性方式
- Android 获取View的位置属性
- Android 自定义View并添加属性(转)
- android在自定义View的xml中设置自定义的成员属性
- Android UI设计之<四>自定义TextView属性,实现带边框效果的TextView
- Android自定义View以及layout属性全攻略
- Android 自定义View自定义属性的声明
- android 自定义View属性
- android自定义view属性
- 【android自定义控件】自定义View属性