11月更文挑战|Android基础-文本实现跑马灯效果

1,278 阅读3分钟

这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

前言

之前在开发中遇到国际化外文翻译后文本特别长的情况,尤其是在Title中显示不下。开始的方案是使用setEllipsizeEnd就是省略后面无法显示的内容采用省略号。但是用户还是希望能够全部显示整个文案,毕竟中文能够完整显示的情况下,外国用户也希望能够看到完整的信息,也符合最终效果也达到信息完整性。万幸的是TextView是原生支持跑马灯的显示方式,但在实际开发中却又遇到设置跑马灯无效的问题,因此在这里做个记录。

在ToolBar中实现跑马灯

由于在ToolBar标题TextView不能直接获取,就无法设置跑马灯属性。因此想到的办法在ToolBar中额外添加一个TextView视图然后隐藏ToolBar内部TextView标题。

但运行结果额外添加的TextView却一直无法正常显示整个文本,而显示效果一直是跑马灯加省略号。错误代码如下:

  • xml资源文件
<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar_top_view"
        android:layout_width="match_parent"
        android:layout_height="@dimen/toolbar_height"
        android:background="?attr/status_bg_color"
        android:gravity="center_vertical"
        android:minHeight="?attr/actionBarSize"
        android:paddingBottom="0dp"
        android:paddingLeft="2dp"
        android:paddingRight="2dp"
        android:paddingTop="0dp"
        android:elevation="0dp"
        app:titleMarginTop="10dp">
        <TextView
            android:id="@+id/tv_title"
            style="@style/toolbar_action_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_gravity="center"
            android:singleLine="true"
            android:ellipsize="marquee"
            android:marqueeRepeatLimit="marquee_forever"
            android:textIsSelectable="true"
             />
    </android.support.v7.widget.Toolbar>
  • 应用代码
   mTvTitle = (TextView) mToolBar.findViewById(R.id.tv_title);
   if(mTvTitle != null){
        mTvTitle.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        mTvTitle.setMarqueeRepeatLimit(-1);
        mTvTitle.setFocusable(true);
        mTvTitle.setFocusableInTouchMode(true);
  }
  protected void setTitle(String title) {
     if (mToolBar != null) {
       if(mTvTitle != null){
          mTvTitle.setText(title);
          mTvTitle.setSelected(true);
       }else{
          mToolBar.setTitle(title);
       }
     }
   }

时间比较久远忘记后来是如何解决完成ToolBar跑马灯功能,这里先留个坑后续补上。

普通文本跑马灯效果

参考大多数案例只要TextView满足以下条件就能实现跑马灯效果:

  1. android:focusable="true"
  2. android:singleLine="true"
  3. android:ellipsize="marquee"
  4. android:marqueeRepeatLimit="marquee_forever"
  5. android:focusableInTouchMode="true"
  6. android:focusable="true"
  7. setSelected(true)
var textView2 = TextView(this)
textView2.also {
    it.isSingleLine = true
    it.ellipsize = TextUtils.TruncateAt.MARQUEE
    it.text = "跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯"
    it.isFocusableInTouchMode = true
    it.isFocusable = true
    it.marqueeRepeatLimit = -1
    it.setHorizontallyScrolling(true)
    it.isSelected = true
}

但实际操作发现在配置项中只要实现以下条件也能实现跑马灯效果

环境
环境:Android 10
minSdkVersion: 18
targetSdkVersion: 29
  1. android:ellipsize="marquee"
  2. android:marqueeRepeatLimit="marquee_forever"
  3. android:singleLine="true"
  4. setSelected(true)
var textView = TextView(this)
textView.also {
    it.isSingleLine = true // 只能使用单行设置 设置maxLine会导致冲突报错
    it.ellipsize = TextUtils.TruncateAt.MARQUEE
    it.text = "跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯跑马灯"
    it.marqueeRepeatLimit = -1 // 设置跑马灯循环次数 -1表示无限
    it.isSelected = true
}

其中是否展示跑马灯效果主要由setSelected方法控制,当为True时执行跑马灯效果。但在很多参考案例中介绍很多情况下TextView是无法实现跑马灯效果的:

  1. 页面出现多个TextView时,焦点丢失
  2. 页面点击EditText,焦点丢失
  3. 弹出对话框,焦点丢失

通过试验发现只有第三种情况会使TextView跑马灯效果失效,弹窗启动时跑马灯停止播放,弹窗消失后跑马灯恢复播放,同样不会出现TextView跑马灯失效的情况。

目前验证后确实没有其他案例中所说的问题,暂时无法确定是否特殊场景导致,但基本功能已经实现。

b60c8284c6a29533edec377b3e2b74a8.gif

自定义实现跑马灯效果

原生TextView跑马灯功能也存在缺陷:

  1. 不能自定义跑马灯速度
  2. 不能设置跑马灯方向,只支持水平方向,不能实现垂直方向
  3. 如以上其他案例会遇到机型跑马灯无法实现情况 如果希望实现更多自定义的跑马灯功能就需要自定义视图组件来实现,当然也有很多优秀的第三方开源库可以使用。例如MarqueeView支持水平和垂直方向文本跑马灯功能。

MarqueeView.gif

参考