李琳琳 發表於 2024-7-25 22:05:00

Android开发 - Canvas类与Paint画笔与Draw绘制方法详解与使用

<h1 id="canvas类是什么">Canvas类是什么</h1>
<ul>
<li><strong>Android</strong>中<strong>Canvas类</strong>常用于<strong>自定义View</strong>等操作中,<strong>Canvas</strong>则如同一张<strong>画布</strong>可以在上面绘制内容,然后这张画布也可以叠加其他的图层或者平移旋转等操作。<strong>Canvas对象</strong>的获取方式有两种:一种我们通过重写<strong>onDraw方法</strong>,<strong>View</strong>中重写<code>onDraw(Canvas canvas)</code><strong>Canvas对象</strong>会被当做参数传递过来,我们操作这个<strong>Canvas</strong>,效果会直接反应在<strong>View</strong>中(<strong>我们也可以在ViewGroup中对Canvas做操作,然后将这个Canvas通过<code>diapatchDraw(Canvas canvas)</code>的方式传递给子View,子View将会按照Canvas的规则去绘制</strong>);另一种就是<strong>new</strong>的方式去创建。<strong>Canvas类</strong>持有“<strong>draw</strong>”调用。要绘制内容需要4个基本组件:一个用于持有像素的<strong>Bitmap</strong>,一个用于承载绘制调用的<strong>Canvas</strong>(<strong>写入位图</strong>),一个绘制图元(例如<strong>矩形(Rect)</strong>,<strong>路径(Path)</strong>,<strong>文本(text)</strong>,<strong>位图(Bitmap)</strong>)和一个<strong>画笔(Paint)</strong>( <strong>描述图纸的颜色和样式</strong>)</li>
</ul>
<h1 id="绘制需要什么">绘制需要什么</h1>
<h2 id="paint画笔">paint(画笔)</h2>
<ul>
<li><strong>画笔提供了最基础的绘画功能,颜色、画笔大小、样式等。我们只需要简单的设计几个参数就可以使用</strong>:
<ul>
<li><strong><code>setColor();</code></strong>:设置画笔的<strong>颜色</strong></li>
<li><strong><code>setAntiAlias();</code></strong>:设置画笔的<strong>锯齿效果</strong></li>
<li><strong><code>setARGB();</code></strong>:设置画笔的<strong>A</strong>、<strong>R</strong>、<strong>G</strong>、<strong>B颜色值</strong></li>
<li><strong><code>setAlpha();</code></strong>:设置画笔的<strong>Alpha值</strong></li>
<li><strong><code>setTextSize();</code></strong>:设置<strong>字体的尺寸</strong></li>
<li><strong><code>setStyle();</code></strong>:设置画笔的<strong>风格(空心或实心)</strong></li>
<li><strong><code>setStrokeWidth();</code></strong>:设置<strong>空心边框的宽度(线宽)</strong></li>
</ul>
</li>
</ul>
<h2 id="canvas画布">canvas(画布)</h2>
<h3 id="canvas-常用的api"><strong>canvas 常用的API</strong></h3>
<h4 id="绘制画笔drawpaint">绘制画笔:drawPaint</h4>
<ul>
<li>
<p><strong><code>drawPaint(Paint paint)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>paint</strong>:这个画笔绘制出来就是当前<strong>view</strong>的颜色,填充满整个画布</li>
</ul>
</li>
</ul>
<h5 id="代码实例">代码实例</h5>
<pre><code class="language-java">private void drawPaint(Canvas canvas) {
    canvas.drawPaint(paint);
}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724122754_10.png"></p>
</li>
</ul>
<h4 id="绘画圆弧drawarc">绘画圆弧:drawArc</h4>
<ul>
<li><strong><code>canvas:drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)</code></strong>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>RectF</strong>:画布的大小</li>
<li><strong>startAngle</strong>: 开始角度,这个值只能决定图形的开始角度,不能改变图的开角角度。</li>
<li><strong>sweepAngle</strong>:扫描的角度,正常就是图形的角度</li>
<li><strong>useCenter</strong>:是否以中心旋转,如果是,画中的扇形中心在圆中心,否则就是一个普通的扇形</li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>​       <img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724023222_1.gif"></p>
<h5 id="拼色扇形实例"><strong>拼色扇形实例</strong></h5>
<ul>
<li>
<p>像一些统计图其实是通过<strong>绘制圆弧</strong>完成的,但是绘制的时候<strong>需要注意图层问题</strong>:<strong>Canvas</strong>是一层一层绘制的,如果处理多图形拼图,最大层应该在最下方</p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724025816_2.png"></p>
<h6 id="代码实例-1">代码实例</h6>
<pre><code class="language-java">RectF rectF = new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight());


