Continuously animate Text from left to right

后端 未结 3 971
温柔的废话
温柔的废话 2021-02-06 16:14

I\'m trying to create an animation which moves a TextView from left to right and loop indefinitely. This is the TextView I want to animate:

<         


        
相关标签:
3条回答
  • 2021-02-06 16:16

    What you want to do can be easily achieved with a simple ValueAnimator.

    What you first have to do is put two identical versions of the TextView you want to animate into your layout. In this example my layout looks like this:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:id="@+id/first"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:textSize="32sp"
            android:text="@string/hello_word"/>
    
        <TextView
            android:id="@+id/second"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:textSize="32sp"
            android:text="@string/hello_word"/>
    
    </FrameLayout>
    

    Then - as I already mentioned - you use a ValueAnimator to animate the translationX property of both Views, but offset one by the width of the screen (since the TextViews above use match_parent as width their width is equal to the width of the screen and that is what I will be using to offset the position of one of them). Your code should look something like this:

    final TextView first = (TextView) findViewById(R.id.first);
    final TextView second = (TextView) findViewById(R.id.second);
    
    final ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f);
    animator.setRepeatCount(ValueAnimator.INFINITE);
    animator.setInterpolator(new LinearInterpolator());
    animator.setDuration(9000L);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            final float progress = (float) animation.getAnimatedValue();
            final float width = first.getWidth();
            final float translationX = width * progress;
            first.setTranslationX(translationX);
            second.setTranslationX(translationX - width);
        }
    });
    animator.start();
    

    And the result should look something like this:

    0 讨论(0)
  • 2021-02-06 16:26

    if somebody tries to search regarding text marquee on game canvas continuously here is the code to achieve that in your game loop. StartingLine.java is a class that returns a canvas to be drawn on the game surface its functions are being called by gameview loop

    public class StartingLine {
    private int screenWidth;
    private int screenHeight;
    private int xStartPosition;
    private int yStartPosition;
    private int xEndPosition;
    private int yEndPosition;
    private int width = 50;
    private int tv1y = 0;
    private int tv2y = 0;
    private int tv3y = 0;
    private Paint paint;
    
    
    public StartingLine(Context context, int screenX, int screenY, int laneCount) {
        screenWidth = screenX;
        screenHeight = screenY;
        this.xStartPosition = screenWidth - width - (screenHeight / laneCount) * 2;
        this.yStartPosition = 0;
        this.xEndPosition = screenWidth - width - (screenHeight / laneCount) * 2;
        this.yEndPosition = screenHeight;
        paint = new Paint();
    }
    
    public void update(int color) {
        paint.setColor(color);
        paint.setStrokeWidth(2);
        paint.setTextSize(30);
        paint.setTextAlign(Paint.Align.CENTER);
    }
    
    public void draw(Canvas canvas) {
        Rect tb = new Rect();
        paint.getTextBounds("STOP AFTER THIS POINT", 0, "STOP AFTER THIS POINT".length(), tb);
        if (tv1y == 0 && tv2y == 0 && tv3y == 0) {
            tv1y = 0;
            tv2y = tb.width() + width;//tb.width()+width = gap between two texts
            tv3y = 2 * (tb.width() + width);
        } else {
            if (tv3y  >= (3 * (tb.width() + width))) {
                tv3y = 2 * (tb.width() + width);
            }
    
            tv1y = tv3y - 2 * (width + tb.width());
            tv2y = tv1y + width + tb.width();
            tv3y = tv2y + width + tb.width();
        }
    
        canvas.drawLine(xStartPosition, yStartPosition, xEndPosition, yEndPosition, paint);
        canvas.drawLine(xStartPosition + width, yStartPosition, xEndPosition + width, yEndPosition, paint);
        canvas.save();
        canvas.rotate(270, screenWidth / 2, screenHeight / 2);
    
        canvas.drawText("STOP AFTER THIS POINT", tv1y += 5, yEndPosition - 20, paint);
        canvas.drawText("STOP AFTER THIS POINT", tv2y += 5, yEndPosition - 20, paint);
        canvas.drawText("STOP AFTER THIS POINT", tv3y += 5, yEndPosition - 20, paint);
        canvas.restore();
    }
    }
    
    0 讨论(0)
  • 2021-02-06 16:28

    Android has a built-in solution for this called 'marquee'.

    Add these lines to your TextView.

    <TextView
        android:id="@+id/txtTitle"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"
     />
    

    Then simply call

    txtTitle.setText(title);
    txtTitle.setSelected(true);
    

    However, this only works if the text is long enough to go out of bounds.

    0 讨论(0)
提交回复
热议问题