android自定义属性详解_android自定义组合控件

Android (84) 2023-09-16 13:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说android自定义属性详解_android自定义组合控件,希望能够帮助你!!!。

分享职场生活、职场攻略、领导同事相处技巧和创业资源

01

对于一个Android开发者来说,自定义控件是一项重要的技能,然而对于大部分人而言,感觉自定义控件并不是那么好对付。在工作过程中难免需要遇到一些特效需要通过自定义控件来实现,如果对自定义不是很熟练,开发起来会比较吃力。

在学习自定义控件,不知你有没有这样的疑问:

  • 自定义属性是怎样工作的?
  • 为什么要使用自定义属性?

今天我们一起来探讨自定义属性。

要使用自定义属性首先我们得有这个自定义属性。

常见的TextView控件的Android:text属性是怎么来的呢,我们来一起看一下系统的自定义属性源码,系统定义的所有属性我们可以\sdk\platforms\Android-xx\data\res\values目录下找到attrs.xml这个文件,这里只找几个很常见的view属性。

<declare-styleable name="View">

<attr name="id" format="reference" />

<attr name="background" format="reference|color" />

<attr name="padding" format="dimension" />

...

</declare-styleable>

<declare-styleable name="TextView">

<attr name="text" format="string" localization="suggested" />

<attr name="hint" format="string" />

<attr name="textColor" />

<attr name="textColorHighlight" />

<attr name="textColorHint" />

...

</declare-styleable>

<declare-styleable name="ViewGroup_Layout">

<attr name="layout_width" format="dimension">

<enum name="fill_parent" value="-1" />

<enum name="match_parent" value="-1" />

<enum name="wrap_content" value="-2" />

</attr>

<attr name="layout_height" format="dimension">

<enum name="fill_parent" value="-1" />

<enum name="match_parent" value="-1" />

<enum name="wrap_content" value="-2" />

</attr>

</declare-styleable>

<declare-styleable name="LinearLayout_Layout">

<attr name="layout_width" />

<attr name="layout_height" />

<attr name="layout_weight" format="float" />

<attr name="layout_gravity" />

</declare-styleable>

<declare-styleable name="RelativeLayout_Layout">

<attr name="layout_centerInParent" format="boolean" />

<attr name="layout_centerHorizontal" format="boolean" />

<attr name="layout_centerVertical" format="boolean" />

...

</declare-styleable>

android自定义属性详解_android自定义组合控件_https://bianchenghao6.com/blog_Android_第1张

我们知道我控件都是继承自View的,View类具有的属性我们继承它的子类也拥有了,而我们父view类却不能使用子View的特有的属性,充分的体现了我们的语言的多态性。

聪明的你应该发现上面都有一个共同点,就是 里面还有一系列子标签,而这些子标签就表示这是其属性。

但并不是每个控件都能使用所有属性,譬如LinearLayout有layout_weight属性,而RelativeLayout却没有,因为layout_weight是为LinearLayout的LayoutParams定义的。

细心的你,应该注意到,attr标签后面有的带了format属性,有的没有。带有format的就是自定义属性,没有带format的就是在使用已有的属性,name的值就是属性的名称,format则是限定当前定义的属性能接受什么值。

我们知道,系统定义的属性一般引用是android:XX引用,如果我们现在要定义一个text属性。

常规定义方式:

<resources>

<declare-styleable name="CustomerTextView">

<attr name=“text" format="string" />

</declare-styleable>

</resources>

或者引用系统已经定义:

<resources>

<declare-styleable name="CustomerTextView">

<attr name=“android:text"/>

</declare-styleable>

</resources>

format一共支持11种类型

1、 reference

属性定义:

<declare-styleable name = "名称">

<attr name = "background" format = "reference" />

</declare-styleable>

属性使用:

<ImageView android:background = "@drawable/ImageViewId"/>

2、color

属性定义:

<attr name = "textColor" format = "color" />

属性使用:

<TextView android:textColor = "#00FF00" />

3、boolean

属性定义:

<attr name = "focusable" format = "boolean" />

属性使用:

<Button android:focusable = "true"/>

4、dimension

属性定义:

<attr name = "layout_width" format = "dimension" />

属性使用:

<Button android:layout_width = "42dip"/>

5、float

属性定义:

<attr name = "fromAlpha" format = "float" />

属性使用:

<alpha android:fromAlpha = "1.0"/>

6、integer

属性定义:

<attr name = "framesCount" format="integer" />

属性使用:

<animated-rotate android:framesCount = "12"/>

7、string

属性定义:

<attr name = "text" format = "string" />

属性使用:

<TextView android:text = "我是文本"/>

8、fraction

属性定义:

<attr name = "pivotX" format = "fraction" />

属性使用:

<rotate android:pivotX = "200%"/>

9、 enum:枚举值

属性定义:

<declare-styleable name="名称">

<attr name="orientation">

<enum name="horizontal" value="0" />

<enum name="vertical" value="1" />

</attr>

</declare-styleable>

属性使用:

注意:当使用枚举属性的话不能在一个属性中同时使用两个值

10、 flag:位或运算

属性定义:

<declare-styleable name="名称">

<attr name="gravity">

<flag name="top" value="0x30" />

<flag name="bottom" value="0x50" />

<flag name="left" value="0x03" />

<flag name="right" value="0x05" />

<flag name="center_vertical" value="0x10" />

...

</attr>

</declare-styleable>

属性使用:

位运算符在使用的时候可以使用多个属性

