本文正在参与「金石方案」
工作是这样的,我无聊刷到一个B站视频【歪门邪道PPT】我发现了大厂发布会中,少文字PPT还贼高级的隐秘!。看到视频中这个特殊的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】我发现了大厂发布会中,少文字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
}
}
作用如下:
添加一个波涛动画
咱们也能够给咱们的图片填充添加一个动画,其间最常见的便是波涛动画了。作用完成很简单:
第一步:在波涛作用网站上下载一张自己想要的波涛图片
第二步:创建自定义的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()
作用如下:
参阅
- What is the difference between Paint and TextPaint in Android?
- Android绘图之Shader
- 消除布景
- 波涛作用网站
- 书法字体下载网站