【前言】

在Textview设置的宽度有限,而需要显示的文字又比较多的情况下,往往需要给Textview设置跑马灯效果才能让用户完整地看到所有设置的文字,所以给TextView设置跑马灯效果的需求是很常见的

一、新手设置跑马灯效果

1、先在xml中给Textview设置好对应的属性

 <TextViewandroid:id="@+id/tv"android:layout_width="200dp"android:layout_height="wrap_content"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@id/show_float"android:singleLine="true"android:ellipsize="marquee"android:focusable="true"android:focusableInTouchMode="true"android:marqueeRepeatLimit="-1"android:layout_marginTop="20dp"android:padding="10dp"android:text="欢迎来到跑马灯新手村,这是新手示例~"android:textColor="@color/white"android:background="@drawable/com_live_rounded_rectangle"/>

2、然后在代码中设置请求获取焦点即可

        TextView tv = findViewById(R.id.tv);tv.requestFocus();

这样设置之后,跑马灯的效果就出来了

【关键点讲解】

1、android:layout_width 是限制为固定宽度,同时文本的长度大于所设置的宽度,要是设置android:layout_widthwrap_content, 那么Textview的宽度会随着文本长度变长而拉宽,这样就不能出现跑马灯效果
2、android:singleLine="true"设置Textview只能一行显示,要是不设置为true,默认会自动换行,显示为多行,这样的话,也不能出现跑马灯效果
3、android:ellipsize="marquee"设置要是文本长度超出Textview的宽度时候,文本应该以跑马灯效果显示,这个是设置跑马灯效果最关键的设置,android:ellipsize还可以取值startendmiddlenone,分别是开头显示省略号结尾显示省略号中间显示省略号直接截断
4、android:focusable="true"设置Textview可以获取焦点,跑马灯效果需要获取到焦点时候才生效,Textview默认是不获取焦点的
5、android:focusableInTouchMode="true"设置在触摸模式下可以获取焦点,目前智能机基本都是自动进入触摸模式,其实目前只要设置android:focusableInTouchMode="true",默认android:focusable也会变为true了
6、android:marqueeRepeatLimit="-1"设置跑马灯循环的次数,-1表示无限循环,不设置的话,默认是循环3次
7、 tv.requestFocus();设置获取焦点, 只有当该view的focusable属性为true时候才生效

【总结】

1、一定要设置android:focusableInTouchMode="true",若是只设置了android:focusable="true"android:focusableInTouchMode没设置,那么跑马灯效果是不生效的,因为进入触摸模式之后,isFocusable()返回false,下面看看Texivew startMarquee()源码就知道需要满足什么条件才会开始跑马灯特效:

     private void startMarquee() {// Do not ellipsize EditTextif (getKeyListener() != null) return;if (compressText(getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight())) {return;}// 1、跑马灯控制类没有创建或者跑马灯效果已经停止if ((mMarquee == null || mMarquee.isStopped()) && // 2、当前Textview是获取到焦点或者被选中状态(isFocused() || isSelected())// 3、文本的行数只有一行&& getLineCount() == 1// 4、文本长度大于Textview的宽度 && canMarquee()) {if (mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_FADE;final Layout tmp = mLayout;mLayout = mSavedMarqueeModeLayout;mSavedMarqueeModeLayout = tmp;setHorizontalFadingEdgeEnabled(true);requestLayout();invalidate();}if (mMarquee == null) mMarquee = new Marquee(this);mMarquee.start(mMarqueeRepeatLimit);}}private boolean canMarquee() {int width = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();return width > 0 && (mLayout.getLineWidth(0) > width|| (mMarqueeFadeMode != MARQUEE_FADE_NORMAL && mSavedMarqueeModeLayout != null&& mSavedMarqueeModeLayout.getLineWidth(0) > width));}

二、高端玩家设置跑马灯效果

从上面总结的TextView跑马灯源码可以看到,只要isFocusable()或者isSelected()方法返回true,那么就没必要管是否触摸模式,是否可以获取焦点之类的问题了,所以我们可以自定义一个类继承于TextView,然后重写isFocusable()直接返回true即可:

public class MarqueeTextView extends TextView {public MarqueeTextView(Context context) {super(context);initView(context);}public MarqueeTextView(Context context, AttributeSet attrs) {super(context, attrs);initView(context);}public MarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView(context);}private void initView(Context context) {this.setEllipsize(TextUtils.TruncateAt.MARQUEE);this.setSingleLine(true);this.setMarqueeRepeatLimit(-1);}//最关键的部分public boolean isFocused() {return true;}
}

1、直接在Xml中使用自定义的MarqueeTextView,那么跑马灯效果就出来了,无需任何额外配置

 <com.example.MarqueeTextViewandroid:id="@+id/tv"android:layout_width="200dp"android:layout_height="wrap_content"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@id/show_float"android:layout_marginTop="20dp"android:padding="10dp"android:text="欢迎来到跑马灯高端玩家局,这是高端玩法示例~"android:textColor="@color/white"android:background="@drawable/com_live_rounded_rectangle"/>

