Android绘图

    在Android开发过程中,常常需要自定义View,需要自己绘制图片效果或者需要一些动态效果,我们就可以使用Android提供的绘图工具进行绘制。绘图的三要素Canvas--画布,Paint--画笔,Rect/RectF--绘图区域,只要掌握了这几个要素就基本上可以满足我们大部分需求。
一、Canvas--画布
    可以理解为美术课上的画板,这个类提供了绘制各种基本图形的方法,如下图所示,

    只截取了部分drawXXX方法,从上面方法的名字看来我们可以知道Canvas可以绘制的对象有:弧线(arcs)、填充颜色(argb和color)、 Bitmap、圆(circle和oval)、点(point)、线(line)、矩形(Rect)、图片(Picture)、圆角矩形 (RoundRect)、文本(text)、顶点(Vertices)、路径(path)。通过组合这些对象我们可以画出各种各样的图像。为了满足不同场合的需求,还提供了一些对Canvas进行操作的方法:rorate、scale、translate、skew(扭曲)等,而且它允许你通过获得它的转换矩阵对象直接操作它。这些操作就像是虽然你的笔还是原来的地方画,但是画纸旋转或者移动了,所以你画的东西的方位就产生变化。为了方便一些转换操作,Canvas 还提供了保存和回滚属性的方法(save和restore),比如你可以先保存目前画纸的位置(save),然后旋转90度,向下移动100像素后画一些图形,画完后调用restore方法返回到刚才保存的位置。

  
  
二、Paint--画笔
    Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色,样式等绘制信息,指定了如何绘制文本和图形,画笔对象有很多设置方法,大体上可以分为两类,一类与图形绘制相关,一类与文本绘制相关。          

1.图形绘制  

    setARGB(int a,int r,int g,int b);  

    设置绘制的颜色,a代表透明度,r,g,b代表颜色值。  

    setAlpha(int a);  

    设置绘制图形的透明度。   

    setColor(int color);  

    设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度和RGB颜色。  

    setAntiAlias(boolean aa);  

    设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。      

    setDither(boolean dither);  

    设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰    

    setFilterBitmap(boolean filter);  

    如果该项设置为true,则图像在动画进行中会滤掉对Bitmap图像的优化操作,加快显示速度,本设置项依赖于dither和xfermode的设置     

    setMaskFilter(MaskFilter maskfilter);  

    设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等         

    setColorFilter(ColorFilter colorfilter);  

    设置颜色过滤器,可以在绘制颜色时实现不用颜色的变换效果        

    setPathEffect(PathEffect effect);  

    设置绘制路径的效果,如点画线等     

    setShader(Shader shader);  

    设置图像效果,使用Shader可以绘制出各种渐变效果       

    setShadowLayer(float radius ,float dx,float dy,int color);  

    在图形下面设置阴影层,产生阴影效果,radius为阴影的角度,dx和dy为阴影在x轴和y轴上的距离,color为阴影的颜色          

    setStyle(Paint.Style style);  

    设置画笔的样式,为FILL,FILL_AND_STROKE,或STROKE        

    setStrokeCap(Paint.Cap cap);  

    当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的图形样式,如圆形样式Cap.ROUND,或方形样式Cap.SQUARE     

    setSrokeJoin(Paint.Join join);  

    设置绘制时各图形的结合方式,如平滑效果等      

    setStrokeWidth(float width);  

    当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度      

    setXfermode(Xfermode xfermode);  

    设置图形重叠时的处理方式,如合并,取交集或并集,经常用来制作橡皮的擦除效果   

2.文本绘制  

    setFakeBoldText(boolean fakeBoldText);  

    模拟实现粗体文字,设置在小字体上效果会非常差        

    setSubpixelText(boolean subpixelText);  

    设置该项为true,将有助于文本在LCD屏幕上的显示效果     

    setTextAlign(Paint.Align align);  

    设置绘制文字的对齐方向    

    setTextScaleX(float scaleX);  

    设置绘制文字x轴的缩放比例,可以实现文字的拉伸的效果    

    setTextSize(float textSize);  

    设置绘制文字的字号大小    

    setTextSkewX(float skewX);  

    设置斜体文字,skewX为倾斜弧度    

    setTypeface(Typeface typeface);  

    设置Typeface对象,即字体风格,包括粗体,斜体以及衬线体,非衬线体等   

    setUnderlineText(boolean underlineText);  

    设置带有下划线的文字效果    

    setStrikeThruText(boolean strikeThruText);  

    设置带有删除线的效果  

3.其他设置

    bitmapShader--位图平铺,常用来实现图片圆角的绘制

    linearGradient--线性渐变

    radialGradient--环形渐变

    sweepGradient--角度渐变

    composeShader--组合效果(组合以上几种)

三、Rect/RectF
   Rect和RectF用法一样,区别仅仅在于精度,一般用于设置绘图区域,
public RectF(float left, float top, float right, float bottom) {
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
    构造函数的四个参数表示,矩形的左边坐标,顶部坐标,右边坐标,底部坐标,这样就限定了矩形的大小,我们绘制的图像就在这个矩形里面。它还有一个构造方法,已现有的RectF对象作为参数,就相当于拷贝。
public RectF(RectF r) {
if (r == null) {
left = top = right = bottom = 0.0f;
    } else {
left = r.left;
top = r.top;
right = r.right;
bottom = r.bottom;
    }
}
    Rect/RectF了解这么多就行了。
四、实例
1.矩形
public class CustomView extends View {

    Paint mPaint;
    RectF rectF;

public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
        init();
    }

private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(false);// 不使用锯齿
mPaint.setColor(Color.GREEN);// 绿色
mPaint.setStyle(Paint.Style.FILL);// 填充
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(0, 250, 400, 450, mPaint);
    }
}


   也可以先生成RectF对象,然后传入该参数,效果是一样的。
