Android View之View绘制原理

本文详细介绍了Android中View的绘制原理及实现方法,包括基本绘图元素如点、线、矩形等的绘制过程,使用Shader实现渐变效果的技术细节,并提供了一个绘制表钟的具体示例。
1. View的绘制原理
android.graphics 相关类
Paint: 画笔
Cancas: 画布
Bitmap: Canvas背景图片
Color、Matrix、Drawable

简单绘制
 private Bitmap getBitmap(){
    int width = 300;
    int height = 300;
    Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(bmp);

    Paint paint = new Paint();
    paint.setColor(Color.YELLOW);
    canvas.drawRect(0, 0, width, height, paint);

    Paint textPaint = new Paint();
    textPaint.setColor(Color.BLUE);
    textPaint.setTextSize(100);
    textPaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD_ITALIC));
    textPaint.setTextAlign(Paint.Align.CENTER);
    canvas.drawText("Hello", width/2, height/2,textPaint);

    return bmp;
}






2. 渐变颜色 Shader 着色器
Shader类子类
BitmapShader:图形渲染
LinearGradient:线性渐变
RadialGradient:环形渐变
SweepGradient:扫描渐变
ComposeShader:组合渲染
//配置渐变色,默认左上角开始斜着渐变
int[] colors =new int[]{Color.WHITE, Color.YELLOW, Color.GREEN};
float[] positions =new float[]{0.0f,0.5f,1.0f};
LinearGradient shader =newLinearGradient(0,0,width,height,colors, positions, Shader.TileMode.CLAMP);

//顺时针旋转45度
Matrix matrix =newMatrix();
matrix.setRotate(45,width/2, height/2);
shader.setLocalMatrix(matrix);
// 设置paint的shader
paint.setShader(shader);



3. 重要绘制方法

3.1 绘制点和线
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas =newCanvas(bmp);
//解析颜色值
canvas.drawColor(Color.parseColor("#DDCC01"));

Paint paint =newPaint();
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);//设置线宽

float[] pts =new float[]{
20,20,
40,40,
80,80,
100,100
};

canvas.drawPoints(pts, paint);//画点,pts必须为2的倍数
canvas.drawLines(pts, paint);//画线,4个值为一条线



3.2 绘制矩形
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas =newCanvas(bmp);
//解析颜色值
canvas.drawColor(Color.parseColor("#DDCC01"));

Paint paint =newPaint();
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);//设置线宽

canvas.drawRoundRect(newRectF(100,100,300,300),50,50, paint);

如需要画一个空心的矩形
paint.setStyle(Paint.Style.STROKE);//设置paint的style为STROKE




3.3 绘制路径

Path path =newPath();
path.moveTo(10.0f,10.0f);
path.lineTo(300.0f,30.0f);
path.lineTo(400.0f,500.0f);
path.lineTo(500.0f,300.0f);
canvas.drawPath(path, paint);

注:当画实心的时候,最后一个点会与第一个点粘上,画空心的时候则不会(即调用paint.setStyle(Paint.Style.STROKE);)


4 绘制表钟的实例
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
// 解析颜色值
canvas.drawColor(Color.parseColor("#FFFFFF"));

Paint paint = new Paint();
paint.setColor(Color.parseColor("#333333"));
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true); // 消除锯齿的功能
paint.setStrokeWidth(4);

// 外围圆
float radius = width/2 - 4;
canvas.drawCircle(width/2, height/2, radius, paint);

// 内部实心圆
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(width/2, height/2, 10, paint);

// 循环画刻度
for(int i = 0; i < 12; i++){
    if(i % 3 == 0){
        paint.setStrokeWidth(10);
        canvas.drawLine(width/2 , height/2 + radius - 24, width/2, height/2 + radius, paint);
    }else{
        paint.setStrokeWidth(4);
        canvas.drawLine(width/2 , height/2 + radius - 20, width/2, height/2 + radius, paint);
    }
    canvas.rotate(30, width/2, height/2); // 注意:这里巧妙应用canvas旋转的思想
}


// 画时间指针
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);

float lenH = radius * 0.7f;
float lenM = radius * 0.8f;
float lenS = radius * 0.9f;

float degree = hour * 30.0f + minute / 2;
paint.setStrokeWidth(10);
canvas.save(); // 第二种方法:先保存后restore
canvas.rotate(degree, width/2, height/2);
canvas.drawLine(width/2 , height/2, width/2, height/2 - lenH, paint);
// canvas.rotate(-degree, width/2, height/2); // 第一种方法,旋转回来
canvas.restore(); // 第二种方法:先保存后restore

// canvas.save();// save有count返回值
// canvas.restoreToCount(1);// restore到制定的count

// 画分钟
degree = minute * 6.0f + second / 10;
paint.setStrokeWidth(6);
canvas.save();
canvas.rotate(degree, width/2, height/2);
canvas.drawLine(width/2 , height/2, width/2, height/2 - lenM, paint);
canvas.restore();
// 画分钟
degree = second * 6.0f;
paint.setStrokeWidth(4);
canvas.save();
canvas.rotate(degree, width/2, height/2);
canvas.drawLine(width/2 , height/2, width/2, height/2 - lenS, paint);
canvas.restore();

// 要使表钟动起来,可新建一个AsyncTask,来在后台更新,如下简易版代码:

private class updateClock extends AsyncTask<Void, Void, Void>{

    @Override
    protected Void doInBackground(Void... params) {
        while(true){
            publishProgress();
            try {
                Thread.sleep(1000);
            }catch (InterruptedException e){

            }
        }
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
        mImageView.setImageBitmap(getBitmap());
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值