Canvas中的书法家讲解与实战——Android高级UI

目录java

1、前言git

2、Canvas中的书法家APIgithub

3、实战canvas

4、写在最后微信

1、前言

canvas 的 API 方法至关之多,小盆友本篇文章以前已经分享了 “Canvas中的裁剪师”“Canvas中的绘图师”,今天分享的是文字方面的API。ide

在分享前,小盆友啰嗦两句,有些童鞋说 canvas 的这几篇文章是初级文章和 “Android高级UI” 这几个字显得有些格格不入。小盆友借此解释下,canvas 的这几篇文章是做为 高级UI 文章的补充,是这系列文章中的 垫脚石,并不是想作 “标题党” 来吸引流量(貌似一直也没什么流量😂)。函数

啰嗦了这么多,来看看今天的实战效果图post

抖动的字符 动画

2、Canvas中的书法家API

一、drawText(四个重载方法)

(1)第一个 drawText 函数编码

public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) 复制代码

描述: 在坐标为 (x,y) 处绘制 text 字符串。

举个例子:

private static final String CONTENT = "zinc 猛猛的小盆友";

canvas.drawText(CONTENT, -300, -500, mPaint);
复制代码

效果图

(2)第二个 drawText 函数

public void drawText(@NonNull String text, int start, int end, float x, float y, @NonNull Paint paint) 复制代码

描述: 在坐标为 (x,y) 处绘制字符串text,从下标为start的字符开始,到下标为 (end-1) 的字符终止。

举个例子:

private static final String CONTENT = "zinc 猛猛的小盆友";

// 绘制内容为从CONTENT的第四个字符开始,到CONTENT最后一个字符
canvas.drawText(CONTENT, 3, CONTENT.length(), -300, -400, mPaint);
复制代码

效果图

(3)第三个 drawText 函数

public void drawText(@NonNull char[] text, int index, int count, float x, float y, @NonNull Paint paint) 复制代码

描述: 在坐标为 (x,y) 处绘制 text,从下标为start开始,绘制count个字符。

举个例子

private static final char[] C = "https://github.com/zincPower/UI2018".toCharArray();

canvas.drawText(C, 0, C.length, -300, -100, mPaint);
canvas.drawText(C, 5, 10, -300, 0, mPaint);
复制代码

效果图

(4)第四个 drawText 函数

public void drawText(@NonNull CharSequence text, int start, int end, float x, float y, @NonNull Paint paint) 复制代码

描述: 在坐标为 (x,y) 处绘制 text,从下标为start的字符开始,到下标为 (end-1) 的字符终止。

举个例子

private static final CharSequence SEQ = "https://blog.csdn.net/weixin_37625173";

canvas.drawText(SEQ, 0, SEQ.length(), -300, 300, mPaint);
canvas.drawText(SEQ, 6, 20, -300, 400, mPaint);
复制代码

效果图

二、drawTextOnPath (两个重载方法)

(1)第一个 drawTextOnPath 函数

public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) 复制代码

描述:路径path 上绘制 text。

特殊参数说明: 1)hOffset:水平偏移量 2)vOffset:垂直偏移量

举个例子

private static final String CONTENT = "zinc 猛猛的小盆友";

// mPath 是一个贝塞尔曲线绘制的路径
canvas.drawTextOnPath(CONTENT, mPath, 0, 0, mPaint);
复制代码

效果图

(2)第二个 drawTextOnPath 函数

public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) 复制代码

描述:路径path 上绘制 text。

特殊参数说明: 1)index:从下标为index的字符开始绘制 2)count:绘制字符的个数 3)hOffset:水平偏移量 4)vOffset:垂直偏移量

例子

private static final char[] C = "https://blog.csdn.net/weixin_37625173".toCharArray();

// 从下标为2的字符(即第三个字符)开始,绘制20个字符
canvas.drawTextOnPath(C, 2, 20, mPath, 0, 0, mPaint);
复制代码

效果图

三、drawTextRun

这个方法不作过多的解释,由于在实际开发中使用能够说较少。简单归纳这个方法的做用,他是为了处理一些语言文字(例如:阿拉伯语),当一个字在一个词语中,会受左右的字影响而进行变形的状况。

