最近工作中遇到了一个跑马灯怎么样做都不能愉快跑起来的问题,是这样的,我要动态添加一个通知栏,那通知栏里的内容就是跑马灯,但是要求是超过20个字才会跑马灯,其余的正常展示,那这个要怎么搞呢?有童鞋可能说了,设置maxLength为20不就可以了,然后让宽度自适应,不过很遗憾,这样并不可行,原因很简单,跑马灯效果的实现是需要确切知道宽度才能跑起来的。但是仅仅有宽度就够了,再次遗憾告诉你,这还远远不够,除了必要的属性之外,动态添加TextView需要考虑到容器的容纳问题,就是textview其实还没有加进去,也就是父布局其实仍然对这个textview一无所知,因此为了能够跑起来,我们需要异步调用textview.setSelected(true),方法就是通过view.post(new Runnable()),事实上无需调用delay方法。
那么textview的setSelected方法是做什么用的呢,首先我们来看下下面截取的部源码:
...省略...
@Override
public void setSelected(boolean selected) {
boolean wasSelected = isSelected();
super.setSelected(selected);
if (selected != wasSelected && mEllipsize == TextUtils.TruncateAt.MARQUEE) {
if (selected) {
startMarquee();
} else {
stopMarquee();
}
}
}
...省略...
很明显,这个方法是告诉textview我被选中了,我可以开始跑马灯了。由于startMarquee的条件也很复杂,只有最终满足条件的才能愉快的跑起来。
下面看下我的解决方案:
noticeTextView = (MarqueeTextView) View.inflate(getContext(), R.layout.marque_textview, null);
params.height = ResUtils.getDimenToInt(R.dimen.y52);
//动态设置宽度,最多显示20个字符,多余20个字符显示跑马灯
final String content = info.getContent();
if (content.length() > MARQUEE_MAX_LENGTH) {
noticeTextView.setHorizontalFadingEdgeEnabled(true);
int vWidth = ViewUtils.computeTextWidthDynamic(content.substring(0, MARQUEE_MAX_LENGTH), ResUtils.getDimensionPixelSize(R.dimen.x26));
params.width = vWidth + ResUtils.getDimenToInt(R.dimen.x56);
post(() -> noticeTextView.setSelected(true));
} else {
//非跑马灯去除左右阴影
noticeTextView.setHorizontalFadingEdgeEnabled(false);
noticeTextView.setEllipsize(null);
}
noticeTextView.setText(content);
computeTextWidthDynamic方法只是动态计算超过20个字之后的宽度,以此来设置宽度实现跑马灯。
还有一点我需要告诉大家,如果一开始不能设置宽度,通过异步获取自适应的宽度之后再去重新设置宽度以及调用setSelected(true)也是无效的,这些都是开发中测试过的。当然如果大家还有什么意见或者感觉我现在的解释有问题,欢迎指出。