效果:
效果就是这样(他会不断跑来跑起的 -_- ),这里会用到 Android 中 Sharder 子类 LinearGradient 线性渐变和自定义view onDraw()、onSizeChanged()方法;
一、Android 提供的 Shader 类主要是渲染图像以及一些几何图形:
1.BitmapShader : 主要用来渲染图像
2.LinearGradient :用来进行线性渲染
3.RadialGradient : 用来进行环形渲染
4.SweepGradient : 扫描渐变—围绕一个中心点扫描渐变就像电影里那种雷达扫描,用来梯度渲染。
5.ComposeShader : 组合渲染,可以和其他几个子类组合起来使用。
2.LinearGradient :用来进行线性渲染
3.RadialGradient : 用来进行环形渲染
4.SweepGradient : 扫描渐变—围绕一个中心点扫描渐变就像电影里那种雷达扫描,用来梯度渲染。
5.ComposeShader : 组合渲染,可以和其他几个子类组合起来使用。
LinearGradient 有两个构造方法分别如下:
1、LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[], TileMode tile)
注:Android中计算x,y坐标都是以屏幕左上角为原点,向右为x+,向下为y+
第一个参数为线性起点的x坐标
第二个参数为线性起点的y坐标
第三个参数为线性终点的x坐标
第四个参数为线性终点的y坐标
第五个参数为实现渐变效果的颜色的组合
第六个参数为前面的颜色组合中的各颜色在渐变中占据的位置(比重),如果为空,则表示上述颜色的集合在渐变中均匀出现
第七个参数为渲染器平铺的模式,一共有三种
-CLAMP
边缘拉伸
-REPEAT
在水平和垂直两个方向上重复,相邻图像没有间隙
-MIRROR
以镜像的方式在水平和垂直两个方向上重复,相邻图像有间隙
2、public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, TileMode tile)
其他参数同上
int color0表示渐变起始颜色
int color1表示渐变终止颜色
onSizeChanged() 在控件大小发生改变时调用。所以这里初始化会被调用一次(获取控件的宽和高度)
使用 getPaint() 方法获取当前绘制的 TextVIew 的 Paint 对象,给这个Paint 对象设置 LinearGradient 属性, paint.setShader(linearGradient);接着重写 onDraw()绘制需要的图形。
直接上代码(注释很清楚):
第一个参数为线性起点的x坐标
第二个参数为线性起点的y坐标
第三个参数为线性终点的x坐标
第四个参数为线性终点的y坐标
第五个参数为实现渐变效果的颜色的组合
第六个参数为前面的颜色组合中的各颜色在渐变中占据的位置(比重),如果为空,则表示上述颜色的集合在渐变中均匀出现
第七个参数为渲染器平铺的模式,一共有三种
-CLAMP
边缘拉伸
-REPEAT
在水平和垂直两个方向上重复,相邻图像没有间隙
-MIRROR
以镜像的方式在水平和垂直两个方向上重复,相邻图像有间隙
2、public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, TileMode tile)
其他参数同上
int color0表示渐变起始颜色
int color1表示渐变终止颜色
二、onDraw()和 onSizeChanged():
onDraw() :绘制图形onSizeChanged() 在控件大小发生改变时调用。所以这里初始化会被调用一次(获取控件的宽和高度)
使用 getPaint() 方法获取当前绘制的 TextVIew 的 Paint 对象,给这个Paint 对象设置 LinearGradient 属性, paint.setShader(linearGradient);接着重写 onDraw()绘制需要的图形。
直接上代码(注释很清楚):
xml:
<RelativeLayout 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:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.ht.lineargradienttv.MainActivity"> <com.ht.lineargradienttv.LinearGradientTv android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" android:text="你有多久单身一人不再去旅行" android:textSize="18sp" app:showStyle="UNIDIRECTION" app:showTime="40" app:tvColor="#f54b4b" /> </RelativeLayout>
code:
/** * Package com.ht.lineargradienttv * Created by HT on 2018/7/3. */ public class LinearGradientTv extends AppCompatTextView { private TextPaint paint; private LinearGradient linearGradient; private Matrix matrix; private float translateX; private float deltaX = 26; private int showTime;//显示的时间 private int showStyle; public static final int UNIDIRECTION = 0; public static final int LOOP = 1; private int color; public LinearGradientTv(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LinearGradientTextView); showTime = typedArray.getInteger(R.styleable.LinearGradientTextView_showTime, 40); showStyle = typedArray.getInt(R.styleable.LinearGradientTextView_showStyle, UNIDIRECTION); color = typedArray.getColor(R.styleable.LinearGradientTextView_tvColor, Color.RED); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); paint = getPaint(); String text = getText().toString(); float textWidth = paint.measureText(text); //GradientSize三个文字的大小 int gradientSize = (int) (3 * textWidth / text.length()); //边缘融合 linearGradient = new LinearGradient(-gradientSize, 0, gradientSize, 0, new int[]{Color.YELLOW, color, Color.YELLOW}, new float[]{0, 0.5f, 1}, Shader.TileMode.CLAMP); paint.setShader(linearGradient); matrix = new Matrix();//Matrix表示变换矩阵 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float textWidth = (getPaint().measureText(getText().toString())); translateX += deltaX; switch (showStyle) { case UNIDIRECTION: //单向闪动 if (translateX > textWidth + 1 || translateX < 1) { translateX = 0; translateX += deltaX; } break; case LOOP: //来回闪动 if (translateX > textWidth + 1 || translateX < 1) { deltaX = -deltaX; } break; } matrix.setTranslate(translateX, 0);//平移,两个参数分别为x和y方向平移量 linearGradient.setLocalMatrix(matrix);//渐变的平移矩阵(setLocalMatrix方法是Shader类的方法) postInvalidateDelayed(showTime);//延迟重绘(刷新) } }
没什么难度,效果完成!主要是一些自定义 view 的基础。