[Android Code] ทำตัวเลขวิ่งๆด้วย ValueAnimator

0

          สวัสดีครับกลับมาเจอกันอีกครั้งหลังจากห่างหายการเขียนบทความ Android ไปเสียนาน ก่อนหน้านี้เมื่อหลายเดือนก่อนผมอยากจะทำให้ตัวเลขใน TextView ให้มันวิ่งๆมาถึงค่าที่เราต้องการ แต่หาจนแล้วจนรอดก็ไม่เจอกันที ผ่านไปหลายเดือนในที่สุดผมก็เจอวิธีทำ นั่นก็คือ ValueAnimator นั่นเองงงง!!

          ValueAnimator เป็นญาติพี่น้องกับ Property Animation ตัวอื่นๆของ Android แต่มันไม่ได้ทำ Animation ตรงๆ การทำงานของมันคือการเพิ่มค่าจากจุดๆนึงไปยังอีกจุดนึง เช่น เพิ่มจาก 0 เป็น 1000 ซึ่งเหมาะมากกับการเอาไปทำตัวเลขวิ่งๆ เพื่อความสวยงาม เรามาลองกันเลยดีกว่า

ก่อนอื่นก็สร้าง Layout xml ขึ้นมาก่อน ผมใส่เป็น TextView 1 อันแล้วประกาศ Id ให่มันด้วยนะครับ อย่าลืม ใส่ Id ของ layout ด้านนอกด้วยนะ เอาไว้กันตอนหลัง

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layoutBg"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.kamonway.valueanimator.MainActivity">

    <TextView
        android:id="@+id/textCount"
        android:layout_centerInParent="true"
        android:textSize="40sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
</RelativeLayout>

วิธีใช้งาน ValueAnimator ก็เหมือน Class ทั่วไปคือประกาศตัวแปรขึ้นมาก่อนแบบนี้

ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1000);

ตรง ValueAnimator.ofInt(start, end) การกำหนดให้มันเริ่มทำงานที่ค่าเท่าไหร่แล้วบวกเพิ่มไปจนถึงค่าเท่าไหร่ สามารถใส้ได้ทั้ง Int, Float, ARGB(ค่าสีต่างๆ) ผมให้มันเริ่มที่ 0 แล้วเพิ่มไปจนถึง 1000

จากนั้นก็เป็นส่วนของการกำหนดเวลา แบบนี้

valueAnimator.setDuration(5000); 

ตรงนี้จะใส่เวลาเป็น millisecond โดย 1000 เท่ากับ 1 วินาที

นอกจากนี้เรายังสามารถกำหนดรูปแบบของการเพิ่มขึ้นของค่าด้วย Interpolator ได้อีกด้วย

valueAnimator.setInterpolator(new LinearInterpolator());

แล้วก็มาถึงขั้นตอนสำคัญ การเพิ่ม Listener เพื่อให้รู้ว่าค่าเปลี่ยนไป เราจะได้นำค่าไปใส่ใน TextView ได้

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (Integer) animation.getAnimatedValue();
                textView.setText("X is " + value);
            }
        });

จะเห็นว่าเราแปลง AnimatedValue ออกมาเป็น int แล้วค่อยเอาไปใส่ใน Textview เหมือนปกติ (ง่ายเนอะ)

ข้อสำคัญ!!! อย่าลืม Start มันด้วย เดี๋ยวจะไม่ทำงาน

valueAnimator.start();

เราจะได้ Code ออกมารูปร่างหน้าตาประมาณนี้

ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1000);
valueAnimator.setDuration(5000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
           int value = (Integer) animation.getAnimatedValue();

           textView.setText("X is " + value);
      }
});
valueAnimator.start();

ลอง Run ดูเลยครับ เราจะเห็น Textview เขียนว่า X is 0 แล้ววิ่งไปจนถึง X is 1000

ตัวเลขกำลังวิ่งเลยตอนนี้

