本文继续介绍自定义控件的相关内容,Path在一些高级特效中使用相当广泛,如一些加载特效、刮刮卡和前段时间的比较火的撕衣应用。

Path一般结合xfermode或者贝塞尔曲线做一些很炫的交互效果,有关贝塞尔曲线的内容这里暂不涉及,本文主要介绍Path的一些简单基础用法,相关的类还包括PathMeasure,需要掌握PathMeasure的两个方法:getLength()、getSegment。

Path封装了由直线和曲线(二阶,三阶贝塞尔曲线)构成的几何路径。你能用Canvas中的drawPath来把这条路径画出来(同样支持Paint的不同绘制模式),也可以用于剪裁画布和根据路径绘制文字。我们有时会用Path来描述一个图像的轮廓,所以也会称为轮廓线(轮廓线仅是Path的一种使用方法,两者并不等价)。

PathMeasure

PathMeasure是用来测量Path路径长度的类,可以通过getLength()获取Path的长度,但是该值的大小与forceClosed强相关,forceClosed可以通过如下方法传入:

public PathMeasure(Path path, boolean forceClosed)

public void setPath(Path path, boolean forceClosed)

forceClosed就是Path最终是否需要闭合,如果为true的话,则不管关联的Path是否是闭合的,都会被闭合,forceClosed对绑定的Path不会产生任何影响。

可以通过如下一个简单的代码测试一下影响:

path.moveTo(100,100);

path.lineTo(100,300);

path.lineTo(300,300);

path.lineTo(300,100);

pathMeasure=new PathMeasure(path,true);

float length=pathMeasure.getLength();

Log.d(TAG, "MyPathView: length="+length);

上述代码Path路径就是绘制一个不闭合的正方形,如果将PathMeasure的第二个参数forceClosed传入true,这是length为800,如果forceClosed为false,那么这时length为600。

一定要注意这里PathMeasure的forceClosed参数与Path类的close()方法的差异,PathMeasure的forceClosed参数并不会影响视觉上的绘制,就是说如果绘制Path不是闭合图像,这时候视觉上仍然是不闭合的。

但是Path的close()方法会影响图像,close()方法的意思是将当前点与初始点连接在一起,如果当前点与初始点不在一个点,这时候会将两个点连接在一起,而且在视觉上可以看到效果。如果连接了最后一个点和初始点仍然无法形成封闭图形,则close()方法什么也不做。

Direction

在使用Path绘制图形时有一个Direction类型的参数,该参数有两个值CW和CCW,其中CW是顺时针的绘制,CCW是逆时针绘制。

public void addCircle(float x, float y, float radius, Direction dir)

public void addOval(RectF oval, Direction dir)

public void addRect(RectF rect, Direction dir)

public void addRoundRect(RectF rect, float rx, float ry, Direction dir)

Direction在绘制时一般没有太大的差异,但是如果涉及到某些特效时,需要特别注意。

下面通过示例代码运行截图对比一下:

// 顺时针

path.addCircle(500, 400, 300, Path.Direction.CW);

canvas.drawPath(path, paint);

canvas.drawTextOnPath(str, path, 0, 0, paint);

path.reset();

// 逆时针

path.addCircle(500, 1100, 300, Path.Direction.CCW);

canvas.drawPath(path, paint);

canvas.drawTextOnPath(str, path, 0, 0, paint);

PathMeasure的getSegment方法

public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)

该方法是一个boolean类型的方法,主要用于截取指定Path的片段到dst中,通过参数startD和stopD来控制截取的长度,最后一个参数startWithMoveTo表示起始点是否使用moveTo方法,通常为True,保证每次截取的Path片段都是正常的、完整的。

如果startWithMoveTo设置为false,通常是和dst一起使用,因为dst中保存的Path是被不断添加的,而不是每次被覆盖,设置为false,则新增的片段会从上一次Path终点开始计算,这样可以保存截取的Path片段数组连续起来。

