Android 绘图 ——Android群英传 学习笔记

FontMatrics部分参考:http://mikewang.blog.51cto.com/3826268/871765

核心类

1.Canvas 画布
2.Bitmap 纸
3.Paint 笔
4.{
    FontMetrics
    PorterDuffXfermode
    Matrix(3x3矩阵) 
    ColorMatrix(4x5矩阵)
    ColorFilter
    Shader
    PathEffect
}
5. SurfaceView P155,有固定模版用法

思想

1.一般初始化Canvas时,要传入一个Bitmap,之后的所有的绘制效果都将呈现在Bitmap上。
    Bitmap mPaper = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mPaper);
    mCanvas.drawBitmap(bm, 0, 0, paint);//将bm用画笔paint画到mPager上
2.在onDraw(canvas)方法中,只需要将步骤1中的纸mPaper绘制到系统提供的画布canvas上即可。
    canvas.drawBitmap(mPaper, 0, 0, null);
3.Paint 
    具有非常强大的功能:
    1)PorterDuffXfermode 滤镜功能:
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
        设置混合模式,具体效果参考文档,或Android群英传P146.
    2)获取FontMetrics,测量文本尺寸
        Paint.FontMetrics fm = mPaint.getFontMetrics();
        FontMetrics属性:{
            1. 基准点是baseline
            2. ascent是baseline之上至字符最高处的距离
            3. descent是baseline之下至字符最低处的距离
            4. leading文档说的很含糊,其实是上一行字符的descent到下一行的ascent之间的距离
            5. top指的是指的是最高字符到baseline的值,即ascent的最大值
            6. 同上,bottom指的是最下字符到baseline的值,即descent的最大值

            说明:ascent/descent/top/bottom,这几个值均表示距离baseline的距离。举例:ascent的值,即为字符最高处的y坐标减去baseline的y坐标之差。所以,其永远为负值。同理,descent/bottom永远为正值。
        }

        float baseY = - fm.top;
        mCanvas.drawText("cuncaojin", 0, baseY, mPaint);

        ![](http://img1.51cto.com/attachment/201205/204735397.png)
    3)Style(空心/实心)
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    4)setColorFilter
        ColorMatrix imageMatrix = new ColorMatrix();
        //颜色矩阵,可以设置色调、饱和度、亮度
        imageMatrix.setRotate(0/1/2,hue);//0,1,2——R,G,B 色调
        imageMatrix.setSaturation(saturation);//饱和度为0时,图像为灰度图像
        imageMatrix.setScale(lum, lum, lum, 1);//亮度
        imageMatrix.postConcat(anotherColorMatrix);//将颜色矩阵叠加
        paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));

    5)setShader():主要作用是作为遮罩层,产生特殊效果
        Shader(渲染器)类实现类有{
            a. BitmapShader 位图Shader (相比其他Shader比较特殊)
                {
                    用BitmapShader填充时的3种模式:
                        CLAMP 拉伸
                        REPEAT 重复
                        MIRROR 镜像
                }
            b. LinearGradient 线性Shader
            c. RadialGradient 光束Shader
            d. SweepGradient 梯度Shader
            e. ComposeShader 混合Shader
        }


    6)setPathEffect 路径效果
        a. null    
        b. CornerPathEffect    路径圆滑处理
        c. DiscretePathEffect    产生杂点
        d. DashPathEffect    虚线化
        e. PathDashPathEffect    可设置虚线图形
        f. ComposePathEffect    可组合以上效果


    7)其他属性{
        setAntiAlias(true); 抗锯齿
        setStrokeJoin(Paint.Join.ROUND); 设置笔连接处圆滑处理
        setStrokeCap(Paint.Cap.ROUND); 设置笔触圆滑处理
        setStrokeWidth(50);    设置笔宽
        setColor();    
        setARGB();
        setAlpah();
        setTextSize();
    }    
