Android TextView:有没有办法用短文强制选框动画?

问题描述 投票:6回答:6

我有一个带有一些文本的TextView,我想让它用滚动的选框动画制作动画。我看到这个popular question关于强制选框动画,但是答案中的代码只有在文本足够长以超出TextView的边界(因此文本被截断)时才起作用,我正在寻找永久制作的解决方案无论文本的宽度如何,文本都有这个选取框动画;这可能吗?

android animation textview marquee
6个回答
16
投票

制作自己的动画。

anim / marquee.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="100%"
        android:toXDelta="-100%"
        android:duration="10000"
        android:repeatCount="infinite"
        android:repeatMode="restart"
        android:interpolator="@android:anim/linear_interpolator"/>
</set>

在你的活动中,

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.my_activity);

    TextView myTextView = (TextView) findViewById(R.id.myTextView);
    Animation marquee = AnimationUtils.loadAnimation(this, R.anim.marquee);
    myTextView.startAnimation(marquee);
}

3
投票

考虑到@ JodiMiddleton关于填充文本的建议,我构建了一些辅助方法,根据TextPaint对象将文本填充到目标宽度(确保在测量时正确调整字体等大小):

/**
 * Pad a target string of text with spaces on the right to fill a target
 * width
 * 
 * @param text The target text
 * @param paint The TextPaint used to measure the target text and
 *            whitespaces
 * @param width The target width to fill
 * @return the original text with extra padding to fill the width
 */
public static CharSequence padText(CharSequence text, TextPaint paint, int width) {

    // First measure the width of the text itself
    Rect textbounds = new Rect();
    paint.getTextBounds(text.toString(), 0, text.length(), textbounds);

    /**
     * check to see if it does indeed need padding to reach the target width
     */
    if (textbounds.width() > width) {
        return text;
    }

    /*
     * Measure the text of the space character (there's a bug with the
     * 'getTextBounds() method of Paint that trims the white space, thus
     * making it impossible to measure the width of a space without
     * surrounding it in arbitrary characters)
     */
    String workaroundString = "a a";
    Rect spacebounds = new Rect();
    paint.getTextBounds(workaroundString, 0, workaroundString.length(), spacebounds);

    Rect abounds = new Rect();
    paint.getTextBounds(new char[] {
        'a'
    }, 0, 1, abounds);

    float spaceWidth = spacebounds.width() - (abounds.width() * 2);

    /*
     * measure the amount of spaces needed based on the target width to fill
     * (using Math.ceil to ensure the maximum whole number of spaces)
     */
    int amountOfSpacesNeeded = (int)Math.ceil((width - textbounds.width()) / spaceWidth);

    // pad with spaces til the width is less than the text width
    return amountOfSpacesNeeded > 0 ? padRight(text.toString(), text.toString().length()
            + amountOfSpacesNeeded) : text;
}

/**
 * Pads a string with white space on the right of the original string
 * 
 * @param s The target string
 * @param n The new target length of the string
 * @return The target string padded with whitespace on the right to its new
 *         length
 */
public static String padRight(String s, int n) {
    return String.format("%1$-" + n + "s", s);
}

因此,当您使用基于TextView的方法时,您会调用:

textView.setText(padText(myTargetString, textView.getPaint(), textView.getWidth()));

它不优雅,我几乎可以肯定有可以做出的改进(更不用说更好的方法了)但是我在我的代码中使用它并且似乎正在做诀窍:)


1
投票

它听起来很脏,但阻力最小的路径可能是用空格填充文本以允许滚动。

如果需要,您可以在Click上删除它们。


0
投票

用于短文本的选框动画

public class MarqueeLayout extends FrameLayout {

    private Animation animation;

    public MarqueeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        animation = new TranslateAnimation(
                Animation.RELATIVE_TO_SELF, +1f,
                Animation.RELATIVE_TO_SELF, -1f,
                Animation.RELATIVE_TO_SELF, 0f,
                Animation.RELATIVE_TO_SELF, 0f
        );

        animation.setRepeatCount(Animation.INFINITE);
        animation.setRepeatMode(Animation.RESTART);
    }

    public void setDuration(int durationMillis) {
        animation.setDuration(durationMillis);
    }

    public void startAnimation() {
        startAnimation(animation);
    }
}

布局:

        <MarqueeLayout
            android:id="@+id/marquee_layout"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/message_text"
                android:singleLine="true"
                android:textColor="@color/marquee_color"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

        </MarqueeLayout>

活动:

MarqueeLayout marqueeLayout = (MarqueeLayout) view.findViewById(R.id.marquee_layout);
marqueeLayout.setDuration(15000);
marqueeLayout.startAnimation();

0
投票

我找到了一个可以解决问题的单行代码!

只需重复短文几次,或用很长的空格分开。

activity_main.xml中

<TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ellipsize="marquee"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:marqueeRepeatLimit="marquee_forever"
        android:scrollHorizontally="true"
        android:singleLine="true"
        android:text=""
        android:textColor="#ffffff"/>

main activity.Java

String shortText = "A short text.";
TextView textView = findViewById(R.id.textView);
textView.setText(shortText + "             " + shortText); 
// repeat the above concatenation as many as required 
// just enough to make it marqueeable for auto scrolling 
// or you can just increase the length of the blank space
textView.setSelected(true);

0
投票

要通过屏幕的文本轨道的效果:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">

<translate
    android:fromXDelta="300%"
    android:toXDelta="-100%"
    android:duration="5000"
    android:repeatCount="infinite"
    android:repeatMode="restart"
    />
</set>
© www.soinside.com 2019 - 2024. All rights reserved.