在Android kitkat版本及之前的版本,该方法所获取到的path可能由于硬件加速问题导致无法被绘制显示出来的。要解决该问题的简单方法就是在所要获取的path上执行lineTo(0, 0) 或执行rLineTo(0, 0)。

public MyPathView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

paint = new Paint();

paint.setAntiAlias(true);

paint.setColor(Color.RED);

paint.setStyle(Paint.Style.STROKE);

paint.setStrokeWidth(10);

dstPath = new Path();

path = new Path();

path.addCircle(500, 500, 200, Path.Direction.CW);

pathMeasure = new PathMeasure(path, false);

length = pathMeasure.getLength();

final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator valueAnimator) {

animatorValue = (float) valueAnimator.getAnimatedValue();

invalidate();

}

});

valueAnimator.setDuration(1300);

valueAnimator.setRepeatCount(ValueAnimator.INFINITE);

valueAnimator.start();

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

dstPath.reset();

dstPath.lineTo(0, 0);

float stop = length * animatorValue;

float start = (float) (stop - ((0.5 - Math.abs(animatorValue - 0.5)) * length));

pathMeasure.getSegment(start, stop, dstPath, true);

canvas.drawPath(dstPath, paint);

}

Path与xfermode示例

Path也经常与xfermode组合使用,如下是一个简单刮刮卡示例,如果有兴趣可以参看Bitmap学习笔记。

public MyPathView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

paint = new Paint();

paint.setAntiAlias(true);

paint.setStyle(Paint.Style.STROKE);

paint.setStrokeCap(Paint.Cap.ROUND);

paint.setStrokeJoin(Paint.Join.ROUND);

paint.setStrokeWidth(30);

//paint.setAlpha(0);

//paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));

path = new Path();

bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);

//双缓冲机制创建前景灰色图层

foreground = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);

myCanvas = new Canvas(foreground);

myCanvas.drawColor(Color.GRAY);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawBitmap(bitmap, 0, 0, null);

canvas.drawBitmap(foreground, 0, 0, null);

myCanvas.drawPath(path, paint);

}

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

startX = (int) event.getX();

startY = (int) event.getY();

path.moveTo(startX, startY);

break;

case MotionEvent.ACTION_MOVE:

int stopX = (int) event.getX();

int stopY = (int) event.getY();

path.lineTo(stopX, stopY);

startX = stopX;

startY = stopY;

break;

}

invalidate();

return true;

}

小结

本文介绍的内容不多,都是一些Path的简单基础的用法,包括如何获取绘制Path的长度,如何截取绘制Path的部分片段,通过Path和xfermode实现一个刮刮卡效果。将Path简单的用法使用熟练后,然后再结合其它相关类就可以实现一些很炫很酷的交互效果。

下一篇文章中会介绍贝塞尔曲线相关的内容,贝塞尔曲线实现的交互确实要比正余弦函数实现的交互要平滑许多,比如加入购物车或者加载的波纹效果都会使用贝塞尔曲线。