if (paint == null) {
    paint = new Paint();
}

paint.setColor(Color.RED);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.FILL);

canvas.drawArc(rectF, 0, 360, true, paint);
canvas.save();
paint.setColor(Color.YELLOW);
canvas.drawArc(rectF, 0, 150, true, paint);
paint.setColor(Color.BLUE);
canvas.drawArc(rectF, 0, 90, true, paint);

paint.setColor(Color.GRAY);
canvas.drawArc(rectF, 0, 30, true, paint);
</code></pre>
<ul>
<li>
<p><strong>这里面有四种扇形,红色、黄色、绿色、灰色</strong>:</p>
<ul>
<li>
<p>灰色开角:30</p>
</li>
<li>
<p>绿色开角:90</p>
</li>
<li>
<p>黄色开角:150</p>
</li>
<li>
<p>红色开角:360(圆形)</p>
</li>
</ul>
</li>
<li>
<p><strong>视觉上</strong>:</p>
<ul>
<li>灰色:30°
<ul>
<li>绿色:60°</li>
<li>黄色:60°</li>
<li>红色:210°</li>
</ul>
</li>
</ul>
</li>
</ul>
<h6 id="技巧">技巧</h6>
<ul>
<li><strong>先算出各个角度,再计算出各个扇形的开角。注意先绘制大图形,再绘制小的,否则360°先绘制会导致图形的遮挡问题</strong></li>
</ul>
</li>
</ul>
<h4 id="绘制路径drawpath">绘制路径:drawPath</h4>
<ul>
<li>
<p><strong><code>canvas.drawPath(Path path,Paint paint)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li>
<p><strong>path</strong>:路径值,又因为<strong>path</strong>可以完成各种路径的构建</p>
</li>
<li>
<p><strong>paint</strong>:画笔</p>
</li>
</ul>
</li>
</ul>
</li>
<li>
<p><strong>正常path绘制很多东西,如果一个画面由三个点组成</strong></p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724031929_3.png"></p>
<h5 id="代码实例-2">代码实例</h5>
<pre><code class="language-java">private void drawPath(Canvas canvas) {
    Path path = new Path();
    path.moveTo(100, 100);
    path.lineTo(300, 300);
    path.lineTo(200,300);
    path.close();

    canvas.drawPath(path, paint);
}
</code></pre>
</li>
</ul>
<h4 id="组合绘图drawpicture">组合绘图:drawPicture</h4>
<ul>
<li><strong><code>canvas.drawPicture(Picture picture)</code></strong>:绘制复杂的图形或者需要耗时较长,可以通过该方法
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>picture</strong>:图片或者海报</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="绘制色块drawargb">绘制色块:drawARGB</h4>
<ul>
<li>
<p><strong><code>canvas.drawARGB(int a, int r, int g, int b)</code></strong>:这个色块类似一个填充色,以<strong>ARGB颜色</strong>来完成。值可以参考色值:<strong>0-255,2^8-1</strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>a</strong>:透明度</li>
<li><strong>r</strong>:红色</li>
<li><strong>g</strong>:绿色</li>
<li><strong>b</strong>:蓝色</li>
</ul>
</li>
</ul>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724040535_4.png"></p>
</li>
</ul>
<h4 id="绘制bitmap资源drawbitmap">绘制bitmap资源:drawBitmap</h4>
<ul>
<li>
<p><strong><code>canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>bitmap</strong>:<strong>bitmap</strong>资源</li>
<li><strong>left</strong>:从布局左边的坐标点(类似<strong>View</strong>的<strong>X轴</strong>)开始绘制</li>
<li><strong>top</strong>:从布局的顶部的坐标点(类似<strong>View</strong>的<strong>Y轴</strong>)开始绘制</li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
</ul>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724041115_5.png"></p>
<h5 id="代码实例-3">代码实例</h5>
<pre><code class="language-java">private void drawBitmap(Canvas canvas)
{
    canvas.drawBitmap(getBitmap(),0,0,paint);
    canvas.save();
}
</code></pre>
</li>
</ul>
<h4 id="图片扭曲特效drawbitmapmesh">图片扭曲特效:drawBitmapMesh</h4>
<ul>
<li>
<p><strong><code>canvas.drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, colors, int colorOffset, Paint paint)</code></strong></p>
<ul>
<li>
<p><strong>参数解析</strong>:</p>
<ul>
<li><strong>bitmap</strong>:指定需要扭曲的源位图。</li>
<li><strong>meshwidth</strong>:该参数控制在横向上把该源位图划分成多少格</li>
<li><strong>meshheight</strong>:该参数控制在纵向上把该源位图划分成多少格</li>
<li><strong>verts</strong>:该参数是一个长度为<code>(meshWidth + 1)*(meshHeight+1)* 2</code>的数组,它记录了扭曲后的位图各"<strong>顶点</strong>"位置。虽然它是个一维数组,实际上它记录的数据是形如<code>(x0, y0),(x1, y1),(x2, y2)......(xN, yN)</code>格式的数据,这些数组元素控制对<strong>bitmap位图</strong>的扭曲效果</li>
<li><strong>vertOffset</strong>:vert的偏移,也就是控制<strong>verts数组</strong>中从第几个数组元素开始才对<strong>bitmap</strong>进行扭曲(<strong>忽略veroffset之前数据的扭曲效果</strong>)</li>
</ul>
</li>
<li>
<p><strong>drawBitmapMesh方法</strong>对源位图扭曲时最关键的参数是<strong>meshWidth</strong>、<strong>meshHeight</strong>和<strong>verts</strong>这三个参数对扭曲的控制,如下图:</p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724060727_6.png"></p>
</li>
<li>
<p>从上图可以看出,当程序希望调用<strong>drawBitmapMesh方法</strong>对位图进行扭曲时,关键是计算<strong>verts数组</strong>的<strong>值(该数组的值记录了扭曲后的位图上各"顶点"的坐标)</strong></p>
</li>
</ul>
<h5 id="代码实例-4">代码实例</h5>
<ul>
<li>
<p>下面的实例是通过<strong>drawBitmapMesh方法</strong>来控制图片的扭曲</p>
<ol>
<li>
<p>自定义<strong>MeshView</strong>组件</p>
<pre><code class="language-java">package com.example.matrixdemo.view;

