侯爵设置速度



我正在使用一个字幕来显示我的一个活动中的文本。我的问题是,是否可以加快字幕的速度,使其在屏幕上滚动得更快。下面是我的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" />

您必须创建一个自定义类来滚动文本:

滚动文本视图.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's 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's 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

如果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();
        }
    }
}

这对我有效。如果f.get(tv)返回null,请在调用setMarqueSpeed()之前尝试调用mTextView.setSelected(true)。最初的答案:Android和一个TextView';s水平字幕滚动速率

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

我在运行Android 7.1的设备上解决了以上滚动问题,从这里和其他地方的多篇文章中提取

  1. 解决了速度问题
  2. 仅在需要时滚动/文本长于TextView的宽度
  3. 适用于扩展TextView或AppCompatTextView

package com.myclass.classes;
import android.content.Context;
import android.graphics.Rect;
import android.text.Layout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.LinearInterpolator;
import android.widget.Scroller;
import android.widget.TextView;
public class ScrollTextView extends TextView {
// scrolling feature
private Scroller mSlr;
// the X offset when paused
private int mXPaused = 0;
// whether it's being paused
private boolean mPaused = true;
private float mScrollSpeed = 250f; //Added speed for same scrolling speed regardless of text
/*
 * constructor
 */
public ScrollTextView(Context context) {
    this(context, null);
    // customize the TextView
    setSingleLine();
    setEllipsize(null);
    setVisibility(VISIBLE);
    getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener); //added listener check
}
/*
 * constructor
 */
public ScrollTextView(Context context, AttributeSet attrs) {
    this(context, attrs, android.R.attr.textViewStyle);
    // customize the TextView
    setSingleLine();
    setEllipsize(null);
    setVisibility(VISIBLE);
    getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener); //added listener check
}
/*
 * constructor
 */
public ScrollTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // customize the TextView
    setSingleLine();
    setEllipsize(null);
    setVisibility(VISIBLE);
    getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener); //added listener check
}

@Override
protected void onDetachedFromWindow() {
    removeGlobalListener();
    super.onDetachedFromWindow();
}
/**
 * begin to scroll the text from the original position
 */
private void startScroll() {
    boolean needsScrolling = checkIfNeedsScrolling();
    // begin from the middle
    mXPaused = -1 * (getWidth() / 2);
    // assume it's paused
    mPaused = true;
    if (needsScrolling) {
        
        resumeScroll();
    } else {
        pauseScroll();
    }
    removeGlobalListener();
}
/**
 * Removing global listener
 **/
private synchronized void removeGlobalListener() {
    try {
        if (onGlobalLayoutListener != null)
            getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
        onGlobalLayoutListener = null;
    } catch (Exception e) {
        e.printStackTrace();
    }
}
/**
 * Waiting for layout to initiate
 */
private OnGlobalLayoutListener onGlobalLayoutListener = () -> {
    startScroll();
};
/**
 * Checking if we need scrolling
 */
private boolean checkIfNeedsScrolling() {
    measure(0, 0);
    int textViewWidth = getWidth();
    if (textViewWidth == 0)
        return false;
    float textWidth = getTextLength();
    return textWidth > textViewWidth;
}
/**
 * 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 = (int) (1000f * distance / mScrollSpeed);
    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() {
    int length = getTextLength();
    return length + getWidth();
}
private int getTextLength() {
    TextPaint tp = getPaint();
    Rect rect = new Rect();
    String strTxt = getText().toString();
    tp.getTextBounds(strTxt, 0, strTxt.length(), rect);
    int length = rect.width();
    rect = null;
    return length;
}
/**
 * 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 boolean isPaused() {
    return mPaused;
}
}

借助已接受的答案&有些更改,您现在甚至可以在运行时使用此库设置Speed()。

https://github.com/RohanPatil1/SpeedMarquee

使用XML

<com.rohan.speed_marquee.SpeedMarquee
        android:id="@+id/marqueeTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/dummy_text"
        android:maxLines="1"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:marquee_speed="180.0" />

使用方法

 findViewById<Button>(R.id.speedButton).setOnClickListener {
            //Increment Text3's speed by 100.0
            marqueeTextView3.setSpeed(marqueeTextView3.getSpeed() + 100.0f)
        }
    }

最新更新