博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
View详解(4)
阅读量:6248 次
发布时间:2019-06-22

本文共 5543 字,大约阅读时间需要 18 分钟。

在上文中我们简单介绍了Canvas#drawCircle()的使用方式,以及Paint#setStyle(),Paint#setStrokeWidth(),Paint#setColor()等相关函数,不知道小伙伴们了解了多少?那么是不是所有的图形都能通过圆来描述呢?当然不行,那么熟悉API套路的我们就应该知道,这时候应该去看Canvas源码中提供的公有方法是否能满足我们的需求,这样我们就会看到下表中的公有函数:

公有函数 函数说明
drawBitmap 绘制图片
drawArc 绘制圆弧
drawLine 绘制线条
drawOval 绘制椭圆
drawPoint 绘制点
drawRect 绘制矩形
drawRoundRect 绘制圆角矩形
drawText 绘制字符串

上表中大多数函数都不止一个实现,具体的参数含义也不同。激动的你们是不是已经搬好小板凳,等着我讲解这些函数的用法及参数了?不好意思,要让你们失望了,我一向秉承,授之以鱼,不如授之以渔,所以亲们自行尝试这些函数哦,绘制结果老规矩,后台等你们哦!

接下来敲黑板,开始画重点喽,仔细排查上表中函数,思考三角形,五角形,六角形,五角星等的绘制方法。肯定有小伙伴立刻补刀,傻不傻?画线啊,拼起来不就好?那么问题来了,让你画一个红色三角形怎么搞?三条线拼起来,Paint设置成Style.FILL能搞定?

机智的我立马去撸了一波代码

@Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    canvas.drawLine(10,10,200,200,mPaint);    canvas.drawLine(200,200,150,200,mPaint);    canvas.drawLine(150,200,10,10,mPaint);  }  private void init(){    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);    mPaint.setColor(Color.RED);    mPaint.setStyle(Style.FILL);  }复制代码

手抖一运行,秒打脸,结果是图-错误的三角

那到底要怎么整呢?Google爸爸设计API不可能没考虑到这些东东啊?不服气,接着搜源码,终于找到了一个看不懂的东东:
public void drawPath(@NonNull Path path, @NonNull Paint paint)复制代码

这个Path到底是个什么东东,下面我们一起来学习下。

Path

什么是Path

Path英翻汉的结果是路径,路途,也就是说Path代表着一段可用路径。使用Path可以构建一个路径对象,用于Canvas绘制,Path中的相关函数及说明我们用到一个讲解一个,有兴趣的小伙伴可以自行查阅尝试,资料很多。

绘制三角形

在使用Path定义路径时,我们首先应该为该路径指定起点,使用Path#moveTo()方法,随后使用其他函数绘制所需路径即可,以开篇三角形为例,构建Path的代码如下:

//Path对象初始化    mPath = new Path();    //移动路径起点到(10,10)    mPath.moveTo(10,10);    //从点(10,10)绘制直线到点(200,200)    mPath.lineTo(200,200);    //从点(200,200)绘制直线到点(150,200)    mPath.lineTo(150,200);    //闭合该路径,从当前点绘制直线到起点    mPath.close();复制代码

随后使用Canvas#drawPath绘制该路径,代码如下:

//第一个参数为路径对象,第二个参数为画笔canvas.drawPath(mPath,mPaint);复制代码

再次运行,我们可以看到界面上有一个实心红色三角形,如下图:

这里请大家自行绘制五边形,六边形。老规矩,截图甩后台。

前面小试牛刀,绘制了一个小小三角形,大家对Path应该还是一知半解,接下来我们进一步学习如何使用Path描述自定义View中的不规则路径。目标下面动图:

咋一看,是不是一个头两个大,不要方,都是纸老虎,我们来一点一点分析。

动画形成过程

仔细观察上面动图,我们不难发现整个图形由四部分组成,拿出其中一部分单独分析,我们不难得到下图:

左上角这四分之一是由两条直线加四分之一圆弧组成,其中动画是由点P的位置变化形成的,P点坐标范围起于图1止于图4.

Path组成及点坐标

还是以左上角四分之一做细致分析,讲解Path的形成过程及点坐标,详细的左上角坐标标记如下图:

描述左上角的Path路径对象伪代码如下:

移动起点到点B,绘制四分之一圆,绘制直线AP,然后闭合该路径即可复制代码

进一步细化上图中辅助点,计算我们所需要的三个关键点P,A,B的坐标,细化后的分析图如下:

如上图所示我们假设要绘制的圆半径为R,那么可以得到P点所能取得的最大坐标值为(O-B1,O-A1),其中O-B1=O-A1。

由于三角形OPA是等腰三角形,所以其高线P-A1=R/2,又B1-O = P-A1,所以O-B1 = R/2

进而我们可以得到P点的取值范围为(0,0)到(R/2,R/2).

生成Path

切换坐标系到我们的View坐标系内,假设P点坐标为(x,x),x取值范围为0到R/2,从而我们可以确认得到左上角路径上的P,A,B三点坐标,其中:

A(mWidth/2,mHeight/2 - R)

B(mWidth/2 - R,mHeight/2)
P(mWidth/2 - x,mHeight/2 - x)