import com.example.matrixdemo.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/***
* 通过Canvas的drawBitmapMesh方法控制图片的扭曲效果
* @author Administrator
*
*/
public class MyMeshView extends View {
        /** 源图片 */
        private Bitmap bitmap;
        /** 定义常量,常量指定该图片横向上被分为20格 */
        private final int MESH_WIDTH = 20;
        /** 定义常量,常量指定该图片纵向上被分为20格 */
        private final int MESH_HEIGHT = 20;
        /** 记录该图片上包含的441个顶点 */
        private final int COUNT = (MESH_WIDTH + 1) * (MESH_HEIGHT + 1);
        /** 定义一个数组,保存Bitmap上的21*21个点的坐标 */
        private float[] verts = new float;
        /** 定义一个数组,保存Bitmap上的21*21个点经过扭曲后的坐标 */
        // 对图片进行扭曲的关键就是修改该数组里元素的值
        private float[] orig = new float;

        public MyMeshView(Context context) {
                this(context, null);
        }

        public MyMeshView(Context context, AttributeSet attrs) {
                this(context, attrs, 0);
        }

        public MyMeshView(Context context, AttributeSet attrs, int defStyleAttr) {
                super(context, attrs, defStyleAttr);
                setFocusable(true);
                // 加载Bitmap资源
                bitmap = ((BitmapDrawable) getResources().getDrawable(
                                R.drawable.bg02)).getBitmap();
                // 获取图片的宽度,高度
                float bitmapWidth = bitmap.getWidth();
                float bitmapHeight = bitmap.getHeight();
                int index = 0;
                for (int i = 0; i &lt;= MESH_HEIGHT; i++) {
                        float fy = bitmapHeight * i / MESH_HEIGHT;
                        for (int j = 0; j &lt; MESH_WIDTH; j++) {
                                float fx = bitmapWidth * i / MESH_WIDTH;
                                // 初始化orig,verts数组,初始化后,orig,verts两个数组均匀的保存了21*21个点的坐标
                                orig = verts = fx;        //偶数
                                orig = verts = fy;        //奇数
                                index += 1;
                        }
                }
                // 设置背景色
                setBackgroundColor(Color.WHITE);
        }

