Android TextView设置跑马灯效果

article/2025/10/22 22:21:00

【前言】

     在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);}}

效果如下:
在这里插入图片描述


http://chatgpt.dhexx.cn/article/4oZ6sBLf.shtml

相关文章

css 实现跑马灯效果

最近有一个跑马灯的效果&#xff0c;需要实现。本来想偷个懒从网上随便拷贝一个&#xff0c;结果发现都不太理想&#xff0c;于是自己动手封装了一个&#xff0c;和大家分享一下。 首先我们要知道跑马灯的具体效果是什么样子的。 效果图 我们通过效果图可以看到&#xff0c;在…

h5跑马灯效果

无缝滚动效果 &#xff0c;外加 手指的移动效果 思路&#xff1a; 1.无缝滚动1个内容区域&#xff0c;复制一下这个内容&#xff0c;追加到改内容的后面&#xff0c;形成无缝滚动的效果 2.手指左滑右滑进行x轴方向的加减 代码如下&#xff1a; <template><div cl…

Android --- 跑马灯效果

1、基于开发者文档的官方说明 跑马灯效果主要使用的控件为TextView&#xff0c;其中涉及的几个标签如下所示&#xff1a; android:ellipsize If set, causes words that are longer than the view is wide to be ellipsized instead of broken in the middle. You will often …

html跑马灯效果

该笔记记录 <marquee> 标签&#xff0c;跑马灯除了使用js实现&#xff0c;还可以使用 marquee标签&#xff0c;自带跑马灯效果。&#xff08;marquee已经 Obsolete了&#xff0c;但是它很好用&#xff09; 基本用法 <!-- marquee是块元素&#xff0c;直接在其内部放…

跑马灯效果如何实现?Smartbi一文助你掌握

大数据时代&#xff0c;人的注意力越来越成为一种稀缺资源&#xff0c;让信息去匹配读者注意力&#xff0c;显然优于让人的注意力去适应信息。因此我们就需要在数据呈现上进行创新。那么如何让数据变得动态化&#xff0c;可视化呢&#xff1f;或许可以尝试一下跑马灯效果。 跑…

滚动动画(跑马灯动画)的几种实现方式

在大屏可视化应用中&#xff0c;滚动动效&#xff08;跑马灯效果&#xff09;也是常见的一种数据展现方式&#xff0c;本章节针对字幕滚动和列表滚动效果做一个小小的总结&#xff0c;结合vue框架&#xff0c;具体展示效果如下&#xff0c;从左至右选型技术分别为&#xff1a;m…

本地KMS虚拟服务器,搭建kms本地服务器

搭建kms本地服务器 内容精选 换一换 Kerberos是一种计算机网络认证协议&#xff0c;它允许某实体在非安全网络环境下通信&#xff0c;向另一个实体以一种安全的方式证明自己的身份。它也指由麻省理工实现此协议&#xff0c;并发布的一套免费软件。软件设计上采用客户端/服务器模…

Ubuntu搭建kms服务器

Key Management Service&#xff08;简称:KMS&#xff09;&#xff0c;这个功能是在Windows Vista之后的产品中的一种新型产品激活机制。我们可以利用手里闲置的VPS安装vlmcsd来搭建KMS激活服务器&#xff0c;这篇文章以Ubuntu为例&#xff0c;当然vlmcsd并不局限限于Ubuntu&am…

linux系统安装kms,Linux安装部署KMS服务器

Loading... # Linux 安装部署 KMS 服务器 ## 一、强制关闭kms-server服务 killall kms-server ## 二、下载 kms 服务文件 ### 1、下载 32bit包 如果你要安装 32位包&#xff0c;请直接下载 bash wget https://dl.wxlost.com/2017/01/Linux/vlmcsd-x86-musl-static -O /usr/bi…

centos7快速搭建KMS服务器

1、下载最新的vlmcsd服务端 https://github.com/Wind4/vlmcsd/releases/tag/svn1113 2、解压&#xff0c;并找到binaries/Linux/intel/static/vlmcsd-x64-musl-static并复制到到/usr/bin/vlmcsd 3、赋予执行权限 chmod x /usr/bin/vlmcsd 4、添加开机启动/etc/rc.local中添…