获得ABP三点坐标后,接下来的重点就是怎么将四分之圆加入Path对象了,这里我们就需要用到Path#addArc()方法了,函数声明如下:

//第一个参数为圆弧所在矩形区域,第二个参数为截图的开始角度,第三个参数为截取的角度大小public void addArc(RectF oval, float startAngle, float sweepAngle)复制代码

画图说明如下:

一点要注意第三个参数是截取得角度大小,从水平方向开始,顺时针取正值,逆时针取负值

那么此时我们就可以确定左上角的Path对象了,代码如下:

//清空上一次Path中存放的所有路径    mPath3.reset();    //移动路径起点到B点    mPath3.moveTo(mWidth / 2 - mRadius, mHeight / 2);    //绘制四分之一圆弧BA    mPath3.addArc(new RectF(mWidth / 2 - mRadius, mHeight / 2 - mRadius, mWidth / 2 + mRadius,        mHeight / 2 + mRadius), 180, 90);    //绘制直线AP    mPath3.lineTo(mWidth / 2 - x, mHeight / 2 - x);    //闭合曲线,默认绘制直线PB    mPath3.close();复制代码

生成动画

public void startAnimation() {    //新建ValueAnimator对象    mValueAnimator = ValueAnimator.ofFloat(0f, mRadius / 2f);    //设置动画单次时长    mValueAnimator.setDuration(5000);    //设置动画重复模式,REVERSE--反转,RESTART--重新开始    mValueAnimator.setRepeatMode(ValueAnimator.REVERSE);    //设置动画重复次数,-1 --- INFINE    mValueAnimator.setRepeatCount(-1);    mValueAnimator.addUpdateListener(new AnimatorUpdateListener() {      @Override      public void onAnimationUpdate(ValueAnimator valueAnimator) {        //更新P点坐标        x = (float) valueAnimator.getAnimatedValue();        postInvalidate();      }    });    mValueAnimator.start();  }复制代码

运行后效果如下:

作业

上面已经详细解释了左上角的绘制过程,相信机智的你已经完全懂了,那么请自行完成剩余三部分的绘制,交流群里gif甩起来。

下期预告

提前透漏个动画给你们。还是在圆上搞事情,感觉和圆杠上了。

完整代码

public class ArcView extends View {  private Paint mPathPaint;  private Path mPath;  private int mWidth;  private int mHeight;  private int mRadius = 200;  private ValueAnimator mValueAnimator;  private float x = 0f;  public ArcView(Context context) {    super(context);    init();  }  public ArcView(Context context, @Nullable AttributeSet attrs) {    super(context, attrs);    init();  }  @Override  protected void onSizeChanged(int w, int h, int oldw, int oldh) {    super.onSizeChanged(w, h, oldw, oldh);    if (w > 0 && h > 0) {      mWidth = w;      mHeight = h;    }  }  @Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    initPaths();    mPathPaint.setColor(Color.parseColor("#FD9A59"));    canvas.drawPath(mPath, mPathPaint);  }  private void init() {    mPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);    mPathPaint.setStyle(Style.FILL);    mPath = new Path();  }  private void initPaths() {    mPath.reset();    mPath.moveTo(mWidth / 2 - mRadius, mHeight / 2);    mPath.addArc(new RectF(mWidth / 2 - mRadius, mHeight / 2 - mRadius, mWidth / 2 + mRadius,        mHeight / 2 + mRadius), 180, 90);    mPath.lineTo(mWidth / 2 - x, mHeight / 2 - x);    mPath.close();  }  public void startAnimation() {    mValueAnimator = ValueAnimator.ofFloat(0f, mRadius / 2f);    mValueAnimator.setDuration(5000);    mValueAnimator.setRepeatMode(ValueAnimator.REVERSE);    mValueAnimator.setRepeatCount(-1);    mValueAnimator.addUpdateListener(new AnimatorUpdateListener() {      @Override      public void onAnimationUpdate(ValueAnimator valueAnimator) {        x = (float) valueAnimator.getAnimatedValue();        postInvalidate();      }    });    mValueAnimator.start();  }}复制代码

觉得不错的亲们动动手指分享转发下哈。

转载于:https://juejin.im/post/5bc85103e51d450e925290d3

你可能感兴趣的文章
SQLIOSim 模拟SQLServer的行为来测试IO性能
查看>>
更改activity组件切换的动画
查看>>
周鸿祎在360新员工入职培训上的讲话
查看>>
网页基础编程第十章
查看>>
centos7 命令行版本 安装 teamviewer
查看>>
修复XP注册表文件system损坏故障
查看>>
每周一书
查看>>
Java代码规范那些事
查看>>
我的友情链接
查看>>
如何更好地对齐分区??
查看>>
使用Python从rds上下载mysql备份文件
查看>>
react native组件的创建
查看>>
批量删除文件
查看>>
Linux网络管理
查看>>
iOS JSPatch 热修复使用
查看>>
某二级行机房搬迁
查看>>
基于MVC+EasyUI的Web开发框架经验总结(4)--使用图表控件Highcharts
查看>>
vs2015 xamarin 添加智能感知
查看>>
call to member function bind_param() on boolean...........
查看>>
刘启成_补充知识:awk:报告生成器
查看>>