如何优雅的在Android上实现文字不超过一行跑马灯效果

前言

跑马灯效果应用非常广泛,项目经常用到。一般的使用方法,大家已经都知道了。只不过,我今天要说明的是,在文字没有超过一行的情况下,如何让文字有跑马灯效果。

一般实现

一般的实现主要有以下结果步骤:

  • 在XML文件中设置属性
    <style name="MarqueeTextView">
        "android:singleLine">true
        "android:ellipsize">marquee
        "android:marqueeRepeatLimit">marquee_forever
    style>

文字要单行显示;隐藏类型为文字滚动,即跑马灯;文字滚动重复次数,永久滚动;
有这三个条件,文字超过单行后,会出现滚动显示效果。

那么问题来了,我需要在文字没有超过单行的时候,也需要文字滚动,那怎么办?

文字不足一行

在TextView.java文件中,有如下代码,表示启动跑马灯效果。

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

这里面,可以看到,如果要文字滚动必须文字的宽度大于布局宽度。
所以这里我们的修改思路有2个:

  1. 重写方法,让判断生效,布局宽度永远小于文字宽度。
  2. 让文字宽度永远大于布局宽度。

目前我的方案里面是2。就是在设置文字时,在末尾添加多个空格字符。

public class MarqueeTextView extends AppCompatTextView {

    private String empty_char = "                                                     ";
    public MarqueeTextView(Context context) {
        this(context, null);
    }

    public MarqueeTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean isSelected() {
        return true;
    }

    @Override
    public boolean isFocused() {
        return true;
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(text + empty_char, type);
    }
}

这样控件就可以在文字不足超过一行的时候进行滚动了!

你可能感兴趣的:(java,android,textview)