转载请标明出处:http://blog.csdn.net/edisonchang/article/details/50000879

前几天一直下雪,早上过来上班,路上特别拥堵,还好赶上了早餐。回到工位后,刚入职不久的产品小鲜肉匆忙过来,希望我在应用列表的头部加一个跑马灯的文字滚动效果,并且能在中午能够看到结果。

对完需求后我就开始了调研和开发工作,因为Android的TextView天生支持跑马灯效果,所以一切看起来都是水到渠成,信手拈来。首先,使用android 原生的TextView控件实现走马灯的滚动效果,需要了解以下几项属性:

     android:ellipsize="marquee"      android:marqueeRepeatLimit="marquee_forever" 

android:ellipsize=”marquee” 表示当文本长度大于View的宽度时以横向滚动方式显示;
android:marqueeRepeatLimit以设置滚动次数,marquee_forever表示无限循环 。

但是仅设置这两个属性,运行代码后TextView是没有滚动效果的,从Textview 实现跑马灯的源码可以看出TextView需要持有焦点才能实现跑马灯效果。

final TextView textView = mView.get();            if (textView != null && (textView.isFocused() || textView.isSelected())) {                long currentMs = mChoreographer.getFrameTime();                long deltaMs = currentMs - mLastAnimationMs;                mLastAnimationMs = currentMs;                float deltaPx = deltaMs / 1000f * mPixelsPerSecond;                mScroll += deltaPx;                if (mScroll > mMaxScroll) {                    mScroll = mMaxScroll;                    mChoreographer.postFrameCallbackDelayed(mRestartCallback, MARQUEE_DELAY);                } else {                    mChoreographer.postFrameCallback(mTickCallback);                }                textView.invalidate();            }

解决这个问题也不复杂,对我们的TextView加上
android:focusable=”true”
android:focusableInTouchMode=”true” 两个属性, 运行代码后TextView就自动滚动起来。从上面的例子可以看出TextView如果实现跑马灯效果,需要同时具备三个条件:

(1)android:ellipsize=”marquee”
(2)TextView单行显示,且内容必须超出TextView大小
(3)TextView要获得焦点

产品同学看了demo的跑马灯效果后,还是比较满意的,与此同时也提出另一些需求,他希望在列表的头部和一些特定的item里面都有滚动效果的TextView,并且可以同时滚动。 这一下确实还是有点为难,TextView要能滚动必须获得当前焦点,而对于一个View上的元素来讲,至多只有一个View能够获取焦点,所以多个TextView同时实现跑马灯效果,已经不是简单的配置就能满足需求了。

但是,我们还是很快就想到了解决方案。其实,从源码中,我们也可以看出,TextView的滚动显示与焦点有关系,一旦TextView失去焦点,TextView会立即停止滚动,所以要想实现多个TextView的同时跑马灯滚动,还得从TextView 的isFocused()方法入手。解决手段简单粗暴,我们直接重写isFocused()方法,让这个方法一直返回true, 果然多个TextView的跑马灯效果可以一并动起来了,示例代码如下:

public class MarqueeTextView extends TextView {    public MarqueeTextView(Context context) {        this(context, null);    }    public MarqueeTextView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MarqueeTextView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    @Override    public boolean isFocused() {        return true;    }}

但是事情往往没有想象中的顺利,将demo测试过的代码合到我们主程序时,却发现首次进入页面后ListView head 中的TextView 无法自动滚动,如果home键退出,或者切到其他页面再返回,就会顺利的滚动起来。

原因在于TextView启动跑马灯时,ListView并没有Layout完成,此时TextView的mLayout 为空 ,导致首次无法自动滚动,解决方法可以延时调用下 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();            }        }    }

以上是setSelected方法的源码实现,从源码中我们发现如果原来TextView 已经是被选中状态,再次调用也是没有效果的,所以我们可以先调用 setSelected(false), 再调用 setSelected(true),这样一来就可以保证TextView的正常滚动 。

    public void setText(String text) {       super.setText(text);        setHorizontallyScrolling(true);        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                setSelected(false);                setSelected(true);            }        }, 3000);    }

至此,跑马灯效果顺利实现了,产品也效果也比较满意。如果您对文章内容有兴趣,请多多关注,有问题请回复

更多相关文章

  1. Android(安卓)Socket 通信实例...【Pnoker】
  2. Android中AVD的使用以及错误处理方法
  3. Android仿真翻页
  4. TextView一行显示一个文字效果
  5. Android笔试和面试常见题目(四)
  6. Android(安卓)自定义View练手Demo(三)实现微信拍一拍的动画效果
  7. Android屏蔽ListView的Item点击事件
  8. Android中下拉通知栏,Activity会走哪些生命周期?
  9. android实现图片翻转动画

随机推荐

  1. android Preference ListPreference Edit
  2. android 邮件地址正则表达式
  3. Android之ScrollView嵌套ListView解决工
  4. Activity中使用AIDL让Service与Activity
  5. Android 去掉toolbar阴影
  6. Android中继承RadioButton后,点击不能选中
  7. android一些核心功能程序代码
  8. android 根据SD卡中图片路径读取并显示SD
  9. Android Facebook分享功能实现
  10. android studio3.1.3和kotlin1.2.51踩坑(