Android TextView设置跑马灯效果
【前言】
在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_width
为wrap_content
, 那么Textview的宽度会随着文本长度变长而拉宽,这样就不能出现跑马灯效果
2、android:singleLine="true"
设置Textview只能一行显示,要是不设置为true,默认会自动换行,显示为多行,这样的话,也不能出现跑马灯效果
3、android:ellipsize="marquee"
设置要是文本长度超出Textview的宽度时候,文本应该以跑马灯效果显示,这个是设置跑马灯效果最关键的设置,android:ellipsize
还可以取值start
、end
、middle
、none
,分别是开头显示省略号
、结尾显示省略号
、中间显示省略号
、直接截断
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源码分析可知,跑马灯跑完一轮之后会调用到Marquee
类 mRestartCallback
对象的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设置跑马灯效果相关推荐
- android:ellipsize = marquee 跑马灯,Android基于TextView属性android:ellipsize实现跑马灯效果的方法...
本文实例讲述了Android基于TextView属性android:ellipsize实现跑马灯效果的方法.分享给大家供大家参考,具体如下: Android系统中TextView实现跑马灯效果,必须具 ...
- Android 文本实现跑马灯效果 用自带的TextView控件
注意跑马灯需要文本已经确定的情况下设置 1.第一种方式在布局代码中 <TextViewandroid:id="@+id/music_name_tv"android:layou ...
- android实现跑马灯效果,TextView实现跑马灯效果 就这么简单!
一.方法 这里我们用两种方法来实现跑马灯效果,虽然实质上是一种 实质就是: 1.TextView调出跑马灯效果 2.TextView获取焦点 第一种: 1.TextView调出跑马灯效果 androi ...
- TextView的跑马灯效果实现
TextView的跑马灯效果实现 问题描述 当文字内容过长,但是只允许显示一行时,可以将文字显示为跑马灯效果,即文字滚动显示. 代码实现 第一种方法实现 先查询TextView控件的属性,得到以下信息 ...
- TextView的跑马灯效果(AS开发实战第二章学习笔记)
TextView的跑马灯效果 跑马灯用到的属性与方法说明 singleLine 指定文本是否单行显示 ellipsize 指定文本超出范围后的省略方式 focusable 指定是否获得焦点,跑马灯效果 ...
- Android文字实现跑马灯效果——两种方法实现
第一种方法,设置textView的属性 <com.example.glide.MarqueeViewandroid:id="@+id/marqueeView"android: ...
- Android开发 实现跑马灯效果滚动字幕
Android开发 实现跑马灯效果滚动字幕 ~! ~ !~ 浙江温州!~ 浙江温州!~江南皮革厂倒闭了! 黄鹤老板欠下了3.5个亿 ! 带着他的小姨子跑了! 我们没有办法 没有办法,拿着钱包抵工资, ...
- android:ellipsize实现跑马灯效果总结
原文地址:http://www.cnblogs.com/Gaojiecai/archive/2013/06/18/3142783.html android:ellipsize用法如下: 在xml中 a ...
- TextView实现跑马灯效果
经常使用TextView会出现这样的情况,有限的空间内只能写一行,然后导致好多文字被"..."表示了,如图: 而且有可能是重要信息被隐藏了,于是就有了跑马灯效果. 实现方式很简单: ...
- Android studio | From Zero To One ——TextView实现跑马灯效果及聊天室、文字直播间
================================================ 博主github:https://github.com/MichaelBeechan 博主CSDN:h ...
最新文章
- 按esc键退出的一个函数
- jstree如何禁止平级拖拽?_小程序为鲜花店经营带来哪些价值?如何搭建一款鲜花小程序?...
- 《卓有成效的程序员》----读书笔记一
- 经典面试题:将有序数组、有序链表转换成平衡二叉树
- OS X EI Captain 下解决 There was a problem confirming the ssl certificate 问题
- sql server行列转化和行列置换
- WIN7安装VS2008的 Error1935 问题解决方案
- 成为Googler的资源分享!
- 计算机比赛训练总结500字,比赛活动总结500字(精选7篇)
- Fifth season last two episodes,Vegas is an amazing place!!!Ross and Rachel got married???
- smb.php如何使用,win10smb1协议怎么开
- 【操作系统】操作系统的功能管理与分类
- 【线段树】【P5522】[yLOI2019] 棠梨煎雪
- k3 审核流程图_K3单据使用解释及流程图明细
- 集群策略--集群(clustering)
- linux中fflush函数和printf函数 【转】
- 数美科技风控前沿| AIGC需要什么内容风控基建?ChatGPT本“人”有话要说
- PIC16F887 单片机 电压检测
- Cas5.3.14手机号码登录(五)
- 小学有计算机课程吗,小学计算机是不是就是信息技术啊