สวัสดีครับกลับมาเจอกันอีกครั้งหลังจากห่างหายการเขียนบทความ Android ไปเสียนาน ก่อนหน้านี้เมื่อหลายเดือนก่อนผมอยากจะทำให้ตัวเลขใน TextView ให้มันวิ่งๆมาถึงค่าที่เราต้องการ แต่หาจนแล้วจนรอดก็ไม่เจอกันที ผ่านไปหลายเดือนในที่สุดผมก็เจอวิธีทำ นั่นก็คือ ValueAnimator นั่นเองงงง!!
ValueAnimator เป็นญาติพี่น้องกับ Property Animation ตัวอื่นๆของ Android แต่มันไม่ได้ทำ Animation ตรงๆ การทำงานของมันคือการเพิ่มค่าจากจุดๆนึงไปยังอีกจุดนึง เช่น เพิ่มจาก 0 เป็น 1000 ซึ่งเหมาะมากกับการเอาไปทำตัวเลขวิ่งๆ เพื่อความสวยงาม เรามาลองกันเลยดีกว่า
ก่อนอื่นก็สร้าง Layout xml ขึ้นมาก่อน ผมใส่เป็น TextView 1 อันแล้วประกาศ Id ให่มันด้วยนะครับ อย่าลืม ใส่ Id ของ layout ด้านนอกด้วยนะ เอาไว้กันตอนหลัง
[xml] <?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>
[/xml]
วิธีใช้งาน ValueAnimator ก็เหมือน Class ทั่วไปคือประกาศตัวแปรขึ้นมาก่อนแบบนี้
[java]
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1000);
[/java]
ตรง ValueAnimator.ofInt(start, end) การกำหนดให้มันเริ่มทำงานที่ค่าเท่าไหร่แล้วบวกเพิ่มไปจนถึงค่าเท่าไหร่ สามารถใส้ได้ทั้ง Int, Float, ARGB(ค่าสีต่างๆ) ผมให้มันเริ่มที่ 0 แล้วเพิ่มไปจนถึง 1000
จากนั้นก็เป็นส่วนของการกำหนดเวลา แบบนี้
[java]
valueAnimator.setDuration(5000);
[/java]
ตรงนี้จะใส่เวลาเป็น millisecond โดย 1000 เท่ากับ 1 วินาที
นอกจากนี้เรายังสามารถกำหนดรูปแบบของการเพิ่มขึ้นของค่าด้วย Interpolator ได้อีกด้วย
[java]
valueAnimator.setInterpolator(new LinearInterpolator());
[/java]
แล้วก็มาถึงขั้นตอนสำคัญ การเพิ่ม Listener เพื่อให้รู้ว่าค่าเปลี่ยนไป เราจะได้นำค่าไปใส่ใน TextView ได้
[java]
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (Integer) animation.getAnimatedValue();
textView.setText("X is " + value);
}
});
[/java]
จะเห็นว่าเราแปลง AnimatedValue ออกมาเป็น int แล้วค่อยเอาไปใส่ใน Textview เหมือนปกติ (ง่ายเนอะ)
ข้อสำคัญ!!! อย่าลืม Start มันด้วย เดี๋ยวจะไม่ทำงาน
[java]
valueAnimator.start();
[/java]
เราจะได้ Code ออกมารูปร่างหน้าตาประมาณนี้
[java]
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();
[/java]
ลอง Run ดูเลยครับ เราจะเห็น Textview เขียนว่า X is 0 แล้ววิ่งไปจนถึง X is 1000
ป่ะ เรามาเล่นกันต่อ อย่างที่บอกว่ามันรับ Parameter เป็นค่าสีได้ ดังนั้นมันจึงเปลี่ยนสีของ View ได้เหมือนกัน เรามาเปลี่ยนสีของ Background กัน ก่อนอื่นก็สร้างตัวแปร colorFrom กับ colorTo ก่อนเพื่อบอกสีตั้งต้นและสีที่อยากจะเปลี่ยนไป
[java]
Integer colorFrom = Color.TRANSPARENT;
Drawable background = layoutBg.getBackground();
if (background instanceof ColorDrawable){
colorFrom = ((ColorDrawable) background).getColor();
}
Integer colorTo = Color.RED;
[/java]
จากนั้นก็ประกาศตัวแปร ValueAnimator สำหรับรับค่าสี
[java]
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
[/java]
การกำหนดเวลาทำเหมือนเดิม แต่ตรงส่วน Listener อาจจะแตกต่างไปนิดหน่อย แบบนี้
[java]
colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
layoutBg.setBackgroundColor((Integer) animator.getAnimatedValue());
}
});
colorAnimation.start();
[/java]
เมื่อเรารับค่า Integer มาก็นำไปใส่เป็น BackgroundColor ของ View แล้วอย่าลืม Start
เป็นไงครับ ValueAnimator ใช้ง่ายมากๆ เพื่อนลองเอาไปเล่นกันดูได้ ทำเสร็จแล้วอย่าลิมเอามาอวดกันบ้างนะครับ อยากเห็น Animation สวยๆ ด้านล่างเป็น Code ทั้งหมดครับ มีแถบส่วนเปลี่ยนสีของ TextView ด้วย
[java]
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();
}
}
[/java]
ขอขอบคุณตัวอย่างต่างๆและข้อมูลอ้างอิงจากเว็บเหล่านี้
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