您的位置:首页 > 移动开发 > Android开发

Android绘图

2016-06-14 14:14 337 查看
    在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;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android Canvas Paint