TextView跑马灯的几点问题:持续动画 和 与EditText争抢焦点的问题

TextView跑马灯的几点问题:

(一)网络上提供的解决办法以及对应的问题

一、TextView的跑马灯效果:
  1. TextView添加属性

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

    问题:在其他控件获取焦点后,跑马灯动画会停止

二、自定义控件MarqueeTextView,改造TextView跑马灯效果

  1. 改造TextView,重写部分方法

    网络上提供的方法:
    1、一般是自定义控件MarqueeTextView,继承TextView
    2、重写isFocused方法
    3、部分博客上还要求重写onFocusChanged 和onWindowFocusChanged 方法
    
  2. 代码:

    public class MarqueeTextView extends TextView
    {
        public MarqueeTextView(Context context, AttributeSet attrs, int defStyle)
        {
            super(context, attrs, defStyle);
        }
    
        public MarqueeTextView(Context context, AttributeSet attrs)
        {
            super(context, attrs);
        }
    
        public MarqueeTextView(Context context)
        {
            super(context);
        }
    
        @Override
        protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect)
        {
            if (focused)super.onFocusChanged(focused, direction, previouslyFocusedRect);
        }
    
        @Override
        public void onWindowFocusChanged(boolean focused)
        {
            if (focused)super.onWindowFocusChanged(focused);
        }
    
        @Override
        public boolean isFocused()
        {
            return true;
        }
    }
    

    问题:跑马灯动画会一直运行,但遇到页面有EditText的时候,会和EditText争抢焦点,导致EditText不能弹出键盘,即使手动调用键盘,也不能正常输入。(这个还是很坑的)

三、自定义控件MarqueeTextView,手写跑马灯效果

  1. 开源的项目,是针对上面几种情况,手写的跑马灯效果

    1. https://github.com/sfsheng0322/MarqueeView
    2. https://github.com/gongwen/MarqueeViewLibrary
    3. https://github.com/oubowu/MarqueeLayoutLibrary

    可自定义各种效果,跑动时长,控制动画开停,跑动方向,翻转方向等特性

  2. 自己手写

    略(哈哈哈)
    

    问题:部分库需要手动开启跑马灯动画,不能根据长度区分是否需要跑马灯。和原生的效果不一样。

(二)我自己的摸索

  1. 需求

    1. 只需要长度不能完全显示的文字有跑马灯动画,长度可以显示的不需要动画
    2. 动画效果和原生的一样就可以:一起启动,一起暂停,原生的速度刚刚好
  2. 研究源码,自定义实现原生的跑马灯效果

    研究源码,根据源码的跑马灯原理:判断长度是否可以全部显示,判断什么时候开始动画,什么时候结束动画,然后发现了一个方法,很有灵感的代码:

    private void startMarquee() {
        // Do not ellipsize EditText
        if (getKeyListener() != null) return;
    
        if (compressText(getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight())) {
            return;
        }
    
        if ((mMarquee == null || mMarquee.isStopped()) && (isFocused() || isSelected())
                && getLineCount() == 1 && 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);
        }
    }
    

    重点:isFocused() || isSelected(),在开始跑马灯的时候,做的判断之一就是这个,之前我们重写的时候,会重写isFocused,但焦点很重要,TextView一直持有焦点会造成之前提到的问题,那我们换个思路,重写isSelected,让TextView一直是被选中的,不就可以了吗?!

  3. 经过测试,上述想法可行,于是乎,跑马灯持续动画+与EditText争抢焦点的问题就一次性解决了

解决办法

  1. 改造TextView,重写部分方法

    1、自定义控件MarqueeTextView,继承TextView
    2、重写isSelected方法
    
  2. 布局文件中,MarqueeTextView添加属性

    android:ellipsize="marquee"
    android:marqueeRepeatLimit="marquee_forever"
    android:singleLine="true"
    
  3. 具体代码:

    布局文件:使用自定义控件,添加属性
    <com.xxxx.xxxx.ui.widget.MarqueeTextView
        android:id="@+id/user_name"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"
        android:text="超长的文字测试1超长的文字测试2超长的文字测试3超长的文字测试4超长的文字测试5超长的文字测试6超长的文字测试7超长的文字测试8"
    /> 
    
    
    自定义控件:   
    @SuppressLint("AppCompatCustomView")
    public class MarqueeTextView extends TextView{
    
        public MarqueeTextView(Context context) {
            super(context);
        }
    
        public MarqueeTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MarqueeTextView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        public boolean isSelected()
        {
            return true;
        }
    }
    

    遗留问题:点击EditText弹出键盘和收回键盘,或点击返回按键的时候,跑马灯会回到初始位置,重新开始

后记:其实这个解决办法,改动很小,但探索过程比较长,特记录下来。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值