Ⅰ、继承现有控件,对其控件的功能进行拓展。(拓展功能)
Ⅱ、将现有控件进行组合,实现功能更加强大控件。(布局重用)
Ⅲ、重写View实现全新的控件(不规则效果控件)
本文来讨论最难的一种自定义控件形式,重写View来实现全新的控件。
1.构造方法,1参,2参,3参(4参的一般不用)
2.
onMeasure(int widthMeasureSpec, int heightMeasureSpec)测绘大小
onDraw(Canvas canvas)用Canvas和Paint绘制内容
onLayout(boolean changed,int left, int top, int right, int bottom)确定显示的位置
onTouchEvent(MotionEvent event)定义触摸事件
private int mColor01;
public CustomView01(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//构造方法获取自定义属性的方法
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.CustomView01);
//若第一个参数为null,默认值为RED
mColor01=a.getColor(R.styleable.CustomView01_textColor,Color.RED);
//关闭资源
a.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//先声明两个int值来表示最终的width和height并给定一个默认的大小
int width_size = 500;
int height_size = 500;
//使用MeasureSpec分别获取width和height的MODE和SIZE
int HEIGHT_MODE = MeasureSpec.getMode(heightMeasureSpec);
int HEIGHT_SIZE = MeasureSpec.getSize(heightMeasureSpec);
int WIDTH_MODE = MeasureSpec.getMode(widthMeasureSpec);
int WIDTH_SIZE = MeasureSpec.getSize(widthMeasureSpec);
//这个方法的用途是因为自定义view的wrap_content属性失效的使用方法
//setMeasuredDimension用于设置view的宽高
if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT && getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(width_size, height_size);
} else if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(width_size, WIDTH_SIZE);
} else if (getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
setMeasuredDimension(HEIGHT_SIZE, height_size);
}
}
MeasureSpect三种模式
MeasureSpect是由LayoutParameter通过父容器的施加的规则产生的
MeasureSpec.EXACTLY MeasureSpec.AT_MOST MeasureSpec.UNSPECIFIED这三种模式
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// // 画文本
// canvas.drawText();
// // 画弧
// canvas.drawArc();
// // 画圆
// canvas.drawCircle();
canvas.drawColor(Color.RED); //设置canvas的背景色
float radius = 50; //给定半径
//给定圆心的的坐标
float cx = 50;
float cy = 50;
Paint paint1 = new Paint(); //实例化一个Paint对象
paint1.setColor(Color.BLUE); //设置圆的颜色
//通过canvas的drawCircle方法画一个圆圈.
// canvas.drawCircle(cx, cy, radius, paint1);
Paint paint2 = new Paint(); //实例化一个Paint对象
paint2.setColor(Color.BLACK);
paint2.setStrokeWidth(10);//因为默认实在是太细了 设定了一个宽度值
canvas.drawLine(0, 0, 100, 100, paint2);
Paint paint3 = new Paint(); //实例化一个Paint对象
paint3.setColor(Color.BLACK); //设置圆的颜色
paint3.setAntiAlias(true); //设置抗锯齿
paint3.setStyle(Paint.Style.FILL); //设置样式
paint3.setStrokeWidth(3); //设置宽度
Paint paint4 = new Paint(); //实例化第二个paint对象
paint4.setColor(Color.BLUE); //设置颜色为蓝色
paint4.setStyle(Paint.Style.STROKE);//设置样式
paint4.setStrokeWidth(30); //设定边框宽度
//通过canvas的drawCircle方法画一个圆圈.
canvas.drawCircle(cx, cy, radius, paint3);
canvas.drawCircle(cx, cy, radius, paint4);
}
Paint.setStyle三种样式,填充,填充和外轮廓,外轮廓
FILL,FILL_OR_STROKE,或STROKE
Paint的set和Canvas的set详细参考底下
https://www.cnblogs.com/itgungnir/p/6217447.html
@Override
protected void onLayout(boolean changed,int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 手指按下
Log.e("TAG", "手指按下");
break;
case MotionEvent.ACTION_MOVE:
// 手指移动
Log.e("TAG", "手指移动");
break;
case MotionEvent.ACTION_UP:
// 手指抬起
Log.e("TAG", "手指抬起");
break;
default:
break;
}
return super.onTouchEvent(event);
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomView01">
<attr name="textSize" format="dimension" />
<attr name="text" format="string" />
<attr name="circleColor" format="color" />
<attr name="arcColor" format="color" />
<attr name="textColor" format="color" />
<attr name="startAngle" format="integer" />
<attr name="sweepAngle" format="integer" />
</declare-styleable>
</resources>