Android and a TextView's horizontal marquee sc

2019-03-16 12:29发布

I have a text view with following XML attributes:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="14dip"
    android:maxLines="1"
    android:scrollHorizontally="true"
    android:ellipsize="marquee"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:marqueeRepeatLimit="1"
    android:textColor="@android:color/black"
    android:id="@+id/ticker"
    />

I'd like to be able to set the horizontal scroll rate, making it slightly faster than the default. How do I do with this (in XML)?

Thanking you in advance.

4条回答
别忘想泡老子
2楼-- · 2019-03-16 13:01

This is my first answer on SO, so I don't have reputation so I can't comment on Mike's answer, but I modified it a little bit to make it work with Android L.

Besides that, if f.get(tv) returns null, try calling mTextView.setSelected(true) before calling setMarqueeSpeed(). This worked for me.

protected 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楼-- · 2019-03-16 13:09

I don't think there's an attribute that you can set in XML for that purpose.

It might be a bit overkill for you, but check out this customized extended marquee for Android, all settings can be customized in the coding part, you need to play with setDuration of the animation to achieve the speed you want.

查看更多
4楼-- · 2019-03-16 13:09

Just an addition to Mike's answer. Because it returns NoSuchFieldException when working with AppCompatActivity:

Field f;     
if (tv instanceof AppCompatTextView) {
    f = tv.getClass().getSuperclass().getDeclaredField("mMarquee");
} else {
    f = tv.getClass().getDeclaredField("mMarquee");
}
查看更多
叛逆
5楼-- · 2019-03-16 13:14

Here's how I did it, it's dirty but it gets the job done, until they wake-up and make it configurable!

Could you believe there's a "// TODO Add an option to configure this" in the Marquee private static inner class!

    protected 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) {
            Field mf = marquee.getClass().getDeclaredField("mScrollUnit");
            mf.setAccessible(true);
            float newSpeed = speed;
            if (speedIsMultiplier) {
                newSpeed = mf.getFloat(marquee) * speed;
            }
            mf.setFloat(marquee, newSpeed);
            Log.i(this.getClass().getSimpleName(), String.format("%s marquee speed set to %f", tv, newSpeed));
        }
    } catch (Exception e) {
        // ignore, not implemented in current API level
    }
}
查看更多
登录 后发表回答