这方面的语言小盆友不懂,因此无法举出严谨的例子,请有须要的童鞋移步Demo中自行体会。

public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex, int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) 复制代码

四、drawPosText(两个重载方法)

(1)第一个 drawPosText 函数

public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos, @NonNull Paint paint) 复制代码

描述: 在pos对应的坐标上绘制text。

举个例子

private static final String CONTENT = "猛猛的小盆友";
private static final float[] pos1 = new float[]{
        -300, -600,
        -250, -500,
        -200, -400,
        -150, -300,
        -100, -200,
        -50, -100,
};

// 每一个字符 和 pos的坐标要一一对应的上,不然crash
canvas.drawPosText(CONTENT, pos1, mPaint);
复制代码

效果图

(2)第二个 drawPosText 函数

public void drawPosText(@NonNull char[] text, int index, int count, @NonNull @Size(multiple = 2) float[] pos, @NonNull Paint paint) 复制代码

描述: 在pos对应的坐标上绘制text,从下标为index的字符开始,绘制count个。

举个例子

private static final String CONTENT = "猛猛的小盆友";
private static final float[] pos2 = new float[]{
        -300, 100,
        -250, 200,
        -200, 300,
        -150, 400,
        -100, 500,
};

canvas.drawPosText(CONTENT.toCharArray(), 1, 4, pos2, mPaint);
复制代码

效果图

3、实战

抖动的字符

Github入口:传送门

编码思路 在这一实战中,其实 drawTextOnPath 反倒不是主角,他只是负责在咱们的 path 上将文字绘出便可,因此童鞋们知道了最主要的是 path 的肯定。

获取 path 上的点,是经过以下的函数获取

private float calculateY(float x) {
    double a = Math.pow(4 / (4 + Math.pow(4 * x / mLength, 4)), 2.5f) * mA;
    return (float) (a * Math.sin(Math.PI * x / 200 - m));
}
复制代码

具体的函数图形以下

公式的最初原型来源于此博客,在此谢谢博主。

看完这函数,可能有些童鞋比较懵逼,小盆友稍微给一些简单解释(毕竟难的我也说不清😂),咱们将此公式抽象一下,即是以下形状:

A*sin(w*x+m)+k
复制代码

这就是咱们在初中学的三角函数:正弦函数sin。咱们罗列下几个参数的做用:

  • A:管理 正弦函数 的振幅,即上下摆动的幅度;
  • w:管理 正弦函数 的水平收缩幅度
  • m:管理 正弦函数 的水平偏移量
  • k:管理 正弦函数 的垂直偏移量

在咱们这里的场景中,主要控制两个参数:

  1. A 的振幅变更,上面函数图中在靠近 x=0 的地方函数的震动幅度变大,因此咱们将 x的值 考虑进 A的计算中,而且以分母的形式(分母越大,数值越小;分母越小,数值越大)
  2. m 的水平偏移,正弦的一个周期是 2π,因此咱们这里的曲直只须要从 [0-2π] 的一个范围便可。

让字符串摇摆起来 通过上面的简单分析,咱们须要的各类零件也都准备好了,最后加入咱们再熟悉不过的 属性动画,就可让这条 路径path 动起来。路径path 动起来,会致使绘制在上面文字也动起来。

mAnimator = ValueAnimator.ofFloat(0, (float) (2 * Math.PI));
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float progress = (float) animation.getAnimatedValue();
        m = progress;
        mA = (float) (1 - progress / (2 * Math.PI)) * A;
        invalidate();
    }
});
mAnimator.setDuration(1000);
复制代码

4、写在最后

此次的文章较为简单和基础,只是小盆友有点强迫症,必需要把 canvas 的每一个API都过一遍和记录一下。

若是以为文章对你有所启发,请给我个赞吧,若是发现有那些欠妥的地方,请留言区与我讨论,咱们共同进步。

高级UI系列的Github地址:请进入传送门,若是喜欢的话给我一个star吧😄

欢迎加我微信,咱们能够进行更多更有趣的交流

相关文章
相关标签/搜索