View显示流程
1、onMeasure()测量宽高
2、ViewGroup 布局, onLayout()
3 、 draw() 视图显示自身的内容
1 、绘制背景
2 、为显示渐变框做一些准备动作
3 、调用自身的 onDraw(),(ViewGroup 不需要 )
4 、 dispatchDraw() 绘制子视图 ( 调用了 drawChild() 通知孩子 draw() 自身 )
5 、画滚动条
View 的自定义的认识
要自定义 View 的显示效果,可以重写其 onDraw 方法,然后在 Canvas 上绘制内容即可
public class MyView extends View {
public MyView(Context context) {
super(context);
Log.e("m_tag","MyView(Context context)");
init();
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
Log.e("m_tag","MyView(Context context, AttributeSet attrs)");
init();
}
private Paint paint;
private void init(){
setBackgroundColor(0xff999999);
// 创建画笔对象
paint = new Paint();
// 设置画笔的颜色
// paint.setColor(0xFFFF0000);
paint.setColor(Color.RED);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 画图 : 画布 画笔 颜色
canvas.drawRect(50,100,150,200,paint);
}
}
使用:
<com.xykj.viewdemo.MyView
android:layout_width="match_parent"
android:layout_height="300dp" />
Canvas的基本绘制
// 画矩形
// 前面 4 个参数表示矩形的左上右下,第五个参数表示画笔
canvas.drawRect(50,100,150,200,paint);
// 创建一个矩形对象
Rect rect = new Rect(150,300,350,400);
canvas.drawRect(rect,paint);
// 画一个圆
//( 圆心 x 坐标,圆心 y 坐标,半径,画笔 )
canvas.drawCircle(50,300,50,paint);
Paint的基本设置
设置颜色
paint.setColor(0xFFFF0000);
paint.setColor(Color.RED); // 从 Color 类中获取的颜色值
// 消除锯齿
paint.setAntiAlias(true);
// 分开设置各个颜色参数 0x00-0xff 十进制就是 0-255
paint.setARGB(255,20,50,100);
paint.setAlpha(100); // 设置透明度
// 设置画笔样式 STROKE 表示空心 FILL 表示实心
paint.setStyle(Paint.Style.STROKE);
// 空心边框宽度
paint.setStrokeWidth(5);
View的刷新
如果要修改视图显示的内容,需要让视图重新 onDraw ,然后在画布上画上新的内容即可,要让视图重新画需要使用其刷新方法
主线程刷新:invalidate() ; –> 使视图重新绘制
结合触摸监听实现刷新
public class RefreshView extends View {
public RefreshView(Context context) {
super(context);
init();
}
public RefreshView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private Paint paint;
private void init() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
}
// 圆的圆心
private int cx = 50, cy = 100;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 画圆
canvas.drawCircle(cx, cy, 50, paint);
}
// 视图的触摸监听
@Override
public boolean onTouchEvent(MotionEvent event) {
// 获取触摸的行为
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// 手指触摸到视图的瞬间
// 得到触控点跟视图左上角点的坐标 ( 相对位置 )
int x = (int) event.getX();
// int pX = event.getRawX(); // 得到触控点和屏幕左上角的位置
int y = (int) event.getY();
cx = x;
cy = y;
invalidate(); // 刷新视图 ( 视图会重新绘制 )
break;
case MotionEvent.ACTION_MOVE:
// 按下之后离开之前的整个过程 ( 重复执行 )
cx = (int) event.getX();
cy = (int) event.getY();
invalidate();
break;
case MotionEvent.ACTION_UP:
// 手指离开视图的瞬间
break;
}
return true;
}
}
子线程刷新,需要使用 postInvalidate 方法,该方法等效于 Handler+invalidate 方式
private Thread changeThread;
// 随机数 ( 产生 0-255 之间的数字 )
private Random r = new Random();
public void startChangeColor() {
if (null != changeThread && changeThread.isAlive()) {
return;
}
changeThread = new Thread() {
@Override
public void run() {
try {
while(true) {
Thread.sleep(500);
// 改变画笔颜色
paint.setARGB(255,r.nextInt(256),r.nextInt(256),r.nextInt(256));
// 刷新视图 ( 子线程 )
postInvalidate(); // 等效于 Handler+invalidate
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
changeThread.start();
}
canvas其他的各种画
// 圆角矩形
RectF rectF = new RectF(300,10,400,80);
//( 矩形区域,圆角 x 方向半径,圆角 y 方向半径 )
canvas.drawRoundRect(rectF,20,20,paint);
// 画椭圆
RectF oval = new RectF(300,100,400,300);
canvas.drawOval(oval,paint);
RectF arcRectF = new RectF(450,10,550,110);
// 画弧线或者扇形
// 第一个参数 : 扇形所在的圆所在的矩形区域
// 第二个参数:起始角度
// 第三个参数:跨越的总度数
// 第四个参数: true 表示扇形, false 表示弧线
// 第五个参数:画笔
canvas.drawArc(arcRectF,-90,90,false,paint);
Path p = new Path();
// 指定起始点
p.moveTo(450,100);
// 画直线到下一个点
p.lineTo(600,200);
p.lineTo(500,400);
// 画贝塞尔曲线
// 前面两个表示弧度控制点,后面两个参数表示弧线的终点
p.quadTo(300,300,500,200);
// 将最后一个点连接到起始点上
p.close();
// 画路径
canvas.drawPath(p,paint)