来看看效果:

三、延伸阅读

假如有这样一个需求:因为显示文本的空间有限,所以只能用跑马灯的效果来给用户展示文本,但是在用户完整地看完一遍文本之后,需要隐藏掉Textview,那么问题来了,我们怎么知道跑马灯效果什么时候跑完一遍呢?先来看看Textview跑马灯部分Marquee类的部分源码:

       void start(int repeatLimit) {//重复次数设置0,那就直接停止跑马灯if (repeatLimit == 0) {stop();return;}//...省略掉大部分不相关的代码mChoreographer.postFrameCallback(mStartCallback);}}private Choreographer.FrameCallback mStartCallback = new Choreographer.FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {mStatus = MARQUEE_RUNNING;mLastAnimationMs = mChoreographer.getFrameTime();tick();}};void tick() {if (mStatus != MARQUEE_RUNNING) {return;}if (textView != null && (textView.isFocused() || textView.isSelected())) {long currentMs = mChoreographer.getFrameTime();long deltaMs = currentMs - mLastAnimationMs;mLastAnimationMs = currentMs;float deltaPx = deltaMs * mPixelsPerMs;mScroll += deltaPx;//要是跑马灯滚动的距离大于最大距离,那么回到给mRestartCallbackif (mScroll > mMaxScroll) {mScroll = mMaxScroll;mChoreographer.postFrameCallbackDelayed(mRestartCallback, MARQUEE_DELAY);} else {mChoreographer.postFrameCallback(mTickCallback);}textView.invalidate();}}private Choreographer.FrameCallback mRestartCallback = new Choreographer.FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {if (mStatus == MARQUEE_RUNNING) {if (mRepeatLimit >= 0) {mRepeatLimit--;}start(mRepeatLimit);}}}

从上面对Marquee源码分析可知,跑马灯跑完一轮之后会调用到MarqueemRestartCallback对象的doFrame方法,那么我们来一招“偷龙转凤”,通过反射把mRestartCallback对象替换成我们自己实例化的对象,那么在跑马灯跑完一轮之后就会回调到我们替换的对象中,这样就实现了对跑马灯效果跑完一轮的监听,实现源码如下:

public class MarqueeTextView extends androidx.appcompat.widget.AppCompatTextView {private Choreographer.FrameCallback mRealRestartCallbackObj;private Choreographer.FrameCallback mFakeRestartCallback;private OnShowTextListener mOnShowTextListener;public MarqueeTextView(Context context, OnShowTextListener onShowTextListener) {super(context);initView(context);this.mOnShowTextListener = onShowTextListener;}public MarqueeTextView(Context context, AttributeSet attrs) {super(context, attrs);initView(context);}public MarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView(context);}private void initView(Context context) {//绕过隐藏api的限制Reflection.unseal(context.getApplicationContext());//设置跑马灯生效条件this.setEllipsize(TextUtils.TruncateAt.MARQUEE);this.setSingleLine(true);this.setFocusable(true);//反射设置跑马灯监听try {//从TextView类中找到定义的字段mMarqueeField marqueeField = ReflectUtil.getDeclaredField(TextView.class, "mMarquee");//获取Marquee类的构造方法Marquee(TextView v)Constructor declaredConstructor = ReflectUtil.getDeclaredConstructor(Class.forName("android.widget.TextView$Marquee"), TextView.class);//实例化一个Marquee对象,传入参数是Textview对象Object marqueeObj = declaredConstructor.newInstance(this);//从Marquee类中找到定义的字段mRestartCallback,重新开始一轮跑马灯时候会回调到这个对象doFrame()方法Field restartCallbackField = ReflectUtil.getDeclaredField(Class.forName("android.widget.TextView$Marquee"), "mRestartCallback");//从Marquee实例对象中获取到真实的mRestartCallback对象mRealRestartCallbackObj = (Choreographer.FrameCallback) restartCallbackField.get(marqueeObj);//构造一个假的mRestartCallback对象,用来监听什么时候跑完一轮跑马灯效果mFakeRestartCallback = new Choreographer.FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {//这里还是执行真实的mRestartCallback对象的代码逻辑mRealRestartCallbackObj.doFrame(frameTimeNanos);Log.i("min77","跑马灯文本显示完毕");//回调通知跑完一轮if(MarqueeTextView.this.mOnShowTextListener != null){MarqueeTextView.this.mOnShowTextListener.onComplete(0);}}};//把假的mRestartCallback对象设置给Marquee对象,其实就是代理模式restartCallbackField.set(marqueeObj, mFakeRestartCallback);//把自己实例化的Marquee对象设置给TextviewmarqueeField.set(this, marqueeObj);} catch (Exception e) {e.printStackTrace();Log.e("min77",e.getMessage());}}//最关键的部分public boolean isFocused() {return true;}/*** 是否显示完整文本*/public interface OnShowTextListener{void onComplete(int delayMillisecond);}}

效果如下:

Android TextView设置跑马灯效果相关推荐

  1. android:ellipsize = marquee 跑马灯,Android基于TextView属性android:ellipsize实现跑马灯效果的方法...

    本文实例讲述了Android基于TextView属性android:ellipsize实现跑马灯效果的方法.分享给大家供大家参考,具体如下: Android系统中TextView实现跑马灯效果,必须具 ...

  2. Android 文本实现跑马灯效果 用自带的TextView控件

    注意跑马灯需要文本已经确定的情况下设置 1.第一种方式在布局代码中 <TextViewandroid:id="@+id/music_name_tv"android:layou ...

  3. android实现跑马灯效果,TextView实现跑马灯效果 就这么简单!

    一.方法 这里我们用两种方法来实现跑马灯效果,虽然实质上是一种 实质就是: 1.TextView调出跑马灯效果 2.TextView获取焦点 第一种: 1.TextView调出跑马灯效果 androi ...

  4. TextView的跑马灯效果实现

    TextView的跑马灯效果实现 问题描述 当文字内容过长,但是只允许显示一行时,可以将文字显示为跑马灯效果,即文字滚动显示. 代码实现 第一种方法实现 先查询TextView控件的属性,得到以下信息 ...

  5. TextView的跑马灯效果(AS开发实战第二章学习笔记)

    TextView的跑马灯效果 跑马灯用到的属性与方法说明 singleLine 指定文本是否单行显示 ellipsize 指定文本超出范围后的省略方式 focusable 指定是否获得焦点,跑马灯效果 ...

  6. Android文字实现跑马灯效果——两种方法实现

    第一种方法,设置textView的属性 <com.example.glide.MarqueeViewandroid:id="@+id/marqueeView"android: ...

  7. Android开发 实现跑马灯效果滚动字幕

    Android开发 实现跑马灯效果滚动字幕 ~! ~ !~ 浙江温州!~ 浙江温州!~江南皮革厂倒闭了! 黄鹤老板欠下了3.5个亿 ! 带着他的小姨子跑了! 我们没有办法 没有办法,拿着钱包抵工资, ...

  8. android:ellipsize实现跑马灯效果总结

    原文地址:http://www.cnblogs.com/Gaojiecai/archive/2013/06/18/3142783.html android:ellipsize用法如下: 在xml中 a ...

  9. TextView实现跑马灯效果

    经常使用TextView会出现这样的情况,有限的空间内只能写一行,然后导致好多文字被"..."表示了,如图: 而且有可能是重要信息被隐藏了,于是就有了跑马灯效果. 实现方式很简单: ...

  10. Android studio | From Zero To One ——TextView实现跑马灯效果及聊天室、文字直播间

    ================================================ 博主github:https://github.com/MichaelBeechan 博主CSDN:h ...

最新文章

  1. 按esc键退出的一个函数
  2. jstree如何禁止平级拖拽?_小程序为鲜花店经营带来哪些价值?如何搭建一款鲜花小程序?...
  3. 《卓有成效的程序员》----读书笔记一
  4. 经典面试题:将有序数组、有序链表转换成平衡二叉树
  5. OS X EI Captain 下解决 There was a problem confirming the ssl certificate 问题
  6. sql server行列转化和行列置换
  7. WIN7安装VS2008的 Error1935 问题解决方案
  8. 成为Googler的资源分享!
  9. 计算机比赛训练总结500字,比赛活动总结500字(精选7篇)
  10. Fifth season last two episodes,Vegas is an amazing place!!!Ross and Rachel got married???
  11. smb.php如何使用,win10smb1协议怎么开
  12. 【操作系统】操作系统的功能管理与分类
  13. 【线段树】【P5522】[yLOI2019] 棠梨煎雪
  14. k3 审核流程图_K3单据使用解释及流程图明细
  15. 集群策略--集群(clustering)
  16. linux中fflush函数和printf函数 【转】
  17. 数美科技风控前沿| AIGC需要什么内容风控基建?ChatGPT本“人”有话要说
  18. PIC16F887 单片机 电压检测
  19. Cas5.3.14手机号码登录(五)
  20. 小学有计算机课程吗,小学计算机是不是就是信息技术啊

热门文章

  1. Axure RP9 制作平台界面
  2. 如何将论文中的公式图片直接变为word中的公式
  3. 分布式架构 网络传输优化
  4. python二维码_Python 二维码制作
  5. Linux在线词典问题,linux中goldendict发声词典播放报错问题解决方案
  6. fastdds交叉编译
  7. CSS指北——浮动(Floating)规则详解
  8. 警告:integer division in floating-point context
  9. Qt 弹出对话框选择图片并显示
  10. JavaScript图片旋转缩放、像素矩阵获取