26 กันยายน 2555

[Android Code] สร้างการเคลื่อนไหวง่ายๆ ด้วยคลาส Animation


อันนี้ต่อจากของเก่าที่เคยเกริ่นไปบ้างแล้วกับการทำภาพเคลื่อนไหว
คราวนี้มาดูตัวอย่างการทำภาพเคลื่อนไหวอีกแบบบ้าง
โดยเจ้าของบล็อกจะใช้คลาส Animation มาทำภาพเคลื่อนไหว
ซึ่งต่างจาก Animation List ก็ตรงที่ว่า Animation List
เป็นการนำภาพนิ่งหลายๆภาพมาแสดงเรียงกันจนเป็นภาพเคลื่อนไหว
แต่สำหรับ Animation จะเป็นการนำวัตถุมาทำให้มันเคลื่อนที่แทน
วัตถุที่ว่าจะเป็นอะไรก็ได้เช่น Button, Text View หรือ Image View ก็ได้
(เหล่า Widget ที่อยู่ใน android.widget นั่นแหละ)

โดยการเคลื่อนไหวง่ายๆในบทความนี้จะมีด้วยกันอยู่ 4 แบบ คือ
Fade In, Fade Out, Slide In Left และ Slide Our Right
หลักๆก็มีเท่านี้ จริงๆมีแบบอื่นๆด้วย แต่จะเป็น Interpolator 
ซึ่งเจ้าของบล็อกขอยกยอดไปบทความถัดไปแทนละกันนะ

แหล่งที่มาของภาพโลโก้


สำหรับตัวอย่างนี้เจ้าของบล็อกจะสร้างปุ่มขึ้นมาสามปุ่ม
ปุ่ม Fade In Fade Out, ปุ่ม Slide In Left และปุ่ม Slide Out Right
โดยจะให้ควบคุมการเคลื่อนไหวของ Image View 

Main.java
package app.akexorcist.simpleanimation;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;

public class Main extends Activity {
    ImageView imgLogo;
    Animation anim;
    
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        imgLogo = (ImageView)findViewById(R.id.imgLogo);

        Button btnFade = (Button)findViewById(R.id.btnFade);
        btnFade.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                if(imgLogo.getVisibility() == View.VISIBLE) {
                    anim = AnimationUtils.loadAnimation
                            (getApplicationContext()
                            , android.R.anim.fade_out);
                    imgLogo.startAnimation(anim);
                    imgLogo.setVisibility(View.INVISIBLE);
                } else {
                    anim = AnimationUtils.loadAnimation
                            (getApplicationContext()
                            , android.R.anim.fade_in);
                    imgLogo.startAnimation(anim);
                    imgLogo.setVisibility(View.VISIBLE);
                }
            }
        });

        Button btnSlideIn = (Button)findViewById(R.id.btnSlideIn);
        btnSlideIn.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                imgLogo.setVisibility(View.VISIBLE);
                anim = AnimationUtils.loadAnimation(
                        getApplicationContext()
                        , android.R.anim.slide_in_left);
                anim.setDuration(1000);
                imgLogo.startAnimation(anim);
            }
        });

        Button btnSlideOut = (Button)findViewById(R.id.btnSlideOut);
        btnSlideOut.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                imgLogo.setVisibility(View.VISIBLE);
                anim = AnimationUtils.loadAnimation(
                        getApplicationContext()
                        , android.R.anim.slide_out_right);

                anim.setAnimationListener(new AnimationListener() {
                    public void onAnimationEnd(Animation arg0) {
                        Log.i("Animation", "On Animation End");
                    }

                    public void onAnimationRepeat(Animation animation) {
                        Log.i("Animation", "On Animation Repeat");
                    }

                    public void onAnimationStart(Animation animation) {
                        Log.i("Animation", "On Animation Start");
                    }
                });    
                
                imgLogo.startAnimation(anim);
            }
        });
    }
}

ใน Event ของ btnFade จะเห็นว่าเจ้าของบล็อกใช้ If เพื่อเช็คว่า
imgLogo เป็น Visible(แสดงให้เห็น) หรือ Invisible (ซ่อนไม่ให้เห็น)
ถ้าภาพถูกแสดงอยู่ก็จะให้ทำการ Fade Out ภาพออกไป

