【Android】21.2 2D图形图像处理(Canvas和Paint)

分类:C#、Android、VS2015;

创建日期:2016-03-19

一、Canvas对象简介

画布(Canvas对象)是与System.Drawing或iOS核心图形等传统框架非常类似的另一种图形图像绘制技术,该对象提供了创建2D图形的最大控制,利用它可解决难以处理画板资源的情况。例如,绘制自定义滑块控件的外观等。

可以把Canvas理解成系统提供给我们的一块内存区域(但实际上它只是一套绘图API,真正的内存是下面的Bitmap),而且它还提供了一整套对这个内存区域进行操作的方法,所有的这些操作都是绘图API。也就是说,在这种方式下我们已经能一笔一划或者使用Graphic来绘制我们需要的东西了,要画什么要显示什么都由我们自己来控制。

1、Canvas API

画板(Drawables)虽然强大但有其局限性,有些复杂的功能无法用它来实现。例如,将滤镜应用于由设备上的照相机拍摄的图片实现红眼特效等。要实现这些功能,可利用Canvas API对其进行细粒度控制,这样就可以有选择性地改变图片的特定部分中的颜色。

Canvas API绘制2D图形非常类似于画家在模型的不同部分一层一层地涂抹不同颜色的油漆。或者说,对Canvas的每个绘制操作都将覆盖底层位图的一部分,如果和原来绘制的部分重叠则覆盖。

2、获取Canvas对象

有两种方式得到一个Canvas对象。

(1)第1种方式

定义Bitmap对象,然后实例化一个Canvas对象。例如:

Bitmap bitmap = Bitmap.CreateBitmap(100, 100, Bitmap.Config.Argb8888);

Canvas canvas = new Canvas(b);

(2)第2种方式

通过重写视图类的OnDraw()回调方法获取一个Canvas对象。

3、操作Canvas对象

得到Canvas对象后,就可以对它进行操作了,例如:

l Canvas.DrawPaint(Paint p) – 用指定的Paint对象填充整个位图画布。

l Canvas.DrawPath(Path path, Paint paint) –用指定的Paint对象绘制指定的几何形状。

l Canvas.DrawText(String text, float x, float y, Paint paint) –用指定的Paint对象在画布的(x,y)坐标处绘制文本,比如用Paint对象指定颜色等。

二、Paint对象常用属性和方法

Canvas是通过Paint对象来操作的,所以这里先说一下Paint对象的基本用法。

Paint用于指定图形或者文字的颜色、大小等。常用属性和方法如下。

1、消除锯齿

AntiAlias属性:是否消除锯齿,true:消除锯齿,false:不消除。

2、画笔颜色

Color属性:获取或设置颜色。

3、alpha不透明度

Alpha属性:获取或设置alpha不透明度,范围为0~255。

4、字体大小

TextSize属性:获取或设置字体大小。

5、轮廓和填充

SetStyle()方法:设置画笔样式,是绘制轮廓还是填充。

StrokeWidth属性:获取或设置轮廓的宽度。

6、设置Paint对象颜色

SetARGB(int a, int r, int g, int b)

设置 Paint对象颜色,参数1为alpha不透明度(0~255)。

7、设置文本缩放倍数

SetTextScaleX(float scaleX)

设置文本缩放倍数,1.0f为原始大小。

8、设置下划线

SetUnderlineText(booleanunderlineText)

三、Canvas基本用法

这种方式根据环境还分为两种:一种就是使用普通View的canvas画图,还有一种就是使用专门的SurfaceView的canvas来画图。两种的主要是区别就是可以在SurfaceView中定义一个专门的线程来完成画图工作,应用程序不需要等待View的刷图,提高性能。前面一种适合处理量比较小,帧率比较小的动画,比如说象棋游戏之类的;而后一种主要用在游戏,高品质动画方面的画图。

下面是Canvas类常用的方法。

1、绘制矩形

DrawRect(RectF rect, Paint paint)

绘制矩形区域,参数rect表示一个居心的大小。