4.Canvas
    1)绘制{
        drawPoint
        drawLine
        drawRect
        drawRoundRect
        drawArc 绘制扇形或弧形(由参数useCenter决定,true扇形,false弧形,设置Paint.Style决定是空心还是实心)
        drawOval 绘制椭圆
        drawText 
        drawPosText(text, new float[]{x1,y1,x2,y2,...xn,yn}, paint) 在指定位置逐个对每个字符绘制    
        drawPath 绘制路径
        drawBitmap
    }
    2)结合Matrix
        Matrix matrix = new Matrix();
        matrix{
            setRotate()
            setTranslate();    
            setScale();    
            setSkew(); 错切变换/剪切变换
            pre() 先乘
            post() 后乘
        }
        canvas.drawBitmap(mBitmap, matrix ,null);
        ---------------------------------------------
        Canvas mCanvas = new Canvas(mBmp);
        Matrix matrix = new Matrix();
        float scale = w * 1f / getResources().getDisplayMetrics().widthPixels;
        matrix.setScale(scale, scale);
        mCanvas.drawBitmap(bitmap, matrix, mPaint);
    3)Canvas的其他方法{
        save() 将之前绘制的所有图像进行保存
        restore() 将save()之后绘制的所有图像与save()之前的图像进行合并
        translate() 
        rotate()
    }

Demo:

自定义一个圆形图,实现方案{
    1)使用paint.setXferMode(new PorterXferMode(...))
        a. 绘制圆
        b. 对画笔设置PorterDuffXfermode(SRC_IN)则上步绘制的圆作为遮罩层
        c. (设置缩放比例等)优化绘图效果
        d. 绘制图片
    2) 使用paint.setShader(new BitmapShader(...))
        a. 对画笔设置渲染器为BitmapShader,模式选择拉伸
            mPaint.setShader(new BitmapShader(mBmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
        b. (设置缩放比例等)优化绘图效果
        c. 绘制圆
}

参考代码如下:

方案一:
public CircleView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();

    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleView);
    int indexCount = typedArray.getIndexCount();
    for (int i = 0; i < indexCount; i++) {
        int index = typedArray.getIndex(i);
        switch (index) {
            case R.styleable.CircleView_src:

                BitmapDrawable drawable = (BitmapDrawable) typedArray.getDrawable(index);
                mBitmap = drawable.getBitmap();
                break;
        }
    }
    typedArray.recycle();
}

private void init() {
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    mPaper = Bitmap.createBitmap(w, w, Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mPaper);
    mPaint.setTextSize(50);
    mPaint.setStrokeWidth(5);
    mPaint.setARGB(255, 255, 0, 0);
    mPaint.setColor(0xff00ff00);
    mPaint.setTextAlign(Paint.Align.LEFT);

    Paint.FontMetrics fm = mPaint.getFontMetrics();
    Log.i("tag", fm.ascent + ", leading:" + fm.leading + " ,descent:" + fm.descent + ", bottom:" + fm.bottom + ", " + fm.top);
    float baseY = -fm.ascent;
    mCanvas.drawText("寸草金CUNJQjinsdaofihwafehofdmvpBGEOUWmevldnbuehwPOS:lXM", 0, baseY, mPaint);

    Path path = new Path();
    path.moveTo(0, 50);
    path.lineTo(100, 200);
    mCanvas.drawPath(path, mPaint);

    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));

    RectF rect = new RectF(0, 0, w, h);
    mCanvas.drawRoundRect(rect, 50, 50, mPaint);

    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    Matrix matrix = new Matrix();
    matrix.setScale(w * 1f / mBitmap.getWidth(), w * 1f / mBitmap.getWidth());
    mCanvas.drawBitmap(mBitmap, matrix, mPaint);
}

方案二:
private void init(Context context, AttributeSet attrs) {
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic1);
    mBmp = Bitmap.createBitmap(w, w, Bitmap.Config.ARGB_8888);

    Canvas mCanvas = new Canvas(mBmp);
    Matrix matrix = new Matrix();
    float scale = w * 1f / getResources().getDisplayMetrics().widthPixels;
    matrix.setScale(scale, scale);
    mCanvas.drawBitmap(bitmap, matrix, mPaint);

    mPaint.setShader(new BitmapShader(mBmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(widthMeasureSpec, widthMeasureSpec);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int r = getWidth() / 2;
    canvas.drawCircle(r, r, r, mPaint);
}
文章目录
|