แล้วจะกำหนดให้ภาพซ่อนไว้ โดยใช้คำสั่ง

imgLogo.setVisibility(View.VISIBLE); 

ที่ใช้คำสั่งนี้ก็เพราะว่า เมื่อภาพ Fade Out จนหายไปแล้ว
ก็จะเป็นการจบ Animation แล้วกลับมาเป็นเหมือนเดิม 
(เมื่อ Fade Out เสร็จ ภาพจะโผล่กลับมาให้เห็นเหมือนเดิม)
จึงต้องกำหนดให้ภาพไม่แสดงเพื่อให้ Fade Out แล้วภาพหายไปเลย
กรณีที่ภาพถูกซ่อนไว้ (Invisible) ก็จะ Fade In เข้ามาแล้วแสดงภาพ
ก็เหมือนกับตอน Fade Out นั่นแหละ แต่ตรงข้ามกัน

สำหรับ Event ของ btnSlideIn ก็จะมีการใช้คำสั่ง
imgLogo.setVisibility(View.VISIBLE);
เอาไว้กรณีที่กดปุ่ม btnFade แล้วให้ภาพถูกซ่อน
เพราะเมื่อกดปุ่มนี้ต่อมันจะมองไม่เห็นการเคลื่อนไหว
เนื่องจากว่ามันถูกซ่อนไว้อยู่นั่นเอง และได้มีการเพิ่มคำสั่ง
anim.setDuration(1000);
ซึ่งเป็นคำสั่งกำหนดระยะเวลาการเคลื่อนไหว
ตอนรันแอพก็ให้ลองกดปุ่ม btnSlideIn เทียบกับ btnSlideOut ดู
จะเห็นว่าตอน Slide In Left จะช้ากว่า Slide In Right 
เพราะ Slide Out Right ไม่ได้กำหนดเวลา จึงใช้ค่ามาตรฐาน

สำหรับ Event ของ btnSlideOut ก็จะมีการกำหนด Event ขึ้นมา

เป็น Animation Listener เอาไว้จับเหตุการณ์ตอน Animation ทำงาน
จะมีอยู่สามเหตุการณ์คือ เริ่มทำงาน (onAnimationStart)
วนการทำงาน (onAnimationRepeat) และหยุดทำงาน (onAnimationEnd)
โดยจะให้แสดงข้อความขึ้น LogCat ว่ากำลังอยู่ในเหตุการณ์ไหน
สำหรับตัวอย่างนี้ ตอนทดสอบจะทำงานแค่ Start และ End เท่านั้น
ทั้งนี้เพราะการ Repeat จะใช้กับ Animation Set เท่านั้น ไว้เขียนให้อ่านทีหลัง


main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <Button
        android:id="@+id/btnFade"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toLeftOf="@+id/btnSlideIn"
        android:text="Fade In/Out" />
    <Button
        android:id="@+id/btnSlideIn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:text="Slide In" />
    <Button
        android:id="@+id/btnSlideOut"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/btnSlideIn"
        android:text="Slide Out" />
    <ImageView
        android:id="@+id/imgLogo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/samplelogo" />
</RelativeLayout>

AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="app.akexorcist.simpleanimation"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".Main"
            android:label="@string/title_activity_main" 
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

สำหรับผู้ที่หลงเข้ามาอ่านที่ต้องการไฟล์ตัวอย่างสามารถดาวน์โหลดได้จาก
Animation-Simple [Google Drive] หรือ Animation-Simple [GitHub]

บทความที่เกี่ยวกับคลาส Animation


แค่นี้แหละแบบง่ายๆ
ปั่นบทความเสร็จไวดี




เหล่าพันธมิตรแอนดรอยด์

Devahoy Layer Net NuuNeoI The Cheese Factory Somkiat CC Mart Routine Artit-K Arnondora Kamonway Try to be android developer Oatrice Benz Nest Studios Kotchaphan@Medium Jirawatee@Medium Travispea@Medium