        @Override
        protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                canvas.drawBitmapMesh(bitmap, MESH_WIDTH, MESH_HEIGHT, verts, 0,
                                null, 0, null);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
                //调用warp方法根据触摸屏事件的坐标来扭曲verts数组
                warp(event.getX(), event.getY());
                return true;
        }

        /***
       * 根据触摸事件的位置计算verts数组里个元素的值
       *
       * @param x
       *            X坐标
       * @param y
       *            Y坐标
       */
        private void warp(float cx, float cy) {
                for (int i = 0; i &lt; MESH_WIDTH * 2; i += 2) {
                        float dx = cx - orig;
                        float dy = cy - orig;
                        float dd = dx * dx + dy * dy;
                        //计算每个坐标点与当前坐标点(cx,cy)之间的距离
                        float d = (float) Math.sqrt(dd);
                        //计算扭曲度,距离当前点(cx,cy)越远,扭曲度越小
                        float pull = 80000 / (dd * d);
                        //对verts数组(保存bitmap上21*21进过扭曲后的坐标)重新赋值
                        if(pull &gt;= 1){
                                verts = cx;
                                verts = cy;
                        }else{
                                //控制各个顶点向触摸事件发生点进行偏移
                                verts = orig * dx * pull;
                                verts = orig * dy * pull;
                        }
                }
                //通知view组件重绘
                invalidate();
        }
       
}
</code></pre>
</li>
<li>
<p><strong>activity</strong>调用以及布局</p>
<ul>
<li>
<p><strong>Java调用</strong></p>
<pre><code class="language-java">package com.example.matrixdemo;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class MeshActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_mesh);
        }
}
</code></pre>
</li>
<li>
<p><strong>xml布局</strong></p>
<pre><code class="language-xml">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" &gt;.
   
    &lt;com.example.matrixdemo.view.MyMeshView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"/&gt;
   
