哈喽,大家好,好久没有更新内容了,最近公司需要一个控件,跑马灯效果,可以左右滚动和上下滚动的功能,本人呢,本着能不自己写就不自己写的原则,就在网上大肆搜刮抢夺别人的代码功能,结果捏,那个,大部分都是一样,我觉得是一个人写好,然后,一群人转载的那种,让我很是费解啊,为了骗分,有的竟然那么高的分,让我很是无奈啊,其实吧,用分也没关系,可是呢,用完之后,发现没用,就很是难受啊,要么是横向可以滚动,实现得也很不错,然后,改成垂直的就那么的不是很完美了,也可能是自己能力有限吧,没有改好,其实呢,各位大佬们,你们既然发了功能,就不能把功能写详细点吗 ?让我这个小渣渣看的很是摸不着北啊 ,我就想到了,既然是滚动效果,然后呢,要想平滑的话,其实,很简单,就自己想了下,用安卓的动画,来实现这个效果,所以,我就写了今天这个博客,横向平移动画,和上下平移动画 ,具体实现规则呢,就看下面听我一点一点给你们详细说一下吧,其实,很简单,就是,写一个自定义控件,继承LinearLayout,因为,虽然我是一个TextView滚动控件,但是,我这里面,一直是TextView 自己滚动,所以,就要在LinearLayout,或者别的盒子控件,RelativeLayout也可以,别的布局都行,随你,但是,你引入的布局控件一定要是这个就行
1、控件,继承LinearLayout :
public class RollTextView extends LinearLayout
2、几个实现方法实现出来:
public RollTextView(Context context) {
super(context);
init();
}
public RollTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public RollTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
3、上面也看见了,有一个init(),是的,下面就是写这个了 ,里面就是引入一个布局然后获取当前的textview内容:
private void init() {
View inflate = inflate(getContext(), R.layout.rollview_layout, this);
llView = inflate.findViewById(R.id.ll_view);
llViewBg = inflate.findViewById(R.id.ll_view_bg);
tvMsg = inflate.findViewById(R.id.tv_msg);
crrentMsg = tvMsg.getText().toString().trim();
}
4、然后,我把布局文件rollview_layout.xml也贴出来,看明白的自然就能知道:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_view_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@color/colorAccent">
<LinearLayout
android:id="@+id/ll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是测试数据,看一下效果如何!"
android:textSize="30sp" />
</LinearLayout>
</LinearLayout>
5、然后呢,就需要测量数据了,并且在测量后,得到布局中textView 应该多高和多宽,因为是对tetview 进行位移,所以,你的文本有多少,就将textview 控件进行动态设置宽高,方法传入的数据就是,当前文本内容,根据你自己设置的boolean值,来确定是横向滚动还是上下滚动
/**
* 测量数据
*
* @param msg
*/
private void getViewMesureData(String msg) {
TextPaint tp = tvMsg.getPaint();
String newMsg = msg;
int textLength;
if (!vertical) {
if (newMsg != null) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(newMsg);
newMsg = m.replaceAll("");
}
tvMsg.setText(newMsg);
textLength = (int) tp.measureText(newMsg);
}else{
tvMsg.setText(msg);
textLength = (int) tp.measureText(msg);
}
ViewTreeObserver vto = llView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
int height = getHeight();
int width = getWidth();
int lineHeight = tvMsg.getLineHeight();
int lineCount = tvMsg.getLineCount();
int textWidth = Double.valueOf(textSize).intValue();
int tvMsgheight = lineHeight * lineCount;
LayoutParams lp = (LayoutParams) tvMsg.getLayoutParams();
if (!vertical) {
lp.width *= textLength;
FromXposition = width - PdLeft - PdRight;
ToXposition = -textLength;
FromYposition = 0;
ToYposition = 0;
RollMilion = RollTime * (textLength + width) / 10;
} else {
lp.height = tvMsgheight;
FromXposition = 0;
ToXposition = 0;
FromYposition = height - PdBottom - PdTop;
ToYposition = -tvMsgheight;
RollMilion = RollTime * (tvMsgheight + height) / 10;
}
tvMsg.setLayoutParams(lp);
startRollAnimation();
llView.getViewTreeObserver().removeOnPreDrawListener(this);
return true; //返回true,继续执行draw()
}
});
}
6、下面将动画功能加进来:
/**
* 开始滚动
*/
private void startRollAnimation() {
if (rollTranslateAnimation != null) {
rollTranslateAnimation = null;
}
rollTranslateAnimation = new TranslateAnimation(FromXposition, ToXposition, FromYposition, ToYposition);
rollTranslateAnimation.setDuration(RollMilion);
rollTranslateAnimation.setRepeatMode(Animation.RESTART);
if (linearInterpolator == null) {
linearInterpolator = new LinearInterpolator();
}
rollTranslateAnimation.setInterpolator(linearInterpolator);
rollTranslateAnimation.setRepeatCount(ValueAnimator.INFINITE);
tvMsg.startAnimation(rollTranslateAnimation);
}
7、暂停动画:
/**
* 暂停动画
*/
public void stopViewRoll() {
if (rollTranslateAnimation != null)
rollTranslateAnimation.cancel();
}
8、更改文本内容:
/**
* 更改文本内容
*
* @param msg
*/
public void setRollText(String msg) {
crrentMsg = msg;
tvMsg.setText(crrentMsg);
stopViewRoll();
getViewMesureData(crrentMsg);
}
9、设置滚动方向:
/**
* 设置滚动方向
*
* @param type
*/
public void setDirection(String type) {
if (type.equals("1")) {
vertical = false;
} else if (type.equals("2")) {
vertical = true;
}
}
10、设置背景,颜色或者背景图片:
/**
* 设置view背景颜色
*
* @param bgcolor
*/
public void setRollbackground(int bgcolor) {
llViewBg.setBackgroundColor(bgcolor);
}
/**
* 设置view背景图片
*
* @param background
*/
public void setRollbackground(Drawable background) {
llViewBg.setBackground(background);
}
11、设置字体大小:
/**
* 设置字体大小
*/
public void setTextSize(int size) {
tvMsg.setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
stopViewRoll();
}
12、设置padding值:
/**
* 设置内部间距
*
* @param paddingLeft
* @param paddingTop
* @param paddingRight
* @param paddingBottom
*/
public void setPadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
LayoutParams lp = (LayoutParams) llView.getLayoutParams();
lp.leftMargin = paddingLeft;
lp.topMargin = paddingTop;
lp.rightMargin = paddingRight;
lp.bottomMargin = paddingBottom;
llView.setLayoutParams(lp);
PdLeft = paddingLeft;
PdTop = paddingTop;
PdRight = paddingRight;
PdBottom = paddingBottom;
stopViewRoll();
}
13、设置滚动速度:
/**
* 设置控件滚动速度
* 基准值:1000
*
* @param speedValue
*/
public void setRollSpeed(int speedValue) {
RollTime = speedValue;
}
14、设置字体颜色:
/**
* 设置字体颜色
*
* @param color
*/
public void setRollTextColor(int color) {
tvMsg.setTextColor(color);
}
15、这里是控件最上面的抽取的公共变量部分:
private boolean vertical = true;
private TextView tvMsg;
private LinearInterpolator linearInterpolator = new LinearInterpolator();//动画滚动类型
private int RollMilion = 1;
private int RollTime = 2000; //默认滚动速度
private Animation rollTranslateAnimation;
private Animation verticalTranslateAnimation;
private int FromXposition = 0;
private int FromYposition = 0;
private int ToXposition = 0;
private int ToYposition = 0;
private LinearLayout llView, llViewBg;
private String crrentMsg = "";
private int PdTop = 0;
private int PdLeft = 0;
private int PdRight = 0;
private int PdBottom = 0;
private float textSize;
private int textLength;
16、还有一些需要的,自己看着改吧,其实,很简单,我这个功能,不用自己画,只需要自己计算一下滚动时间可以初始位置和结束位置就可以了,所以很容易理解,为了大家能更容易看些,我就将全部的代码都贴出来吧,嘿嘿,肯定有人问,为啥不直接就贴出来,在这废话一大堆,我说为了装13,你们信不信,这样显得我写的长,哈哈:
package com.tiekeyuan.rolltextview;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
public class RollTextView extends LinearLayout {
private boolean vertical = true;
private TextView tvMsg;
private LinearInterpolator linearInterpolator = new LinearInterpolator();
private int RollMilion = 1;
private int RollTime = 2000;
private Animation rollTranslateAnimation;
private Animation verticalTranslateAnimation;
private int FromXposition = 0;
private int FromYposition = 0;
private int ToXposition = 0;
private int ToYposition = 0;
private LinearLayout llView, llViewBg;
private String crrentMsg = "";
private int PdTop = 0;
private int PdLeft = 0;
private int PdRight = 0;
private int PdBottom = 0;
private float textSize;
private int textLength;
public RollTextView(Context context) {
super(context);
init();
}
public RollTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public RollTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
View inflate = inflate(getContext(), R.layout.rollview_layout, this);
llView = inflate.findViewById(R.id.ll_view);
llViewBg = inflate.findViewById(R.id.ll_view_bg);
tvMsg = inflate.findViewById(R.id.tv_msg);
crrentMsg = tvMsg.getText().toString().trim();
}
/**
* 测量数据
*
* @param msg
*/
private void getViewMesureData(String msg) {
TextPaint tp = tvMsg.getPaint();
String newMsg = msg;
int textLength;
if (!vertical) {
if (newMsg != null) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(newMsg);
newMsg = m.replaceAll("");
}
tvMsg.setText(newMsg);
textLength = (int) tp.measureText(newMsg);
}else{
tvMsg.setText(msg);
textLength = (int) tp.measureText(msg);
}
ViewTreeObserver vto = llView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
int height = getHeight();
int width = getWidth();
int lineHeight = tvMsg.getLineHeight();
int lineCount = tvMsg.getLineCount();
int textWidth = Double.valueOf(textSize).intValue();
int tvMsgheight = lineHeight * lineCount;
LayoutParams lp = (LayoutParams) tvMsg.getLayoutParams();
if (!vertical) {
lp.width *= textLength;
FromXposition = width - PdLeft - PdRight;
ToXposition = -textLength;
FromYposition = 0;
ToYposition = 0;
RollMilion = RollTime * (textLength + width) / 10;
} else {
lp.height = tvMsgheight;
FromXposition = 0;
ToXposition = 0;
FromYposition = height - PdBottom - PdTop;
ToYposition = -tvMsgheight;
RollMilion = RollTime * (tvMsgheight + height) / 10;
}
tvMsg.setLayoutParams(lp);
startRollAnimation();
llView.getViewTreeObserver().removeOnPreDrawListener(this);
return true; //返回true,继续执行draw()
}
});
}
/**
* 开始滚动
*/
private void startRollAnimation() {
if (rollTranslateAnimation != null) {
rollTranslateAnimation = null;
}
rollTranslateAnimation = new TranslateAnimation(FromXposition, ToXposition, FromYposition, ToYposition);
rollTranslateAnimation.setDuration(RollMilion);
rollTranslateAnimation.setRepeatMode(Animation.RESTART);
if (linearInterpolator == null) {
linearInterpolator = new LinearInterpolator();
}
rollTranslateAnimation.setInterpolator(linearInterpolator);
rollTranslateAnimation.setRepeatCount(ValueAnimator.INFINITE);
tvMsg.startAnimation(rollTranslateAnimation);
}
/**
* 暂停动画
*/
public void stopViewRoll() {
if (rollTranslateAnimation != null)
rollTranslateAnimation.cancel();
}
/**
* 开始动画
*/
public void startViewRoll() {
getViewMesureData(crrentMsg);
}
/**
* 更改文本内容
*
* @param msg
*/
public void setRollText(String msg) {
crrentMsg = msg;
tvMsg.setText(crrentMsg);
stopViewRoll();
getViewMesureData(crrentMsg);
}
/**
* 设置滚动方向
*
* @param type
*/
public void setDirection(String type) {
if (type.equals("1")) {
vertical = false;
} else if (type.equals("2")) {
vertical = true;
}
}
/**
* 设置view背景颜色
*
* @param bgcolor
*/
public void setRollbackground(int bgcolor) {
llViewBg.setBackgroundColor(bgcolor);
}
/**
* 设置view背景图片
*
* @param background
*/
public void setRollbackground(Drawable background) {
llViewBg.setBackground(background);
}
/**
* 设置字体大小
*/
public void setTextSize(int size) {
tvMsg.setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
stopViewRoll();
}
/**
* 设置内部间距
*
* @param paddingLeft
* @param paddingTop
* @param paddingRight
* @param paddingBottom
*/
public void setPadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
LayoutParams lp = (LayoutParams) llView.getLayoutParams();
lp.leftMargin = paddingLeft;
lp.topMargin = paddingTop;
lp.rightMargin = paddingRight;
lp.bottomMargin = paddingBottom;
llView.setLayoutParams(lp);
PdLeft = paddingLeft;
PdTop = paddingTop;
PdRight = paddingRight;
PdBottom = paddingBottom;
stopViewRoll();
}
/**
* 设置控件滚动速度
* 基准值:1000
*
* @param speedValue
*/
public void setRollSpeed(int speedValue) {
RollTime = speedValue;
}
/**
* 设置字体颜色
*
* @param color
*/
public void setRollTextColor(int color) {
tvMsg.setTextColor(color);
}
}
最后,当然,个人写的是根据个人公司需要的功能写的,很多属性,你们可以直接配置一下,那样就可以直接在调用的地方,xml里面直接将属性写上不用那么多方法调用,所以根据个人项目需要吧,然后呢,个人觉得,还是有必要将demo也发一下,我需要一点积分,如果可以的话,大家支持一下,给我点积分,谢谢大家了!
资源Demo下载:点我点我,对,就是,点我,就能下载了 .