ShimmerTextView
Posted freeCodeSunny
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ShimmerTextView相关的知识,希望对你有一定的参考价值。
产品中有一个需求,要求TextView的文字有一个高亮的效果,高亮的同时有跑马灯效果!
本来想在网上找一个现成的用用,比如Facebook出的Shimmer,还有很多,但是都感觉代码太多,因此撸了一个简单版的,talk is cheap,show me you code。
实现
我们知道TextView的文字的颜色是由Paint根据Color控制的,我们可以设置Paint的Shader来实现该效果,这样在TextView绘制的时候Paint会从对应的Shader获取color来实现绘制。既然TextView要高亮,说明文字颜色不一致,这里我们可以设置一线性渐变shader,这样就可以设置不同部分的文字不同颜色。至于跑马灯那就一直水平改变Shader就可以实现。
属性定义
虽然是简单的,还是要通用,比如颜色可以自定义,方向可以设置,是否自动开始,这里我们先定义几个属性:
<declare-styleable name="ShimmerTextView">
<attr name="auto_start" format="boolean"></attr>
<attr name="start_color" format="reference|color"></attr>
<attr name="end_color" format="reference|color"></attr>
<attr name="direction" format="boolean"></attr>
</declare-styleable>
这里我们分别控制了是否自动开始,开始颜色,结束颜色,方向
代码实现
这里我们实现一个继承自AppCompatTextView的自定义TextView。
public class ShimmerTextView extends android.support.v7.widget.AppCompatTextView
public static final int OFFSET_ONE_TIME = 15;
private Paint paint;
private LinearGradient gradient;
private Matrix matrix;
private int w, h;
private boolean horizontal;
private boolean autoStart;
private int startColor;
private int endColor;
private static final int DEFAULT_START_COLOR = 0xFFFF50ED;
private static final int DEFAULT_END_COLOR = 0xFF3455FF;
private float offset = 0;
private ValueAnimator animator;
public ShimmerTextView(Context context)
super(context);
init(context, null);
public ShimmerTextView(Context context, @Nullable AttributeSet attrs)
super(context, attrs);
init(context, attrs);
public ShimmerTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
init(context, attrs);
private void init(Context context, AttributeSet attrs)
paint = getPaint();
matrix = new Matrix();
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ShimmerTextView);
autoStart = array.getBoolean(R.styleable.ShimmerTextView_auto_start, false);
startColor = array.getColor(R.styleable.ShimmerTextView_start_color, DEFAULT_START_COLOR);
endColor = array.getColor(R.styleable.ShimmerTextView_end_color, DEFAULT_END_COLOR);
horizontal = array.getBoolean(R.styleable.ShimmerTextView_direction, true);
array.recycle();
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
super.onSizeChanged(w, h, oldw, oldh);
this.w = w;
this.h = h;
setGradient();
private void setGradient()
if (horizontal)
gradient = new LinearGradient(0, 0, w, 0, new int[]startColor, endColor, startColor, new float[]0,
0.5f, 1.0f, Shader.TileMode.CLAMP);
else
gradient = new LinearGradient(0, 0, 0, h, new int[]startColor, endColor, startColor, new float[]0,
0.5f, 1.0f, Shader.TileMode.CLAMP);
paint.setShader(gradient);
invalidate();
if (autoStart)
play();
public void play()
ValueAnimator animator = getAnimator();
if (animator.isRunning())
return;
animator.start();
@NonNull
private ValueAnimator getAnimator()
if (animator == null)
animator = ValueAnimator.ofFloat(0.0f, 1.0f);
animator.setDuration(500);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
@Override
public void onAnimationUpdate(ValueAnimator animation)
offset += OFFSET_ONE_TIME;
if (horizontal)
if (offset > w)
offset = -w;
else
if (offset > h)
offset -= h;
invalidate();
);
return animator;
public void stop()
if (animator != null)
animator.cancel();
public void reset()
if (animator != null)
animator.cancel();
animator = null;
@Override
protected void onDetachedFromWindow()
super.onDetachedFromWindow();
reset();
@Override
protected void onDraw(Canvas canvas)
matrix.setTranslate(offset, 0);
gradient.setLocalMatrix(matrix);
super.onDraw(canvas);
上面的代码主要先解析了自定义属性,之后设置了一个线性渐变来改变文字的颜色,之后采用了ValueAnimator来水平移动线性渐变,同时重新绘制内容。
ValueAnimator 我们设置了一直重复动画,ValueAnimator就是一个数值发生器,其实可以用Handler与post来实现相同的效果。只要按一定速率改变线性渐变就可以
- 需要注意的是当距离大于整个View的宽度或者高度时,需要重新开始
效果
最后我们在界面中使用该控件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.demo.example.activity.ShimmerViewActivity">
<com.demo.example.widget.ShimmerTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="我爱北京天安门"
android:textSize="25sp"
app:auto_start="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.148"/>
</android.support.constraint.ConstraintLayout>
在Activity中设置该控件,运行效果。
截图效果有点糊
代码
最后附上代码地址Code
以上是关于ShimmerTextView的主要内容,如果未能解决你的问题,请参考以下文章