ตัวเลขกำลังวิ่งเลยตอนนี้

          ป่ะ เรามาเล่นกันต่อ อย่างที่บอกว่ามันรับ Parameter เป็นค่าสีได้ ดังนั้นมันจึงเปลี่ยนสีของ View ได้เหมือนกัน เรามาเปลี่ยนสีของ Background กัน ก่อนอื่นก็สร้างตัวแปร colorFrom กับ colorTo ก่อนเพื่อบอกสีตั้งต้นและสีที่อยากจะเปลี่ยนไป

Integer colorFrom = Color.TRANSPARENT;
        Drawable background = layoutBg.getBackground();
        if (background instanceof ColorDrawable){
            colorFrom = ((ColorDrawable) background).getColor();
        }
Integer colorTo = Color.RED;

จากนั้นก็ประกาศตัวแปร ValueAnimator สำหรับรับค่าสี

ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);

การกำหนดเวลาทำเหมือนเดิม แต่ตรงส่วน Listener อาจจะแตกต่างไปนิดหน่อย แบบนี้

colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animator) {
                layoutBg.setBackgroundColor((Integer) animator.getAnimatedValue());
            }

        });
colorAnimation.start();

เมื่อเรารับค่า Integer มาก็นำไปใส่เป็น BackgroundColor ของ View แล้วอย่าลืม Start

สี Background จะค่อยๆเปลี่ยนไปเป็นสีแดง

สี Background จะค่อยๆเปลี่ยนไปเป็นสีแดง

          เป็นไงครับ ValueAnimator ใช้ง่ายมากๆ เพื่อนลองเอาไปเล่นกันดูได้ ทำเสร็จแล้วอย่าลิมเอามาอวดกันบ้างนะครับ อยากเห็น Animation สวยๆ ด้านล่างเป็น Code ทั้งหมดครับ มีแถบส่วนเปลี่ยนสีของ TextView ด้วย

public class MainActivity extends AppCompatActivity {
    TextView textView;
    RelativeLayout layoutBg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textCount);
        layoutBg = (RelativeLayout) findViewById(R.id.layoutBg);

        animateNumber(0, 1000);
        animateColorBg(Color.RED);
        //animateColorText(Color.WHITE);
    }

    private void animateNumber(int start, int end){
        ValueAnimator valueAnimator = ValueAnimator.ofInt(start, end);
        valueAnimator.setDuration(5000);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (Integer) animation.getAnimatedValue();

                textView.setText("X is " + value);
            }
        });
        valueAnimator.start();
    }

    private void animateColorBg(Integer colorTo){
        Integer colorFrom = Color.TRANSPARENT;
        Drawable background = layoutBg.getBackground();
        if (background instanceof ColorDrawable){
            colorFrom = ((ColorDrawable) background).getColor();
        }

        ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
        colorAnimation.setDuration(5000);
        colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animator) {
                layoutBg.setBackgroundColor((Integer) animator.getAnimatedValue());
            }

        });
        colorAnimation.start();
    }

    private void animateColorText(Integer colorTo){
        Integer colorFrom = Color.TRANSPARENT;
        colorFrom = textView.getCurrentTextColor();

        ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
        colorAnimation.setDuration(5000);
        colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animator) {
                textView.setTextColor((Integer) animator.getAnimatedValue());
            }

        });
        colorAnimation.start();
    }
}
เปลี่ยนทั้งพื้นหลัง สีตัวอักษร และตัวเลข

เปลี่ยนทั้งพื้นหลัง สีตัวอักษร และตัวเลข

ขอขอบคุณตัวอย่างต่างๆและข้อมูลอ้างอิงจากเว็บเหล่านี้
http://stackoverflow.com/questions/11935216/animation-of-height-of-linearlayout-container-with-valueanimator
http://www.programcreek.com/java-api-examples/index.php?api=android.animation.ValueAnimator
https://developer.android.com/reference/android/view/animation/Interpolator.html

Facebook Comments
Share.

About Author

Comments are closed.