本文正在参与「金石方案」

工作是这样的,我无聊刷到一个B站视频【歪门邪道PPT】我发现了大厂发布会中,少文字PPT还贼高级的隐秘!。看到视频中这个特殊的PPT文字作用,个人感觉十分高端。我就想,能不能用TextView来完成。所以就有了这篇文章,作用如下图:

简单填充 参加文字排版 参加动画
高仿PPT特殊文字效果,TextView实现
高仿PPT特殊文字效果,TextView实现
高仿PPT特殊文字效果,TextView实现

图片填充

Android中,google供给了 BitmapShader 来完成图片填充的功用。代码如下

public BitmapShader(@NonNull Bitmap bitmap,
                        @NonNull TileMode tileX, 
                        @NonNull TileMode tileY)

参数介绍:

●bitmap:用来做填充的 Bitmap 对象

●tileX:横向的 TileMode(平铺形式)

●tileY:纵向的 TileMode

TileMode有三种:分别是 Shader.TileMode.CLAMP、Shader.TileMode.MIRROR、Shader.TileMode.REPEAT

●Shader.TileMode.CLAMP:假如着色器超出原始边界规模,会复制边际色彩。

●Shader.TileMode.MIRROR:横向和纵向的重复着色器的图画,交替镜像图画是相邻的图画总是接合。

●Shader.TileMode.REPEAT: 横向和纵向的重复着色器的图画。

接下来,咱们自定义 TextView,让它运用咱们定义的Shader,代码如下:

class MaskTextView: androidx.appcompat.widget.AppCompatTextView {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )
    private var shader: BitmapShader? = null
    fun setMaskDrawable(source: Drawable): Unit {
        val maskW: Int = source.getIntrinsicWidth()
        val maskH: Int = source.getIntrinsicHeight()
        val b = Bitmap.createBitmap(maskW, maskH, Bitmap.Config.ARGB_8888)
        val c = Canvas(b)
        c.drawColor(currentTextColor)
        source.setBounds(0, 0, maskW, maskH)
        source.draw(c)
        shader = BitmapShader(b, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP)
        paint.shader = shader
    }
}

在免费壁纸网站中找到一个你喜爱的图片,调用 setMaskDrawable 方法时,咱们就能够看到填充后的作用了。作用如下:

高仿PPT特殊文字效果,TextView实现

但是光这个作用还不行,还需要设置文字排版。看【歪门邪道PPT】我发现了大厂发布会中,少文字PPT还贼高级的隐秘!咱们知道,有三种文字排版,分别是 高低低高、高低高低、低高低高,它们都需要修正文字的 baseline 来完成。

怎么修正单个字符的 baseline 呢?很简单,不需要重写 onDraw 方法。咱们能够自定义 Span,然后通过 TextPaint 来完成。在上代码前,先介绍一下 TextPaint,TextPaint 承继 Paint,在绘制和丈量文本时给Android一些额定的数据。它的特点介绍如下:

●baselineShift – 基线是文本底部的线。改动baselineShift会使基线向上或向下移动,所以它影响到文本在一条线上的绘制高度。

●bgColor – 这是文本后面的布景色彩。

●density – 暂不清楚它的作用

●drawableState – 暂不清楚它的作用

●linkColor – 一个链接的文本色彩。

能够看到咱们只需要修正 baselineShift 就能够改动单个文字的 baseline 了,自定义的Span的代码如下:

class TextUpOrDownSpan(private val isUp:Boolean, private val offset: Int): CharacterStyle() {
    override fun updateDrawState(tp: TextPaint?) {
        tp?.baselineShift = if(isUp) - offset else offset
    }
}

作用如下:

高仿PPT特殊文字效果,TextView实现

添加一个波涛动画

咱们也能够给咱们的图片填充添加一个动画,其间最常见的便是波涛动画了。作用完成很简单:

第一步:在波涛作用网站上下载一张自己想要的波涛图片

高仿PPT特殊文字效果,TextView实现

第二步:创建自定义的TextView,加上对应的参数,方便做动画。代码如下:

class AnimatorMaskTextView: androidx.appcompat.widget.AppCompatTextView {
    private var shader: BitmapShader? = null
    private var shaderMatrix: Matrix = Matrix()
    private var offsetY = 0f
    var maskX = 0f
        set(value) {
            field = value
            invalidate()
        }
    var maskY = 0f
        set(value) {
            field = value
            invalidate()
        }
    fun setMaskDrawable(source: Drawable): Unit {
        val maskW: Int = source.getIntrinsicWidth()
        val maskH: Int = source.getIntrinsicHeight()
        val b = Bitmap.createBitmap(maskW, maskH, Bitmap.Config.ARGB_8888)
        val c = Canvas(b)
        c.drawColor(currentTextColor)
        source.setBounds(0, 0, maskW, maskH)
        source.draw(c)
        shader = BitmapShader(b, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP)
        paint.shader = shader
        offsetY = ((height - maskH) / 2).toFloat()
    }
    override fun onDraw(canvas: Canvas?) {
        shaderMatrix.setTranslate(maskX, offsetY + maskY)
        shader?.setLocalMatrix(shaderMatrix)
        paint.shader = shader
        super.onDraw(canvas)
    }
}

第三步:运用Android的动画api,控制图片的位置。代码如下:

val maskXAnimator: ObjectAnimator =
    ObjectAnimator.ofFloat(textView, "maskX", 0f, textView.width.toFloat())
val maskYAnimator: ObjectAnimator =
    ObjectAnimator.ofFloat(textView, "maskY", 0f, (-textView.getHeight()).toFloat())
val animatorSet = AnimatorSet()
animatorSet.playTogether(maskXAnimator, maskYAnimator)
animatorSet.start()

作用如下:

高仿PPT特殊文字效果,TextView实现

参阅

  • What is the difference between Paint and TextPaint in Android?
  • Android绘图之Shader
  • 消除布景
  • 波涛作用网站
  • 书法字体下载网站