Android鬼点子-不用百行代码,让文字闪闪发光
想做一个让文字有类似金属光泽效果的动画。效果如下:
分享一下实现思路,使用kotlin实现。需求是需要有很好的移植性,可以修改设置光泽颜色,光泽宽度,光泽速度,光泽角度。
最后的结果是只要一行代码即可调用:
start_bt.setOnClickListener { mTextView.setBling() } stop_bt.setOnClickListener { mTextView.setBling(isStop = true) }
当然,也可以通过一些参数来设置一些效果mTextView.setBling(blingWidth = 80f,angle = 20f,speed = 6f)
这里的mTextView就是一个普通的TextView。我使用的是kotlin的扩展方法,对TextView进行了拓展,方便调用。
想要实现这种效果,我的思路是给paint设置LinearGradient。然后移动LinearGradient的位置就可以了。
第一步就是拿到TextView的paint,在TextView中找到private final TextPaint mTextPaint;
这个mTextPaint就是用来绘制文字的。
但是mTextPaint是一个私有变量,不能访问到,于是我想通过反射拿到mTextPaint。代码如下:
val class1 = Class.forName("android.widget.TextView") val field = class1.getDeclaredField("mTextPaint") field.isAccessible = true var paint = field.get(this) as TextPaint
然后给mTextPaint设置LinearGradient:
this.context.runOnUiThread { paint.shader = lg [email protected]() }
这里的lg,就是一个LinearGradient对象,设置完LinearGradient之后,呼叫重绘。
我用到LinearGradient是这样的:LinearGradient(0f + position, 0f, blingWidth + position, angle, textColor, blingColor, Shader.TileMode.MIRROR)
光泽的位置变化是通过position变量实现的,我用到了一个线程,并且把这个线程保存到tag里面。
完整代码如下,可以放置到项目中任意位置:
package top.greendami.blingview import android.graphics.Color import android.graphics.LinearGradient import android.graphics.Shader import android.text.TextPaint import android.widget.TextView import org.jetbrains.anko.runOnUiThread /** * Created by GreendaMi on 2018/1/16. */ //是否有动画 fun TextView.isBling(): Boolean { if (this.tag != null) { var mT = this.tag as Thread return mT.isAlive } return false } fun TextView.setBling(textColor: Int = Color.BLACK, blingColor: Int = Color.WHITE, blingWidth: Float = this.textSize, isStop: Boolean = false, speed: Float = 4f,angle :Float = 0f) { var position = 0f //如果已经有发光效果 if (this.tag != null) { var mT = this.tag as Thread mT.interrupt() this.tag = null blingText(null) } if (isStop) { return } var mThread = Thread(Runnable { while (!Thread.currentThread().isInterrupted) { //下一帧 position += speed blingText(LinearGradient(0f + position, 0f, blingWidth + position, angle, textColor, blingColor, Shader.TileMode.MIRROR)) try { //延迟 Thread.sleep(100) } catch (ex: InterruptedException) { Thread.currentThread().interrupt() } } }) this.tag = mThread mThread.start() } private fun TextView.blingText( lg: LinearGradient?) { try { val class1 = Class.forName("android.widget.TextView") val field = class1.getDeclaredField("mTextPaint") field.isAccessible = true //拿到画笔对象 var paint = field.get(this) as TextPaint this.context.runOnUiThread { //设置LinearGradient paint.shader = lg //呼叫重绘 [email protected]() } } catch (e: Exception) { e.printStackTrace() } }
为了方便我用了anko,implementation "org.jetbrains.anko:anko-commons:0.10.4"
代码github