&lt;/LinearLayout&gt;
</code></pre>
</li>
</ul>
</li>
</ol>
</li>
<li>
<p>上面的程序中,<strong>warp方法</strong>会根据触摸点的位置动态修改<strong>verts数组</strong>里所有数组元素的<strong>值</strong>,这样就控制了<strong>drawBitmapMesh方法</strong>的扭曲效果</p>
</li>
</ul>
</li>
</ul>
<h4 id="画圆drawcircle">画圆:drawCircle</h4>
<ul>
<li>
<p><strong><code>canvas.drawCircle(float cx, float cy, float radius, Paint paint)</code></strong></p>
<ul>
<li><strong>参数解析</strong>
<ul>
<li><strong>cx</strong>:圆心<strong>x轴</strong>坐标</li>
<li><strong>cy</strong>:圆心<strong>y轴</strong>坐标</li>
<li><strong>radius</strong>:半径</li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
</ul>
<h5 id="代码实例-5">代码实例</h5>
<pre><code class="language-java">canvas.drawCircle(100, 100, 100, paint);
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724063140_7.png"></p>
</li>
</ul>
<h4 id="划线drawline">划线:drawLine</h4>
<ul>
<li>
<p><strong><code>canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint)</code></strong></p>
<ul>
<li>
<p>参数解析:</p>
<ul>
<li>
<p>startX:起点x坐标</p>
</li>
<li>
<p>startY:起点y坐标</p>
</li>
<li>
<p>stopX:终点x坐标</p>
</li>
<li>
<p>stopY:终点y坐标</p>
</li>
<li>
<p>paint:画笔</p>
</li>
</ul>
</li>
</ul>
<h5 id="代码实例-6">代码实例</h5>
<pre><code class="language-java">private void drawLine(Canvas canvas) {
    paint.setStrokeWidth(100);
    canvas.drawLine(0, 500, 500, 500, paint);
}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724115022_8.png"></p>
<ul>
<li>由于线段是两点确定,所以<strong>(startX,startY)是起点</strong>,<strong>(stopX,stopY)是终点</strong></li>
<li><strong>如果想这条线很宽。通过设置画笔的宽度</strong> <code>paint.setStrokeWidth(100);</code></li>
</ul>
</li>
</ul>
<h4 id="画椭圆drawoval">画椭圆:drawOval</h4>
<ul>
<li>
<p><strong><code>canvas.drawOval(RectF oval, Paint paint)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>oval</strong>:设置一个矩形区域,扫描测量</li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
</ul>
</li>
<li>
<p><strong><code>canvas.drawOval(float left, float top, float right, float bottom, Paint paint)</code></strong></p>
<ul>
<li>
<p><strong>参数解析</strong>:</p>
<ul>
<li>
<p><strong>left</strong>:左边坐标;在绘制中常表示为起点的<strong>Y轴</strong>坐标</p>
</li>
<li>
<p><strong>top</strong>:上边左边;在绘制中常表示为起点的<strong>X轴</strong>坐标</p>
</li>
<li>
<p><strong>right</strong>:右边坐标;在绘制中常表示为终点的<strong>Y轴</strong>坐标</p>
</li>
<li>
<p><strong>bottom</strong>:下边坐标;在绘制中常表示为终点的<strong>Y轴</strong>坐标</p>
</li>
<li>
<p><strong>paint</strong>:画笔</p>
</li>
</ul>
</li>
</ul>
</li>
<li>
<p>第二种方法的<strong>前4个参数</strong>实际上就是<strong>RectF</strong>类的参数,<strong>同样是创建一个矩形扫描测量区域进行放置一个椭圆</strong></p>
</li>
</ul>
<h5 id="代码实例-7">代码实例</h5>
<pre><code class="language-java">private void drawOval(Canvas canvas) {
    int width=getMeasuredWidth();
    int height=getMeasuredHeight()/3;

    canvas.drawOval(0,0,width,height,paint);
}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724122130_9.png"></p>
<h3 id="绘制补丁drawpatch">绘制补丁:drawPatch</h3>
<ul>
<li>
<p><strong><code>canvas.drawPatch(NinePatch patch, Rect dst, Paint paint)</code></strong></p>
<ul>
<li><strong>参数详解</strong>:
<ul>
<li><strong>patch</strong>:点九资源(.9.png),</li>
<li><strong>dst</strong>:绘制区域</li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
</ul>
</li>
<li>
<p><strong>此方法资料很少,估计是不太常用,简单了解一下即可</strong>:[点九资源](android draw9 patch介绍_android studio canvas drawpatch-CSDN博客)</p>
<h5 id="代码实例-8">代码实例</h5>
<pre><code class="language-java">Bitmap bitmap = getBitmap();
NinePatch patch = new NinePatch(bitmap,bitmap.getNinePatchChunk());
canvas.drawPatch(patch, dst, paint)
</code></pre>
</li>
</ul>
<h4 id="绘制点drawpoint">绘制点:drawPoint</h4>
<ul>
<li>
<p><strong><code>canvas.drawPoint(float x, float y, Paint paint)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>x</strong>:点的<strong>x轴坐标</strong>位置</li>
<li><strong>y</strong>:点的<strong>y轴坐标</strong>位置</li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
</ul>
</li>
<li>
<p><strong>点的大小取决于paint的画笔大小</strong></p>
<h5 id="代码实例-9">代码实例</h5>
<pre><code class="language-java">private void drawPoint(Canvas canvas) {
    paint.setStrokeWidth(20);
    canvas.drawPoint(100, 100, paint);
}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724125905_1.png"></p>
</li>
</ul>
<h4 id="绘制文字从点pos出发drawpostext">绘制文字从点pos出发:drawPosText</h4>
<ul>
<li>
<p><strong><code>canvas.drawPosText(String text, @Size(multiple = 2) float[] pos, Paint paint)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>text</strong>:文本</li>
<li><strong>pos</strong>:<strong>pos坐标(x,y)</strong></li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
</ul>
<h5 id="代码实例-10">代码实例</h5>
<pre><code class="language-java">    private void drawPosText(Canvas canvas) {

      float[] pos = new float[]{100, 100};
      canvas.drawPosText("Hellow", pos, paint);

    }
