Android绘图
2016-06-14 14:14
337 查看
在Android开发过程中,常常需要自定义View,需要自己绘制图片效果或者需要一些动态效果,我们就可以使用Android提供的绘图工具进行绘制。绘图的三要素Canvas--画布,Paint--画笔,Rect/RectF--绘图区域,只要掌握了这几个要素就基本上可以满足我们大部分需求。
五、自定义一个扫描效果 之前讲的几个例子都是绘制静态的图片,这里做一个动态扫描的动画,先贴效果图,
其实就是一个扇形--drawArc,然后绕着圆心旋转--rotate,为了有一个渐变的效果,设置着色器--SweepGradient;然后用一个布尔变量
一、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/RectFRect和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; } }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories