前言:
自定义view是android自定义控件的核心之一,那么在学习自定义view之前,我们先来了解下自定义view的自定义属性的attr的用法。
1.attr
1.1 概念
(1)attr 的简单理解就是一个属性约束,约束具体属性字段的属性的数据类型(boolean、string、float…)
(2)attr的文件名称不是固定的,只是方便理解和规范,也可以是其他名称,创建attr 文件在res/values 下
2.attr 作用
attr 作用就是约束属性数据类型,xml资源文件中定义各种attr,指定attr的数据类型。
3.attr 使用方式
(1)通过 为自定义View添加属性
(2) 在xml中为相应的属性声明属性值
(3)在运行时(一般为构造函数)获取属性值
(4)将获取到的属性值应用到View
2.attr的简单创建
(1)我们在res/values目录下新建了一个名为attrs.xml文件,文件名是什么不重要,只要是xml文件就行。
(2)在该文件中定义我们自定义view所支持的xml 属性。
例如:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="sext" format="string|integer"/> 公共属性
<attr name="isSignal" format="boolean"/>
<declare-styleable name="View1">
<attr name="viewBg" format="reference"/>
<attr name="cirColor" format="color|integer"/>
<attr name="txtVisibility" format="string"/>
<attr name="isSignal"/> 直接引用公共属性
</declare-styleable>>
</resources>
declare-styleable name: 是自定义view 的名字
attr name : 是自定义的属性
format :自定义属性支持的类型 enum、boolean、color、dimension、flag、float、fraction、integer、reference、string。
注意:
如果定义多个<declare-styleable name 中的attr name不能相同,否则会报错,那么就把相同的提取到<declare-styleable外部,定义成公共属性,例如 "<“attr name=“isSignal”/>”
3.format 数据类型具体参考
1.reference :参考某一资源ID
(1)属性定义:
<declare-styleable name = "名称">
<attr name = "background" format = "reference" />
</declare-styleable>
(2)属性使用:
<ImageView
android:layout_width = "42dip"
android:layout_height = "42dip"
android:background = "@drawable/图片ID"/>
2.color:颜色值
(1)属性定义:
<declare-styleable name = "名称">
<attr name = "textColor" format = "color" />
</declare-styleable>
(2)属性使用:
<TextView
android:layout_width = "42dip"
android:layout_height = "42dip"
android:textColor = "#00FF00"/>
3. boolean:布尔值
(1)属性定义:
<declare-styleable name = "名称">
<attr name = "focusable" format = "boolean" />
</declare-styleable>
(2)属性使用:
<Button
android:layout_width = "42dip"
android:layout_height = "42dip"
android:focusable = "true"/>
4. dimension:尺寸值
(1)属性定义:
<declare-styleable name = "名称">
<attr name = "layout_width" format = "dimension" />
</declare-styleable>
(2)属性使用:
<Button
android:layout_width = "42dip"
android:layout_height = "42dip"/>
5. float:浮点值
(1)属性定义:
<declare-styleable name = "AlphaAnimation">
<attr name = "fromAlpha" format = "float" />
<attr name = "toAlpha" format = "float" />
</declare-styleable>
(2)属性使用:
<alpha
android:fromAlpha = "1.0"
android:toAlpha = "0.7"/>
6. integer:整型值
(1)属性定义:
<declare-styleable name = "AnimatedRotateDrawable">
<attr name = "visible" />
<attr name = "frameDuration" format="integer" />
<attr name = "framesCount" format="integer" />
<attr name = "pivotX" />
<attr name = "pivotY" />
<attr name = "drawable" />
</declare-styleable>
(2)属性使用:
<animated-rotate
xmlns:android = "http://schemas.android.com/apk/res/android"
android:drawable = "@drawable/图片ID"
android:pivotX = "50%"
android:pivotY = "50%"
android:framesCount = "12"
android:frameDuration = "100" />
7. string:字符串
(1)属性定义:
<declare-styleable name = "MapView">
<attr name = "apiKey" format = "string" />
</declare-styleable>
(2)属性使用:
<com.google.android.maps.MapView
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:apiKey = "0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g"
/>
8. fraction:百分数
(1)属性定义:
<declare-styleable name="RotateDrawable">
<attr name = "visible" />
<attr name = "fromDegrees" format = "float" />
<attr name = "toDegrees" format = "float" />
<attr name = "pivotX" format = "fraction" />
<attr name = "pivotY" format = "fraction" />
<attr name = "drawable" />
</declare-styleable>
(2)属性使用:
<rotate
xmlns:android = "http://schemas.android.com/apk/res/android"
android:interpolator = "@anim/动画ID"
android:fromDegrees = "0"
android:toDegrees = "360"
android:pivotX = "200%"
android:pivotY = "300%"
android:duration = "5000"
android:repeatMode = "restart"
android:repeatCount = "infinite" />
9. enum:枚举值
(1)属性定义:
<declare-styleable name="名称">
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
</declare-styleable>
(2)属性使用:
<LinearLayout
xmlns:android = "http://schemas.android.com/apk/res/android"
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent">
</LinearLayout>
10. flag:位或运算
(1)属性定义:
<declare-styleable name="名称">
<attr name="windowSoftInputMode">
<flag name = "stateUnspecified" value = "0" />
<flag name = "stateUnchanged" value = "1" />
<flag name = "stateHidden" value = "2" />
<flag name = "stateAlwaysHidden" value = "3" />
<flag name = "stateVisible" value = "4" />
<flag name = "stateAlwaysVisible" value = "5" />
<flag name = "adjustUnspecified" value = "0x00" />
<flag name = "adjustResize" value = "0x10" />
<flag name = "adjustPan" value = "0x20" />
<flag name = "adjustNothing" value = "0x30" />
</attr>
</declare-styleable>
(2)属性使用:
<activity
android:name = ".StyleAndThemeActivity"
android:label = "@string/app_name"
android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">
<intent-filter>
<action android:name = "android.intent.action.MAIN" />
<category android:name = "android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
注意:
属性定义时可以指定多种类型值
(1)属性定义:
<declare-styleable name = "名称">
<attr name = "background" format = "reference|color" />
</declare-styleable>
(2)属性使用:
<ImageView
android:layout_width = "42dip"
android:layout_height = "42dip"
android:background = "@drawable/图片ID|#00FF00" />
4.attr 的使用
自定义view简单实现步骤:
(1)首先创建attrs自定义属性文件名称,定义属性以及相关数据类型
(2)再次创建自定义view,然后读取相关属性完成需要的view相关布局、绘制等工作
(3)最后在xml布局文件中引用或者直接在代码中new一个相关对象进行使用
例如:自定义一个textview在屏幕上显示出来
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="viewText" format="string|integer"/>
<attr name="isSignal" format="boolean"/>
<attr name="viewBg" format="color"/>
<declare-styleable name="YText">
<attr name="viewText"/>
<attr name="isSignal"/>
<attr name="viewBg" />
<attr name="viewTextBg" format="color"/>
<attr name="viewSize" format="integer"/>
</declare-styleable>
</resources>
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.demo.YText
android:layout_height="match_parent"
android:layout_width="match_parent"
app:isSignal="false"
app:viewText="自定义View"
app:viewBg="@color/colorYellow"
app:viewTextBg="@color/colorRed"
app:viewSize="80">
</com.example.demo.YText>
</androidx.constraintlayout.widget.ConstraintLayout>
注意: res/android 和 res-auto
xmlns:android=http://schemas.android.com/apk/res/android
xmlns:app=http://schemas.android.com/apk/res-auto
这2个实际上前者是就是让你引用系统自带属性的,后者是让你使用attrs库里自定义属性的。
YText.java
public class YText extends View {
private String mText;
private boolean isSignal;
private int viewTextbg;
private int viewBg;
private int mTextSize;
private Paint paint;
public YText(Context context) {
this(context,null); //手动new 调用
}
public YText(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0); //xml 中调用
parseXmlAttributes(context,attrs);
}
public YText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void parseXmlAttributes(Context context,AttributeSet attributeSet) {
TypedArray typedArray = context.obtainStyledAttributes(attributeSet,R.styleable.YText);
for (int i=0;i<typedArray.getIndexCount();i++) {
switch (typedArray.getIndex(i)) {
case R.styleable.YText_viewText:
mText = typedArray.getString(R.styleable.YText_viewText);
break;
case R.styleable.YText_isSignal:
isSignal = typedArray.getBoolean(R.styleable.YText_isSignal,true);
break;
case R.styleable.YText_viewBg:
viewBg = typedArray.getColor(R.styleable.YText_viewBg, Color.YELLOW);
break;
case R.styleable.YText_viewTextBg:
viewTextbg = typedArray.getColor(R.styleable.YText_viewTextBg, Color.YELLOW);
break;
case R.styleable.YText_viewSize:
mTextSize = typedArray.getInt(R.styleable.YText_viewSize,38);
break;
}
}
typedArray.recycle();
paint = new Paint();
paint.setTextSize(mTextSize);
}
@Override
protected void onDraw(Canvas canvas) {
paint.setColor(viewBg);
canvas.drawRect(0,0,getMeasuredWidth(), getMeasuredHeight(), paint);
paint.setColor(viewTextbg);
canvas.drawText(mText,100,100,paint);
}
}