2、绘制路径

DrawPath(Path path, Paint paint)

绘制一个路径,参数path为路径对象。

3、贴图

DrawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)

参数bitmap是Bitmap对象,参数src是源区域(这里是bitmap),参数dst是目标区域(应该在canvas的位置和大小),参数paint是Paint画刷对象。

注意如果缩放和拉伸,当原始Rect不等于目标Rect时,该方法的性能将会有大幅损失。

4、画线

DrawLine(float startX, float startY, float stopX, float stopY, Paintpaint)

前两个参数是起始点的x、y坐标位置,后两个参数是终点的x、y坐标位置,最后一个参数为Paint 画刷对象。

5、画点

DrawPoint(float x, float y, Paint paint)

前两个参数为x、y坐标,第3个参数为Paint对象。

6、绘制文字

drawText(String text, float x, floaty, Paint paint)

Canvas类除了上面的还可以描绘文字,参数一是string类型的文本,参数2是x轴,参数3是y轴,参数4是Paint对象。

7、画椭圆

DrawOval(RectF oval, Paint paint)

参数1是椭圆的外切矩形,参数2为paint对象;

8、画圆

drawCircle(float cx, float cy, float radius,Paint paint)

参数1是中心点的x轴,参数2是中心点的y轴,参数3是半径。

9、画弧

drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

参数1是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数2是起始角(度)在电弧的开始,参数3扫描角(度)开始顺时针测量的,参数4如果为true则包括椭圆中心的电弧并关闭它,如果为false表示这是一个弧线;参数5是Paint对象;

四、使用Shader类渲染图形

你可能经常看到某些界面(比如屏幕保护或者播放器)中有一些非常绚丽的图形,其实这些都是在原有图形的基础上进行渲染的效果。

Android提供了一个Shader类来实现渲染效果,这是一个抽象类,其子类很多,比如BitmapShader类(位图渲染)、ComposeShader类(混合渲染)、LinearGradient类(线性渲染)、RadialGradient类(仿射渲染)、SweepGradient类(梯度渲染)等。通过Paint对象的SetShader()方法可设置使用的这些渲染对象。

下面的代码演示了其基本用法:

Paint p = new Paint();

Shader mShader = new LinearGradient(0, 0, 100, 100,

new int[] { Color.Red, Color.Green, Color.Yellow, Color.LightGray }, null, Shader.TileMode.Repeat);

p.SetShader(mShader);

五、示例

1、运行截图

image

2、设计步骤

(1)添加ch2102Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:id="@+id/ch2102_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

