最近项目用到文本滚动通知效果,首先想到了跑马灯可是限制太多不适用,就自己写了两种实现方式,本篇来介绍第一种滚动方式。
1.通过scrollTo()方法来实现。
这个方法原理是,需要一个承载TextView的父控件,我这里用到得是一个自定义RelativeLayout,在里面添加一个TextView。通过父控件RelativeLayout的不断scrollTo()方法,来实现TextView滚动效果。
重写自定义RelativeLayout的onDraw方法,在onDraw调用scrollTo滑动效果会比较流畅,下面是代码。
/**
* 自定义RelativeLayout构造方法,把textview加入布局中
* @param context
* @param width
* @param height
*/
public PlayNotifyInnerWindow(Context context) {
super(context);
mContext = context;
// TODO Auto-generated constructor stub
this.setLayoutParams(newLayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));//设置大小
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.paly_notiry_text, null);
tv = (TextView) view.findViewById(R.id.tv_notif);
this.addView(view);//添加文本
}
下面是文本样式设置:
if (!"".equals(left)) {
// layoutParams.leftMargin=Integer.parseInt(left);
layoutParams.setMargins(Integer.parseInt(left),0, 0, 0);//设置边距
}
if (!"".equals(right)) {
layoutParams.setMargins(0, 0, Integer.parseInt(right), 0);//设置边距
}
if (!"".equals(left) && !"".equals(right)) {
layoutParams.setMargins(Integer.parseInt(left), 0,//设置边距
Integer.parseInt(right), 0);
}
if (!"".equals(bottom)) {
layoutParams.topMargin = Integer.parseInt(bottom);//设置边距
} else {
layoutParams.topMargin = 0;
}
msp = new SpannableString(content);
if (isB == true) {//是否加粗
tv.getPaint().setFakeBoldText(true);
} else {
tv.getPaint().setFakeBoldText(false);
}
if (isI == true) {//是否斜体
tv.getPaint().setTextSkewX(-0.5f);
} else {
tv.getPaint().setTextSkewX(0f);
}
if (isU == true) {//是否有下划线
tv.getPaint().setUnderlineText(true);
} else {
tv.getPaint().setUnderlineText(false);
}
//播放速度
if (mspeed != null && !"".equals(mspeed)) {
speed = Integer.parseInt(mspeed);
} else {
speed = 5;
}
//循环次数
if (cicrle != null && !"".equals(cicrle)) {
cicle = Integer.parseInt(cicrle);
} else {
cicle = 10000;
}
//背景颜色
if (bgColor != 0 && isTran == false) {
this.setBackgroundColor(bgColor);
} else {
this.setBackgroundColor(Color.TRANSPARENT);
}
if (bgZiti != 0) {
// 设置字体前景色
msp.setSpan(new ForegroundColorSpan(bgZiti), 0,
content.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 设置前景色为洋红色
} else {
msp.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), 0,
content.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 正常
}
//字体大小
if (!"".equals(zihao)) {
fontSize = Util.px2sp(mContext,
Util.sp2px(mContext, Integer.parseInt(zihao)) * rate);
tv.setTextSize(fontSize);
} else {
fontSize = Util
.px2sp(mContext, Util.sp2px(mContext, 24) * rate);
tv.setTextSize(fontSize);
}
if (!"".equals(ziti)) {
Typeface tf = Util.choiceTypeface(ziti);
tv.setTypeface(tf);// 设置字体
} else {
msp.setSpan(new TypefaceSpan("monospace"), 0, content.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
//设置文本,可设置有样式文本
tv.setText(msp);
//自定义文字样式,立体,悬浮,碑刻,套色
FontEffects mFontEffects = new FontEffects(tv, null);
mFontEffects.setFontEffects(effect);
i = 0;//循环次数标志位
this.startScroll();//开始滚动
// 开始滚动
public void startScroll() {
this.setVisibility(View.VISIBLE);
isStop = false;
invalidate();//重新绘制(执行onDraw)
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (!isStop) {
currentScrollX -= speed;// 滚动速度
scrollTo(currentScrollX, 0);
if (getScrollX() <= -(this.getWidth())) {// 如果滚动位置大于控件宽度说明已经滚动出去
currentScrollX = textWidth;// 初始化位置
// return;
if (i >= cicle - 1) {// 判断是否到达循环次数
// reach max times
stopScroll();
// return;
} else {
i++;
}
}
invalidate();
}
}
//停止滚动
public void stopScroll() {
isStop = true;
this.setVisibility(View.GONE);
// scrollTo(0, 0);
}
以上就是第一种方法的实现,这种方法单独滚动没有问题,但是我们这个项目有很多动画是自定义控件重写OnDraw所以会有动画冲突,出现卡顿现象。所以有了后面两种方法。