</code></pre>
</li>
</ul>
<h4 id="绘制矩形区域drawrect">绘制矩形区域:drawRect</h4>
<ul>
<li>
<p><strong><code>canvas.drawRect(RectF rect, Paint paint)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>RectF</strong>:绘制区域</li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
</ul>
<h5 id="代码实例-11">代码实例</h5>
<pre><code class="language-java">private void drawRect(Canvas canvas) {
    RectF rectF=new RectF(0,0,500,500);
    canvas.drawRect(rectF,paint);

}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724131042_2.png"></p>
</li>
</ul>
<h4 id="绘制色域drawrgbdrawcolor">绘制色域:drawRGB、drawColor</h4>
<ul>
<li>
<p><strong><code>canvas.drawRGB(int r, int g, int b)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>r</strong>:<strong>rgb颜色值的r值</strong></li>
<li><strong>g</strong>:<strong>rgb颜色值的g值</strong></li>
<li>b:<strong>rgb颜色值的b值</strong></li>
</ul>
</li>
</ul>
</li>
<li>
<p><strong><code>canvas.drawColor(int color)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>color</strong>:</li>
</ul>
</li>
</ul>
</li>
<li>
<p>以下只举例其一</p>
<h5 id="代码实例-12">代码实例</h5>
<pre><code class="language-java">public void drawRGB(Canvas canvas) {
    canvas.drawRGB(200, 200, 200);
}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724131735_fc475020a99446a38c2db31861201265.png"></p>
</li>
</ul>
<h4 id="在矩形内绘制圆角drawroundrect">在矩形内绘制圆角:drawRoundRect</h4>
<ul>
<li>
<p><strong><code>canvas.drawRoundRect(RectF rect, float rx, float ry, Paint paint)</code></strong></p>
<ul>
<li>
<p><strong>参数解析</strong>:</p>
<ul>
<li>
<p><strong>RectF</strong> :绘制区域</p>
</li>
<li>
<p><strong>rx</strong>:圆角角度在矩形内的<strong>坐标x轴</strong></p>
</li>
<li>
<p><strong>ry</strong>:圆角角度在矩形内的<strong>坐标y轴</strong></p>
</li>
<li>
<p><strong>paint</strong>:画笔</p>
</li>
</ul>
</li>
</ul>
<h5 id="注意事项"><strong>注意事项</strong></h5>
<ul>
<li>如果<strong>rx和ry为0</strong>,那么绘制出来的view就是<strong>矩形</strong>,如果<strong>rx,ry在矩形正中心</strong>,那么绘制出来的圆角就是<strong>圆形</strong></li>
<li>如果<strong>x和y都小于矩形的宽和高</strong>,那么显示就是<strong>矩形四个角被裁剪</strong></li>
<li>如果<strong>x和y都大于矩形的宽和高</strong>,那么显示就是<strong>圆</strong></li>
<li>如果<strong>x和y其中一个小于宽和高</strong>,那么显示可能是一个<strong>不规则图形</strong></li>
</ul>
<h5 id="代码实例-13">代码实例</h5>
<pre><code class="language-java">public void drawRoundRect(Canvas canvas)
{
    RectF rectF=new RectF(0,0,200,200);
    canvas.drawRoundRect(rectF,10,10,paint);
}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724132407_c8e477d0edc74f69ad8ab31bd99169c7.png"></p>
</li>
</ul>
<h4 id="绘制字符drawtext">绘制字符:drawText</h4>
<ul>
<li>
<p><strong><code>canvas.drawText(String text, float x, float y, Paint paint)</code></strong></p>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>text</strong>:文本</li>
<li><strong>x</strong>:位置的<strong>x轴坐标</strong></li>
<li><strong>y</strong>:位置的<strong>y轴坐标</strong></li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
</ul>
<h5 id="注意事项-1">注意事项</h5>
<ul>
<li>绘制的时候<strong>paint style(画笔风格)</strong>必须设置成<code>paint.setStyle(Paint.Style.FILL);</code>否则会出现一团</li>
<li>文字的<strong>样式和大小</strong>,都是通过<strong>paint(画笔)</strong>来设置,关于<strong>paint</strong>可以自行查看</li>
</ul>
<h5 id="代码实例-14">代码实例</h5>
<pre><code class="language-java">private void drawText(Canvas canvas)
{
    paint.setTextSize(100);
    canvas.drawText("你好",100,100,paint);
}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724133003_507.png"></p>
</li>
</ul>
<h4 id="绘制文本按路径显示drawtextonpath">绘制文本按路径显示:drawTextOnPath</h4>
<ul>
<li>
<p><strong><code>canvas.drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)</code></strong></p>
<ul>
<li>
<p><strong>参数解析</strong>:</p>
<ul>
<li>
<p><strong>text</strong> :文本</p>
</li>
<li>
<p><strong>path</strong>:路径,最终文本文字会按路径显示</p>
</li>
<li>
<p><strong>hOffset</strong> :横向偏移,沿路径添加到文本起始位置的距离</p>
</li>
<li>
<p><strong>vOffset</strong> :纵向偏移,定位文本的路径<strong>上方(-)</strong>或<strong>下方(+)</strong>的距离</p>
</li>
<li>
<p><strong>paint</strong>:画笔</p>
</li>
</ul>
</li>
</ul>
<h5 id="代码实例-15">代码实例</h5>
<pre><code class="language-java">private void drawTextOnPath(Canvas canvas) {
    paint.setTextSize(100);
    Path path=new Path();
    path.moveTo(0,500);
    path.lineTo(500,500);
    path.lineTo(500,0);
    path.close();
    canvas.drawTextOnPath("Hello word just do it",path,100,100,paint);
}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724133658_344.png"></p>
</li>
</ul>
<h4 id="绘制运行中的文本drawtextrun">绘制运行中的文本:drawTextRun</h4>
<ul>
<li>
<p><strong><code>canvas.drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl,Paint paint)</code></strong></p>
<ul>
<li>
<p><strong>参数解析</strong>:</p>
<ul>
<li>
<p><strong>text</strong>:文本</p>
</li>
<li>
<p><strong>start</strong>:内容开始索引</p>
</li>
<li>
<p><strong>end</strong>:内容结束的索引</p>
</li>
<li>
<p><strong>contextStart</strong>:塑造语句的起点索引,<strong>默认从0开始</strong></p>
</li>
<li>
<p><strong>contextEnd</strong>:塑造语句的终结索引默认<strong>text的长度</strong></p>
</li>
<li>
<p><strong>x</strong>:位置<strong>x轴坐标</strong></p>
</li>
<li>
<p><strong>y</strong>:位置<strong>y轴坐标</strong></p>
</li>
<li>
<p><strong>isRtl</strong>:运行是否为<strong>镜像</strong></p>
</li>
<li>
<p><strong>paint</strong>:画笔</p>
</li>
</ul>
</li>
</ul>
<h5 id="代码实例-16">代码实例</h5>
<pre><code class="language-java">private void drawTextRun(Canvas canvas)
{
    paint.setTextSize(100);
    CharSequence text="Hello word just do it";
    canvas.drawTextRun(text,0,text.length(),0,text.length(),100,100,true,paint);

    canvas.drawTextRun(text,0,text.length(),0,text.length(),100,600,false,paint);

}
</code></pre>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/816849/galleries/2378863/o_240724134549_265.png"></p>
</li>
</ul>
<h4 id="绘制多边形drawvertices">绘制多边形:drawVertices</h4>
<ul>
<li><strong><code>canvas.drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, float[] texs, int texOffset, @Nullable int[] colors, int colorOffset, short[] indices, int indexOffset, int indexCount, Paint paint)</code></strong>
<ul>
<li><strong>参数解析</strong>:
<ul>
<li><strong>mode</strong>:如何解释顶点数组</li>
<li><strong>vertexCount</strong>:<strong>顶点数组中的值数</strong>(<strong>如果非空,则为相应的texs和颜色数组</strong>)。每个逻辑顶点都是<strong>两个值(x,y)</strong>,<strong>vertexCount必须是2的倍数</strong></li>
<li><strong>verts</strong>:<strong>网格的顶点数组</strong></li>
<li><strong>vertOffset</strong>:<strong>绘制前要跳过的顶点中的值数</strong></li>
<li><strong>texs</strong>:可能为空。如果不为空,则指定要采样到当前着色器中的坐标(<strong>例如位图平铺或渐变</strong>)</li>
<li><strong>texOffset</strong>:绘制前要跳过的<strong>texs</strong>中的值数</li>
<li><strong>colors</strong>:可为空。如果不为空,则为每个顶点指定一种颜色,以便在三角形上进行插值。</li>
<li><strong>colorOffset</strong>:<strong>绘制前要跳过的颜色值的数目</strong></li>
<li><strong>indices</strong>:如果不为<strong>null</strong>,则引用到顶点<strong>(texs,colors)数组</strong>的索引数组</li>
<li><strong>indexCount</strong>:<strong>如果不为空,索引数组中的条目数</strong></li>
<li><strong>paint</strong>:画笔</li>
</ul>
</li>
<li><strong>由于资料很少,做一下简单的了解,在Android开发程序中应该是不常用的</strong></li>
</ul>
</li>
</ul><br><br>
来源:https://www.cnblogs.com/ajunjava/p/18324242
頁: [1]
查看完整版本: Android开发 - Canvas类与Paint画笔与Draw绘制方法详解与使用