Sunday, May 27, 2012

תכנות לאנדרואיד בקלות פרק 8 - בניית אנימציות tween, frame by frame

בפרק זה אנו נראה כיצד אנחנו יכולים להפוך את ה UI שלנו למעניין יותר ע"י שימוש ב Animation API שמגיע אלינו בתוך ה Android SDK.
נתמקד בשני סוגי אנימציות עיקריים: Frame by frame, tween
כמו בפעמים אחרות שנתקלנו בהן – ניתן לבצע אנימציות גם ב xml וגם בקוד.
כרגע נדבר על tween animation:
נבחן את קטע ה XML הבא:
בתוך תיקיית res צרו תיקיית anim ובתוכה קובץ xml חדש אשר נקרא simpleanimation.xml
<?xml version="1.0" encoding="UTF-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator">
<rotate android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="30%"
android:startOffset="250"
android:duration="3000"/>
<alpha android:fromAlpha="1.0"
android:toAlpha="0.3"
android:duration="1000"/>
<scale android:fromXScale="1.0"
android:toXScale="0.5"
android:fromYScale="1.0"
android:toYScale="0.5"
android:startOffset="500"
android:duration="2000"/>
</set>
התגית הראשונה: set
מרמזת על כך שמדובר על set של כמה שינויים שאנחנו הולכים להכיל על אובייקט.
אם נתבונן על הבנים של set נראה שם 3 אנימציות שונות:
1. Rotate – אנימציית סיבוב (מ 0 מעלות ל 360 מעלות)
2. Alpha – אנימציית fade כאשר השקיפות משתנה
3. Scale – אנימציית הגדלה/הקטנה
כמובן שניתן לשלב כמה אלמנטים שנרצה אך יש לתכנן אותם מראש על מנת שהאנימציה תנוע כמו שרצינו.
כרגע זהו קובץ xml שלא מקושר לשום דבר, צריך להכיל את האנימציה הזאת על איזשהו Control.
נעבור לקוד ה java:
Animation anim;
TextView text;
//Tweened animation
anim = AnimationUtils.loadAnimation(this, R.anim.simpleanimation);
text = (TextView) findViewById(R.id.text);
text.startAnimation(anim);
המחלקה Animation מייצגת אנימציה, המשתנה anim הינו מסוג Animation ולתוכו אנו נטען את האנימציה מקובץ הXML שהרגע הכנו.
נעשה זאת ע"י המתודה הסטאטית
 AnimationUtils.loadAnimation(this,R.anim.simpleanimation)
המקבלת context ואת ה id של קובץ האנימציה מתוך תיקיית res/anim.
ונכיל את האנימציה על ה control , במקרה שלנו על המשתנה text. במידה ואנו שמים את קטע הקוד הזה במתודה onCreate() אז ההנפשה תחל מיד בטעינת ה Activity.
Frame by Frame Animation
כולנו מכירים את הרעיון של כמה תמונות אשר מתחלפות מהר מאוד ומשרות תחושה של תנועה, אז זה הרעיון בגדול.
אנו לוקחים סט של תמונות עם שינויים מינורים, נותנים לכל תמונה משך זמן מסויים להופיע במילישניות ומתחילים את לופ החלפת התמונות.
בסט המצורף של התמונות ישנן 9 תמונות בסיומת Png של דמות אשר אמורה ללכת, וכל תמונה שונה במעט מתמונה אחרת.
ניגש לתיקית ה drawable שלנו ונשים שם את סט התמונות הנ"ל. בנוסף ניצור שם קובץ xml חדש שאמור להגדיר מתי יהיה השינוי או התחלופה של התמונות הללו בינן לבין עצמן.
דוגמא לקטע xml י אשר משרת בדיוק את אותה המטרה:
<?xml version="1.0" encoding="UTF-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/frame01" android:duration="100" />
<item android:drawable="@drawable/frame02" android:duration="100" />
<item android:drawable="@drawable/frame03" android:duration="100" />
<item android:drawable="@drawable/frame04" android:duration="100" />
<item android:drawable="@drawable/frame05" android:duration="100" />
<item android:drawable="@drawable/frame06" android:duration="100" />
<item android:drawable="@drawable/frame07" android:duration="100" />
<item android:drawable="@drawable/frame08" android:duration="100" />
<item android:drawable="@drawable/frame09" android:duration="100" />
</animation-list>
למעשה האנימציה שלנו הינה animation-list ובתוכה יש לנו item - ים אשר כל אחד בעצם מצביע לתמונה אחרת לפי השם שלה (id)ומציין כמה זמן ב ms יקח לתמונה הזאת עד שהיא תתחלף לבאה אחריה לפי הסדר.
ובצד של הקוד :
AnimationDrawable walkingAnimation;
ImageView image = (ImageView)findViewById(R.id.walking_animation);
image.setBackgroundResource(R.drawable.walking);
walkingAnimation = (AnimationDrawable)image.getBackground();

יש לקרוא לתחילת האנימציה מתודה אחרת – ולא ב OnCreate()!!, למשל ב onTouch() אשר גם כן מתודה של Activity

public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (!walkingAnimation.isRunning()) {
walkingAnimation.start();
text.startAnimation(anim);
} else {
walkingAnimation.stop();
}
return true;
}
return super.onTouchEvent(event);
}