(2)添加ch2102MainActivity.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace MyDemos.SrcDemos
{
    [Activity(Label = "【例21-2】Canvas基本用法")]
    public class ch2102MainActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            SetContentView(Resource.Layout.ch2102Main);
            var layout = FindViewById<LinearLayout>(Resource.Id.ch2102_root);
            MyView view = new MyView(this);
            view.SetMinimumWidth(layout.Width - 20);
            view.SetMinimumHeight(layout.Height - 20);
            layout.AddView(view);
        }
    }

    public class MyView : View
    {
        private Context context;

        public MyView(Context context) : base(context)
        {
            this.context = context;
        }

        private void DrawText(Canvas canvas, string text, int x, int y)
        {
            using (Paint p = new Paint())
            {
                p.Color = Color.Black;
                p.TextSize = 24;
                p.AntiAlias = true;   // 消除锯齿  
                canvas.DrawText(text, x, y, p);
            }
        }

        protected override void OnDraw(Canvas canvas)
        {
            base.OnDraw(canvas);

            Color drawColor = Color.Red;
            Paint p = new Paint();
            p.Color = drawColor;
            int x1 = 40, y1 = 60, dy = 80;

            DrawText(canvas, "画圆和直线:", x1, y1);
            canvas.DrawCircle(x1 + 300, y1 + 20, 20, p);// 小圆  
            canvas.DrawCircle(x1 + 400, y1 + 20, 40, p);// 大圆  
            canvas.DrawLine(0, y1 + 20, 600, y1 + 20, p);// 画线  

            y1 += dy;
            DrawText(canvas, "画弧线:", x1, y1);
            p.SetStyle(Paint.Style.Stroke);//仅绘制轮廓
            RectF oval1 = new RectF(x1 + 150, y1, x1 + 180, y1 + 30);
            canvas.DrawArc(oval1, 180, 180, false, p);//小弧形  
            oval1.Set(x1 + 190, y1, x1 + 220, y1 + 30);
            canvas.DrawArc(oval1, 180, 180, false, p);//小弧形  
            oval1.Set(x1 + 160, y1 + 45, x1 + 210, y1 + 60);
            canvas.DrawArc(oval1, 0, 180, false, p);//小弧形  

            y1 += dy;
            DrawText(canvas, "画矩形:", x1, y1);
            p.SetStyle(Paint.Style.Fill);//仅填充
            canvas.DrawRect(x1 + 100, y1, x1 + 160, y1 + 60, p);// 正方形  
            canvas.DrawRect(x1 + 200, y1, x1 + 360, y1 + 60, p);// 长方形  

            y1 += dy;
            DrawText(canvas, "画扇形和椭圆:", x1, y1);
            Shader mShader = new LinearGradient(0, 0, 100, 100,
                new int[] { Color.Red, Color.Green, Color.Black, Color.Yellow, Color.LightGray },
                null, Shader.TileMode.Repeat);
            p.SetShader(mShader);
            RectF oval2 = new RectF(x1 + 100, y1, x1 + 200, y1 + 50);// 设置个新的长方形,扫描测量  
            //true:画扇形,false:画弧线
            canvas.DrawArc(oval2, x1 + 300, y1 + 30, true, p);
            //画椭圆
            oval2.Set(x1 + 350, y1, x1 + 380, y1 + dy);
            canvas.DrawOval(oval2, p);
            //true:画扇形,false:画弧线
            RectF oval3 = new RectF(x1 + 450, y1, x1 + 500, y1 + 30);
            canvas.DrawArc(oval3, x1 + 480, y1 + 30, true, p);

            y1 += dy;
            DrawText(canvas, "画三角形:", x1, y1);
            Path path = new Path();
            path.MoveTo(x1 + 180, y1);// 起点(顶角所在的点)  
            path.LineTo(x1 + 80, y1 + 50);
            path.LineTo(x1 + 260, y1 + 50);
            path.Close(); // 使这些点构成封闭的多边形
            canvas.DrawPath(path, p);

            y1 += dy;
            DrawText(canvas, "画多边形:", x1, y1);
            // 画六连形(可绘制任意多边形)
            p.SetStyle(Paint.Style.Stroke);//仅绘制轮廓
            Path path1 = new Path();
            path1.MoveTo(x1 + 300, y1); //左上角
            path1.LineTo(x1 + 350, y1);  //上面横线
            path1.LineTo(x1 + 400, y1 + 40); //右上方斜线
            path1.LineTo(x1 + 400, y1 + 80); //右方竖线
            path1.LineTo(x1 + 350, y1 + 120); //右下方斜线
            path1.LineTo(x1 + 300, y1 + 120);  //下方横线
            path1.Close(); //封闭  
            canvas.DrawPath(path1, p);

            y1 += dy + 50;
            DrawText(canvas, "画圆角矩形:", x1, y1);
            p.SetStyle(Paint.Style.Fill);//填充
            RectF oval4 = new RectF(x1 + 80, y1, x1 + 280, y1 + 50);
            //20:横向圆角的角度,15:纵向圆角的角度
            canvas.DrawRoundRect(oval4, 20, 15, p);

            y1 += dy;
            DrawText(canvas, "贴图:", x1, y1);
            Bitmap bitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.ch03ic_launcher);
            canvas.DrawBitmap(bitmap, x1 + 200, y1, p);
        }
    }
}
posted @ 2016-03-19 12:18  rainmj  阅读(1153)  评论(0编辑  收藏  举报