Windows搭建kms服务器

文章目录 使用Windows系统搭建kms服务器前言准备正式开始 使用Windows系统搭建kms服务器 前言 网上有许多搭建的教程&#xff0c;但是使用的都是Linux系统&#xff0c;而我们正常使用的则是Windows系统。对Linux不熟悉的同学看着那左一个代码命令右一个代码命令的教程如同天书…

kms服务器搭建及测试

vlmcsd代码仓库&#xff1a;https://github.com/Wind4/vlmcsd 搭建步骤 本次操作环境centos7&#xff0c;通过内网进行搭建 1.安装依赖环境 yum install gcc git make -y 2.下载源码&#xff0c;编译安装 cd /var/opt/ git clone https://github.com/Wind4/vlmcsd.git cd vlmcs…

kms的服务器改回系统默认,指定kms服务器地址后还原

指定kms服务器地址后还原 内容精选 换一换 您可以通过本节内容解决如下问题:用户在管理控制台执行弹性云服务器相关操作后出现异常,针对管理控制台提示的异常信息,应该如何处理?用户参见《弹性云服务器接口参考》调用云服务器相关的API接口时,如果返回错误码,应该如何处理…

Windows部署KMS服务器

下载安装vlmcsd 地址&#xff1a;https://github.com/Wind4/vlmcsd/releases/download/svn1111/binaries.tar.gz 解压 binaries.tar.gz 文件&#xff0c;找到 \binaries\Windows\intel 下的 vlmcsd-Windows-x86.exe 或者 vlmcsd-Windows-x64.exe &#xff08;根据操作系统选择…

虚拟机如何搭建kms服务器,linux 搭建kms服务器

linux 搭建kms服务器 内容精选 换一换 用户通过管理控制台创建或者导入密钥对后,在购买弹性云服务器时,登录方式选择密钥对,并选择创建或者导入的密钥对。用户购买弹性云服务器成功后,可使用密钥对的私钥登录弹性云服务器。使用的登录工具(如PuTTY、Xshell)与待登录的弹性云…

查看kms服务器信息,查看kms服务器地址

查看kms服务器地址 内容精选 换一换 可以一次添加一台服务器,也可以一次添加同一网段连续IP的多台服务器。进入任务中心可以查看状态信息,如果状态为成功,说明服务器已添加成功。 查询指定后端云服务器组的后端云服务器。支持过滤查询和分页查询。如未特殊说明,匹配规则为精…

kms服务器搭建

kms服务器搭建 1. 下载vlmcsd 地址&#xff1a;https://github.com/Wind4/vlmcsd/releases 下载最终版压缩包: binaries.tar.gz 解压后&#xff0c;可看到这个压缩包适了各种操作系统 以windows为例&#xff1a; cd C:\Users\admin\Desktop\kms\binaries\Windows\intel #create…

kms服务器修改,kms服务器ip地址修改

kms服务器ip地址修改 内容精选 换一换 以NTP服务器、DNS服务器的操作系统均为SUSE为例:登录Linux弹性云服务器。执行以下命令,切换至root用户。sudo su -sudo su -执行以下命令,编辑ntp.conf文件。vim /etc/ntp.confvim /etc/ntp.conf添加以下语句,配置NTP服务器。server N…

KMS服务器

1. 一键安装包&#xff08;本脚本安装完成后&#xff0c;会将 KMS 服务加入开机自启动&#xff09; wget --no-check-certificate https://github.com/teddysun/across/raw/master/kms.sh && chmod x kms.sh && ./kms.sh如果是国内的服务器可能无法下载成功&a…

稳定kms服务器,kms服务器

kms服务器 内容精选 换一换 请您在购买前确保已完成注册和充值。详细操作请参见如何注册公有云管理控制台的用户&#xff1f;登录管理控制台。单击管理控制台左上角的&#xff0c;选择区域和项目。选择“计算 > 弹性云服务器”。单击“购买弹性云服务器”。系统进入购买页。…