11、混合类型:属性定义时可以指定多种类型值

属性定义:

<declare-styleable name = "名称">

<attr name = "background" format = "reference|color" />

</declare-styleable>

属性使用:

<ImageView android:background = "@drawable/图片ID" />

android自定义属性详解_android自定义组合控件_https://bianchenghao6.com/blog_Android_第2张

或者:

下面我们通过一个案例来加深理解。

首先在attrs文件中添加我们的自定义属性

<declare-styleable name="CircleSplashView">

<attr name="solid_circle_radius" format="dimension" />

<attr name="solid_circle_color" format="color" />

<attr name="empty_circle_color" format="color" />

<attr name="empty_circle_radius" format="dimension" />

<attr name="circle_text_size" format="dimension" />

<attr name="circle_text_color" format="color" />

<attr name="circle_draw_orientation" format="enum">

<enum name="clockwise" value="1" />

<enum name="anticlockwise" value="2" />

</attr>

<attr name="time_length" format="integer" />

</declare-styleable>

这样我们就可以在布局文件中添加我们的自定义属性,这里要注意一下要引入我们的自定义空间,一般来说有两种:xmlns:circletimerview="http://schemas.android.com/apk/res-auto”,res-auto表示自动查找,还有一种写法xmlns:circletimerview="http://schemas.android.com/apk/com.book.aikaifa.tallybook",其中com.book.aikaifa.tallybook 为我们自身应用程序的包名。

<com.book.aikaifa.tallybook.view.CircleSplashView

android:id="@+id/circle_timer"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

circletimerview:circle_draw_orientation="clockwise"

circletimerview:circle_text_color="@android:color/white"

circletimerview:circle_text_size="16sp"

circletimerview:empty_circle_color="#3F51B5"

circletimerview:empty_circle_radius="22dp"

circletimerview:solid_circle_color="@color/colorPrimaryDark"

circletimerview:solid_circle_radius="20dp"

circletimerview:time_length="5" />

另外,我们可以在构造方法中获取我们的自定义属性

/**

* 自定义属性

*/

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleSplashView);

mSolidCircleColor = typedArray.getColor(R.styleable.CircleSplashView_solid_circle_color, defaultSolidCircleColor);

mSolidCircleRadius = typedArray.getDimensionPixelOffset(R.styleable.CircleSplashView_solid_circle_radius, defaultSolidCircleRadius);

mEmptyCircleColor = typedArray.getColor(R.styleable.CircleSplashView_empty_circle_color, defaultEmptyCircleColor);

mEmptyCircleRadius = typedArray.getDimensionPixelOffset(R.styleable.CircleSplashView_empty_circle_radius, defaultEmptyCircleRadius);

mTextColor = typedArray.getColor(R.styleable.CircleSplashView_circle_text_color, defaultTextColor);

mTextSize = typedArray.getDimensionPixelOffset(R.styleable.CircleSplashView_circle_text_size, defaultTextSize);

mDrawOrientation = typedArray.getInt(R.styleable.CircleSplashView_circle_draw_orientation, defaultDrawOrietation);

mTimeLength = typedArray.getInt(R.styleable.CircleSplashView_time_length, defaultTimeLength);

typedArray.recycle();

这样,我们基本使用了我们自定义的属性,这里我们顺便对AttributeSet和TypeArray类简单阐述一下。

Attributeset看命名好像是一个属性的集合,实际上,它内部就是一个XML解析器,可以将布局文件中该控件的所有属性解析出来,并以key-value的形式存起来。其实我们完全可以只用他通过下面的代码来获取我们的属性就行。

for (int i = 0; i < attrs.getAttributeCount(); i++) {

Log.i(TAG, "name:" + attrs.getAttributeName(i) + " value: " + attrs.getAttributeValue(i));

}

输出结果:

android自定义属性详解_android自定义组合控件_https://bianchenghao6.com/blog_Android_第3张

可以看到使用Attributeset得到的属性的值是取到的xml文件中的值,而我们想要的textsize的大小,还得想方法将sp去掉才能拿到我们的16.0,或是dip去掉,这时typeArray就应运而生了,我们回头看看使用TypeArray后得到的数据

/**

* 自定义属性

*/

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleSplashView);

mSolidCircleColor = typedArray.getColor(R.styleable.CircleSplashView_solid_circle_color, defaultSolidCircleColor);

mSolidCircleRadius = typedArray.getDimensionPixelOffset(R.styleable.CircleSplashView_solid_circle_radius, defaultSolidCircleRadius);

mEmptyCircleColor = typedArray.getColor(R.styleable.CircleSplashView_empty_circle_color, defaultEmptyCircleColor);

mEmptyCircleRadius = typedArray.getDimensionPixelOffset(R.styleable.CircleSplashView_empty_circle_radius, defaultEmptyCircleRadius);

mTextColor = typedArray.getColor(R.styleable.CircleSplashView_circle_text_color, defaultTextColor);

mTextSize = typedArray.getDimensionPixelOffset(R.styleable.CircleSplashView_circle_text_size, defaultTextSize);

mDrawOrientation = typedArray.getInt(R.styleable.CircleSplashView_circle_draw_orientation, defaultDrawOrietation);

mTimeLength = typedArray.getInt(R.styleable.CircleSplashView_time_length, defaultTimeLength);

typedArray.recycle();

这些数据才是我们真正想要的数据。

好了,今天的分享就先到这。晚安!

【END】

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

发表回复