Android的TextView支持跑马灯模式,对于显示一些单行长字符串还是不错的,可惜的是TextView要想显示跑马灯模式,必须要设置两个属性focusableInTouchMode=”true”,focusable=”true”,于是问题来了,如果我要在一个界面同时显示两个或两个以上跑马灯呢?
老规矩,在节目开始之前,先来一个搞笑段子:
男孩终于鼓足勇气去向女孩告白:“我喜欢你很久了,你能做我的女朋友吗?”
女孩说:“对不起,我不能喜欢你,因为我有男朋友了。”
男孩失落地转身离去,泪水不住地往下流。
刚走不远,身后传来女孩急切的声音:“你等一下!”
男孩破涕为笑,满怀期待地回头。
女孩说:“就算我没有男朋友,也不会喜欢你的。”
这两个属性不能同时对多个控件生效,所以就不能实现。
于是就有很多小伙伴开始自定义view,自己绘制、做动画、转换等,这是正途,对于系统控件不能满足的需求,我们确实应该优先想到自定义,但是对于这个case,有一个更加简单的方法。
利用一个小技巧骗过系统的判断,也可以说是一个小BUG吧。
系统判断一个TextView有没有获得焦点,是通过isFocused()方法,但是如果两个或两个以上TextView都设置了上面的两个属性,只有一个isFocused()能返回true,这就是为什么我们不能实现多个多个TextView同时显示跑马灯的原因。
于是,方法来了:我们重写TextView的isFocused()方法,强制返回true。
public class MarqueeTextView extends TextView {
public MarqueeTextView(Context context) {
this(context, null);
}
public MarqueeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setFocusableInTouchMode(true);
setSingleLine();
setEllipsize(TruncateAt.MARQUEE);
setMarqueeRepeatLimit(-1);
}
public MarqueeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setFocusable(true);
setFocusableInTouchMode(true);
setSingleLine();
setEllipsize(TruncateAt.MARQUEE);
setMarqueeRepeatLimit(-1);
}
@Override
protected void onFocusChanged(boolean focused, int direction,
Rect previouslyFocusedRect) {
if (focused) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
}
@Override
public void onWindowFocusChanged(boolean focused) {
if (focused) {
super.onWindowFocusChanged(focused);
}
}
@Override
public boolean isFocused() {
return true;
}
}
这样,系统就会认为所有的TextView的isFocused()都是true,就可以实现多个跑马灯的效果。
对于这种方法,我只想说:真是机智啊!!!
好了,本期节目就到这里,感谢大家的收看,下期再见~