Скорость выделения шатра

Я использую область выделения, чтобы показать текст в одной из моих Деяний. Мой вопрос заключается в том, что можно ускорить скорость выделения, чтобы он быстрее прокручивался по экрану. Ниже приведены мои XML и Java.

TextView et2 = (TextView) findViewById(R.id.noneednum);
    et2.setEllipsize(TruncateAt.MARQUEE);    
    et2.setText("");
    if (num.size() > 0) {
        for (String str : num) {
            et2.append(str + "    ");
        }
    }
    et2.setSelected(true);
}

И XML:

<TextView
    android:id="@+id/noneednum"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:ellipsize="marquee"
    android:fadingEdge="horizontal"
    android:gravity="center_vertical|center_horizontal"
    android:lines="1"
    android:marqueeRepeatLimit="marquee_forever"
    android:scrollHorizontally="true"
    android:singleLine="true"
    android:text="Large Text"
    android:textColor="#fff"
    android:textSize="140dp" />

Ответ 1

Вам нужно создать собственный класс для прокрутки текста:

ScrollTextView.java

public class ScrollTextView extends TextView {

     // scrolling feature
     private Scroller mSlr;

     // milliseconds for a round of scrolling
     private int mRndDuration = 10000;

     // the X offset when paused
     private int mXPaused = 0;

     // whether it being paused
     private boolean mPaused = true;

     /*
     * constructor
     */
     public ScrollTextView(Context context) {
         this(context, null);
         // customize the TextView
         setSingleLine();
         setEllipsize(null);
         setVisibility(INVISIBLE);
     }

     /*
     * constructor
     */
     public ScrollTextView(Context context, AttributeSet attrs) {
         this(context, attrs, android.R.attr.textViewStyle);
         // customize the TextView
         setSingleLine();
         setEllipsize(null);
         setVisibility(INVISIBLE);
     }

     /*
     * constructor
     */
     public ScrollTextView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         // customize the TextView
         setSingleLine();
         setEllipsize(null);
         setVisibility(INVISIBLE);
     }

     /**
     * begin to scroll the text from the original position
     */
     public void startScroll() {
         // begin from the very right side
         mXPaused = -1 * getWidth();
         // assume it paused
         mPaused = true;
         resumeScroll();
     }

     /**
     * resume the scroll from the pausing point
     */
     public void resumeScroll() {

         if (!mPaused) return;

         // Do not know why it would not scroll sometimes
         // if setHorizontallyScrolling is called in constructor.
         setHorizontallyScrolling(true);

         // use LinearInterpolator for steady scrolling
         mSlr = new Scroller(this.getContext(), new LinearInterpolator());
         setScroller(mSlr);

         int scrollingLen = calculateScrollingLen();
         int distance = scrollingLen - (getWidth() + mXPaused);
         int duration = (new Double(mRndDuration * distance * 1.00000
         / scrollingLen)).intValue();

         setVisibility(VISIBLE);
         mSlr.startScroll(mXPaused, 0, distance, 0, duration);
         invalidate();
         mPaused = false;
     }

     /**
     * calculate the scrolling length of the text in pixel
     *
     * @return the scrolling length in pixels
     */
     private int calculateScrollingLen() {
         TextPaint tp = getPaint();
         Rect rect = new Rect();
         String strTxt = getText().toString();
         tp.getTextBounds(strTxt, 0, strTxt.length(), rect);
         int scrollingLen = rect.width() + getWidth();
         rect = null;
         return scrollingLen;
     }

     /**
     * pause scrolling the text
     */
     public void pauseScroll() {
         if (null == mSlr) return;

         if (mPaused)
         return;

         mPaused = true;

         // abortAnimation sets the current X to be the final X,
         // and sets isFinished to be true
         // so current position shall be saved
         mXPaused = mSlr.getCurrX();

         mSlr.abortAnimation();
     }

     @Override
     /*
     * override the computeScroll to restart scrolling when finished so as that
     * the text is scrolled forever
     */
     public void computeScroll() {
         super.computeScroll();

         if (null == mSlr) return;

         if (mSlr.isFinished() && (!mPaused)) {
           this.startScroll();
         }
     }

     public int getRndDuration() {
       return mRndDuration;
     }

     public void setRndDuration(int duration) {
       this.mRndDuration = duration;
     }

     public boolean isPaused() {
       return mPaused;
     }
}

В вашем макете пишите вот так:

<yourpackagename.ScrollTextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/scrolltext" />

В вашей деятельности напишите вот так:

ScrollTextView scrolltext=(ScrollTextView) findViewById(R.id.scrolltext);
scrolltext.setText(yourscrollingtext);
scrolltext.setTextColor(Color.BLACK);
scrolltext.startScroll();

Если вы хотите увеличить скорость прокрутки, уменьшите значение:

private int mRndDuration = 10000;//reduce the value of mRndDuration to increase scrolling speed

Ответ 2

Это работает для меня. Если f.get(tv) возвращает значение null, попробуйте вызвать mTextView.setSelected(true) перед вызовом setMarqueeSpeed ​​(). Оригинальный ответ: Android и скорость прокрутки горизонтального выделения TextView

private void setMarqueeSpeed(TextView tv, float speed, boolean speedIsMultiplier) {

    try {
        Field f = tv.getClass().getDeclaredField("mMarquee");
        f.setAccessible(true);

        Object marquee = f.get(tv);
        if (marquee != null) {

            String scrollSpeedFieldName = "mScrollUnit";
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.L)
                scrollSpeedFieldName = "mPixelsPerSecond";

            Field mf = marquee.getClass().getDeclaredField(scrollSpeedFieldName);
            mf.setAccessible(true);

            float newSpeed = speed;
            if (speedIsMultiplier)
                newSpeed = mf.getFloat(marquee) * speed;

            mf.setFloat(marquee, newSpeed);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Ответ 3

Сбой кода выше, если TextView является экземпляром AppCompatTextView. Ниже работает код - это AppCompatTextView. Протестировано в Зефир.

public static void setMarqueeSpeed(TextView tv, float speed) {
    if (tv != null) {
        try {
            Field f = null;
            if (tv instanceof AppCompatTextView) {
                f = tv.getClass().getSuperclass().getDeclaredField("mMarquee");
            } else {
                f = tv.getClass().getDeclaredField("mMarquee");
            }
            if (f != null) {
                f.setAccessible(true);
                Object marquee = f.get(tv);
                if (marquee != null) {
                    String scrollSpeedFieldName = "mScrollUnit";
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        scrollSpeedFieldName = "mPixelsPerSecond";
                    }
                    Field mf = marquee.getClass().getDeclaredField(scrollSpeedFieldName);
                    mf.setAccessible(true);
                    mf.setFloat(marquee, speed);
                }
            } else {
                Logger.e("Marquee", "mMarquee object is null.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}