rectF = new RectF(0, 250, 400, 450);
canvas.drawRect(rectF, mPaint);
2.圆
        canvas.drawCircle(200, 200, 100, mPaint);


3.圆弧
        canvas.drawArc(rectF, 0, 90, false, mPaint);


如果将第三个参数设为true,
rectF = new RectF(0,0,400,400);
canvas.drawArc(rectF, 0, 90, true, mPaint);


4.文字
public class CustomView extends View {

    Paint mPaint;
    RectF rectF;

public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
        init();
    }

private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(false);// 不使用锯齿
mPaint.setColor(Color.RED);// 红色
mPaint.setStyle(Paint.Style.FILL);// 填充
mPaint.setTextSize(64);
    }

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
        canvas.drawText("Test draw text!!!", 20, 200, mPaint);
    }
}


5.图像
    Bitmap bitmap = Bitmap.createBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.head));
    canvas.drawBitmap(bitmap, 100, 100, null);


    基本图形就举这几个例子,其他的drawXXX方法也是类似的使用,再看几个渐变效果,
Shader mLinearGradient = new LinearGradient(100, 100, 800, 100, new int[]{Color.YELLOW, Color.GREEN, Color.BLUE, Color.RED}, null, Shader.TileMode.REPEAT);
mPaint.setShader(mLinearGradient);
mPaint.setStrokeWidth(30);
canvas.drawLine(100, 100, 800, 100, mPaint);

Shader mRadialGradient = new RadialGradient(400, 400, 160, new int[]{Color.YELLOW, Color.GREEN, Color.BLUE, Color.RED}, null, Shader.TileMode.REPEAT);
mPaint.setShader(mRadialGradient);
canvas.drawCircle(400, 400, 160, mPaint);

Shader mSweepGradient = new SweepGradient(400, 800, new int[]{Color.YELLOW, Color.GREEN, Color.BLUE, Color.RED}, new float[]{0, 0.08f, 0.15f, 0.25f});
mPaint.setShader(mSweepGradient);
RectF rectF = new RectF(200,600,600,1000);
canvas.drawArc(rectF, 0, 360, true, mPaint);
    LinearGradient的构造函数,如下有两种,
public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
        TileMode tile)
public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,
        TileMode tile)
    第二种适用于两种颜色的渐变,第一种可以有多个颜色的渐变,还可以指定位置,参数具体含义,
@param x0           起始x坐标
@param y0 起始y坐标
@param x1 结束x坐标
@param y1 结束y坐标
@param colors 颜色数组
@param positions 位置数组,可以为空
@param tile Shader模式--CLAMP,REPEAT,MIRROR
    RadialGradient和SweepGradient的构造函数LinearGradient类似,不再赘述,还有一个组合模式ComposeShader,其实就是讲几种Shader组合起来使用
public RadialGradient(float centerX, float centerY, float radius,
           @NonNull int colors[], @Nullable float stops[], @NonNull TileMode tileMode)
public RadialGradient(float centerX, float centerY, float radius,
        int centerColor, int edgeColor, @NonNull TileMode tileMode)
public SweepGradient(float cx, float cy,
                     int colors[], float positions[])
public SweepGradient(float cx, float cy, int color0, int color1)



五、自定义一个扫描效果
   之前讲的几个例子都是绘制静态的图片,这里做一个动态扫描的动画,先贴效果图,

    其实就是一个扇形--drawArc,然后绕着圆心旋转--rotate,为了有一个渐变的效果,设置着色器--SweepGradient;然后用一个布尔变量
IsScanning来判断是否正在扫描,如果是的话,就将画布Canvas旋转一个角度,进行绘制,直到停止。按照这个思路就可以很容易把这个效果画出来了,代码如下。
package com.example.drawdemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * Created by dingfeng on 2016/6/13.
 */
public class ScanView extends View {

int width = 0; // View宽度,可在xml中设置android:layout_width="360dp"
int height = 0; // View高度,可在xml中设置android:layout_height="360dp"
Paint mPaint;
    RectF rectF;

float firstAngle = 0; //初始角度,3点钟方向是0度
float radian = 60; // 弧度,扫过的角度
float offsetArc = 0; // 偏移角度

boolean IsScanning = false;

public ScanView(Context context, AttributeSet attrs) {
super(context, attrs);
        init();
    }

private void init() {
mPaint = new Paint();
mPaint.setColor(Color.GREEN);
mPaint.setAntiAlias(false);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 注意,在构造函数中无法获取宽高的
width = getWidth();
height = getHeight();
int center = Math.min(width, height);
rectF = new RectF(0, 0, center, center); // 绘图区域
// 设置渐变色
Shader mShader = new SweepGradient(center / 2, center / 2, new int[]{Color.TRANSPARENT, Color.BLUE}, null);
mPaint.setShader(mShader);

if (IsScanning) {
            canvas.rotate(offsetArc, center / 2, center / 2);
            canvas.drawArc(rectF, firstAngle, radian, true, mPaint);
offsetArc = offsetArc + 3; // 每次增加3个角度
} else {
            canvas.rotate(offsetArc, center / 2, center / 2);
            canvas.drawArc(rectF, firstAngle, radian, true, mPaint);
        }

if (IsScanning) {
            invalidate();
        }
    }

public void start() {
IsScanning = true;
        invalidate();
    }

public void stop() {
IsScanning = false;
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值