天天看點

關于TextView設定Marquee不滾動問題

1、固定高度導緻的

已設定

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

但是不生效。。。

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()) {
        }
    }
           

這裡判斷主要條件有三個:

isFocused() || isSelected():焦點選中或者設定selected=true

getLineCount() == 1:singleLine=“true”

canMarquee()

斷點發現canMarquee傳回false。

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

斷點發現mRight和mLeft為0,其指派發生在調用判斷之後。。。是以這裡傳回了false。

我斷點去看了其他可以正常滾動的TextView。發現了問題:

在makeNewLayout中有一段代碼:

if (height != LayoutParams.WRAP_CONTENT && height != LayoutParams.MATCH_PARENT) {
  startMarquee();
} else {
    // Defer the start of the marquee until we know our width (see setFrame())
    mRestartMarquee = true;
}
           

正常的view走了下面,這個标記mRestartMarquee置為true,然後後面會多次調用restartMarqueeIfNeeded

private void restartMarqueeIfNeeded() {
        if (mRestartMarquee && mEllipsize == TextUtils.TruncateAt.MARQUEE) {
            mRestartMarquee = false;
            startMarquee();
        }
    }
           

而出問題的view因為在makeNewLayout中走了if分支,結果又還沒layout給mRight和mLeft指派,導緻startMarquee沒成功,标志位又是false,導緻後面也不會嘗試重新startMarquee。

改進方法:高度設為wrap_content

2、RecyclerView中item中的textview沒滾動

如上述:

if ((mMarquee == null || mMarquee.isStopped()) && (isFocused() || isSelected())
                && getLineCount() == 1 && canMarquee()) {
        }
           

這個判斷中 (isFocused() || isSelected())傳回了false,因為我設定的是itemview根布局可以擷取焦點,而内部的textview沒擷取焦點。

改進方法:

itemView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                v.findViewById(R.id.tv_name).setSelected(hasFocus);
            }
        });