android drawpath大小,Android Path和PathMeasure相关推荐

  1. android ripple 大小,Android L限制Ripple水波纹范围大小

    Android L限制Ripple水波纹范围大小 Ripple 简介 Android 5.0 之后 google 推出了 Material Design,Botton 默认的触摸反馈会有水波纹涟漪效果 ...

  2. android ratingbar 大小,Android 调整Ratingbar中的小星星大小

    做新空间项目的时候,写到评价模块,就需要用到Ratingbar这个控件,问题是这个控件中的星星大小实在无法满足需求,只有三种样式,不可以直接设置大小 一:首先是属性值的定义: android:id=& ...

  3. android window 大小,android popupWindow 中宽度莫名很大,求帮助?

    这个是popupwindow的内容xml(就是放了个ListView): android:layout_width="wrap_content" android:layout_he ...

  4. android drawpath填充,Android如何用图片来填充Path封闭路径

    刚刚接触安卓,最近在做一个小项目,用path根据四个点坐标绘制了一个矩形,需要用图片来填充矩形.因为根据路径绘制的矩形是倾斜的,所以填充图片不太容易,经过查资料,通过试验得到了一种方法,分享一下: / ...

  5. android ripple 大小,Android Ripple 旋钮水波纹效果(一)

    看到android 5.0有一个按钮点击效果非常棒,先来看效果图: 但是这种效果只能在5.0的系统上有效果,如何在低版本上实现呢? 这种效果网上也有人实现了, blog 地址http://blog.c ...

  6. android 组件大小,Android编程获取组件尺寸大小的方法

    本文实例讲述了Android编程获取组件尺寸大小的方法.分享给大家供大家参考,具体如下: 在oncreate()中利用view.getWidth()或是view.getHeiht()来获取view的宽 ...

  7. android shape大小,Android shape属性详解

    一.概述 最近太忙了,几乎每天都在做项目.同时写两个项目的感觉真爽. 在我们开发中,会经常遇到shape这种属性,这种属性可以在没有美工的情况照样可以实现我们想要的效果.自动动手,丰衣足食. 二.效果 ...

  8. android thumb大小,Android 设置thumb图片大小

    xml: android:thumb="@drawable/seekbar_thumb" seekbar_thumb.xml: 修改为: private int seekWidth ...

  9. android surfaceview 大小,Android设置SurfaceView任意大小、任意位置、保持预览宽高比与屏...

    Android设置SurfaceView任意大小.任意位置.保持预览宽高比与屏 Android设置SurfaceView任意大小.任意位置.保持预览宽高比与屏显一致 一.任意大小.任意位置 1) 代码 ...

最新文章

  1. docker 容器访问宿主机的解决方式
  2. matlab的讲稿ppt,Matlab初步(讲稿200508)之四
  3. 当计算机从硬盘读取数据后 将数据,当计算机从硬盘读取数据后,将数据暂时储存在于()...
  4. 在使用apt-get update 时更行列表,显示[Connecting to archive.ubuntu.com (2001:67c:1360:8001::21)]超时
  5. Arraylist理解(3)删除元素
  6. 小程序直播 OBS 画质_微信小程序怎么直播卖货?
  7. caffe-gpu ubuntu 安装_ubuntu16.04 cuda10.0 配置caffe gpu环境
  8. Android开发笔记(一百四十五)仿应用宝的垃圾清理动画
  9. JavaScript实现中国地图圆点标注(二十四)
  10. 求一个截取字符的正则表达式
  11. Java7/8集合框架——基本知识点
  12. 中国物联网行业发展现状及竞争前景分析报告2022-2028年
  13. ssm——整合,前端页面设计,分页
  14. 什么浏览器最好用,五款浏览器对比那个最好?
  15. requestSubscribeMessage:fail can only be invoked by user TAP gesture 微信小程序调起订阅消息失败
  16. 小猪佩奇与Tom猫的一场内网友谊赛
  17. Win10环境下caffe安装与编译
  18. KVM虚拟化技术的-NUMA技术和应用
  19. 【python自动化】基于Splinter的自动化回归/测试脚本
  20. 第十四次CCF CSP认证心得

热门文章

  1. 【控制】《多智能体系统一致性协同演化控制理论与技术》纪良浩老师-第10章-二阶离散时间时延多智能体系统加权一致性
  2. STM32 电机教程 29 - 无刷无感入门1
  3. FPGA_进阶篇开篇
  4. LTE 有关HARQ
  5. 【arduino】最近在搞的项目,ESP32常用模块连接原理图连线图。TTGO-T8-ESP32arduino开发注意事项...
  6. 雷达篇(六)电磁波的大气衰减
  7. GPS系统跟踪捕获算法的Verilog实现
  8. 初探 Vue 生命周期和钩子函数
  9. canvas使用技巧大全
  10. 对Struts2的认识(-)