自定义 View
// 一般是在第二个构造函数里主动调用
// 如 View 有 style 属性时
public CircleView(Context context,AttributeSet attrs,int defStyleAttr ){
super(context, attrs,defStyleAttr);
init();
}
//API21 之后才使用
// 不会自动调用
// 一般是在第二个构造函数里主动调用
// 如 View 有 style 属性时
public CircleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
// 画笔初始化
private void init() {
// 创建画笔
mPaint1 = new Paint ();
// 设置画笔颜色为蓝色
mPaint1.setColor(Color.BLUE);
// 设置画笔宽度为 10px
mPaint1.setStrokeWidth(5f);
//设置画笔模式为填充
mPaint1.setStyle(Paint.Style.FILL);
}
// 复写 onDraw()进行绘制
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 获取控件的高度和宽度
int width = getWidth();
int height = getHeight();
// 设置圆的半径 = 宽,高最小值的 2 分之 1
int r = Math.min(width, height)/2;
// 画出圆(蓝色)
// 圆心 = 控件的中央,半径 = 宽,高最小值的 2 分之 1
canvas.drawCircle(width/2,height/2,r,mPaint1);
}
}
步骤 2:在 xml 中加入这个 view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="Rikka.MainActivity">
<scut.carson_ho.diy_view.CircleView
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#000000"/>
</RelativeLayout>
效果如下:
接着手动支持 wrap_content 和 padding,以及为自定义 view 设置属性。
(1)支持 wrap_content
(2)padding,在 CircleView 中的 onDraw 添加如下代码:
绘制时考虑传入 padding 属性值(4 个方向)
// 仅看复写的 onDraw()
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 获取传入的 padding 值
final int paddingLeft = getPaddingLeft();
final int paddingRight = getPaddingRight();
final int paddingTop = getPaddingTop();
final int paddingBottom = getPaddingBottom();
// 获取绘制内容的高度和宽度(考虑了四个方向的 padding 值)
int width = getWidth() - paddingLeft - paddingRight ;
int height = getHeight() - paddingTop - paddingBottom ;
// 设置圆的半径 = 宽,高最小值的 2 分之 1
int r = Math.min(width, height)/2;
// 画出圆(蓝色)
// 圆心 = 控件的中央,半径 = 宽,高最小值的 2 分之 1
canvas.drawCircle(paddingLeft+width/2,paddingTop+height/2,r,mPaint1);
}
这时候在 xml 的 view 中添加 android:padding="20dp"
,view 就会支持 padding 了
(3)提供自定义属性:
// 基本是以 android 开头
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:padding="30dp"
上面是系统自带的自定义属性。
但有时候我们需要定义系统所没有的属性,称为自定义属性,实现步骤有下:
①、在 values 目录下自定义属性的 xml 文件
②、在自定义 view 的构造方法中解析自己定义属性的值
③、在布局文件中自己定义属性
具体实现:
①:在 values 中定义 xml 文件:
attrs_circle_view.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleView">
<attr name="circle_color" format="color"/>
</declare-styleable>
</resources>
对于自定义属性类型有如下格式:
<-- 1. reference:使用某一资源 ID -->
<declare-styleable name="名称">
<attr name="background" format="reference" />
</declare-styleable>
// 使用格式
// 1. Java 代码
private int ResID;
private Drawable ResDraw;
ResID = typedArray.getResourceId(R.styleable.SuperEditText_background, R.drawable.background); // 获得资源 ID
ResDraw = getResources().getDrawable(ResID); // 获得 Drawble 对象
// 2. xml 代码
<ImageView
android:layout_width="42dip"
android:layout_height="42dip"
app:background="@drawable/图片 ID" />
<-- 2. color:颜色值 -->
<declare-styleable name="名称">
<attr name="textColor" format="color" />
</declare-styleable>
// 格式使用
<TextView
android:layout_width="42dip"
android:layout_height="42dip"
android:textColor="#00FF00" />
<-- 3. boolean:布尔值 -->
<declare-styleable name="名称">
<attr name="focusable" format="boolean" />
</declare-styleable>
// 格式使用
<Button
android:layout_width="42dip"
android:layout_height="42dip"
android:focusable="true" />
<-- 4. dimension:尺寸值 -->
<declare-styleable name="名称">
<attr name="layout_width" format="dimension" />
</declare-styleable>
// 格式使用:
<Button
android:layout_width="42dip"
android:layout_height="42dip" />
<-- 5. float:浮点值 -->
<declare-styleable name="AlphaAnimation">
<attr name="fromAlpha" format="float" />
<attr name="toAlpha" format="f
loat" />
</declare-styleable>
// 格式使用
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.7" />
<-- 6. integer:整型值 -->
<declare-styleable name="AnimatedRotateDrawable">
<attr name="frameDuration" format="integer" />
<attr name="framesCount" format="integer" />
</declare-styleable>
// 格式使用
<animated-rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:frameDuration="100"
android:framesCount="12"
/>
<-- 7. string:字符串 -->
<declare-styleable name="MapView">
<attr name="apiKey" format="string" />
</declare-styleable>
// 格式使用
<com.google.android.maps.MapView
android:apiKey="0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g" />
<-- 8. fraction:百分数 -->
<declare-styleable name="RotateDrawable">
<attr name="pivotX" format="fraction" />
<attr name="pivotY" format="fraction" />
</declare-styleable>
// 格式使用
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="200%"
android:pivotY="300%"
/>
<-- 9. enum:枚举值 -->
<declare-styleable name="名称">
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
</declare-styleable>
// 格式使用
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<-- 10. flag:位或运算 -->
<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>、
// 使用
<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>
评论