MainActivity – מסך התפריט הראשי
חלון זה בעצם יהיה המסך הראשון שהמשתמש יראה. הוא יכיל תיאור קטן של המשחק וכפתור כניסה למשחק.
ניתן לעצב את התפריט הראשי בשני דרכים:
- לעצב את התפריט ישירות דרך ה-Eclipse.
- לעצב את התפריט דרך Photoshop ואז לייצא את כל הגרפיקה ולבנות אותה מחדש ב-Eclipse (בדיוק כמו שמעצבים עמודי אינטרנט).
מפני שאנו בונים משחק החלטתי דווקא ללכת על האפשרות השנייה. זאת בכדי שהמשחק שלנו יראה כמה שיותר מעניין ומעוצב.
לקחתי רזולוציה דיי גדולה (480 על 800) והתחלתי לעצב את המסך הראשי שיראה כך:
עיצוב ראשוני בפוטושופ |
אנו לא לוקחים את התמונה כמו שהיא אלא לוקחים רק את הגרפיקות החשובות: הלוגו והכפתור. ניתן ליצור את הרקע (ה-Gradient) בקלות – ניראה זאת בהמשך.
במרכז ה-Activity יופיע הסבר טקסטואלי כיצד משחקים. כפי שאמרנו עלינו לחלק את הגרפיקה ולכן נחלץ את כל רכיבי הגרפיקה לתמונות PNG עם רקע שקוף:
כפתור ה-Start
לוגו המשחק |
כפתור ה-Start כאשר הוא לחוץ |
עלינו לחלק את כל הרכיבים למספר רזולוציות: גבוהה, בינונית ונמוכה. הסיבה לכך היא תמיכה בגדלים שונים של מסכים ורזולוציות. ניתן לקרוא על כך במדריך הבא. מפני שייבאנו את כל הגרפיקה מבעוד מועד אינכם צריכים לעשות דבר. רק למטרות המדריך לא ניצור מספר רזולוציות בכדי להקל על גודל האפליקציה. באפליקציות רשמיות נהוג להשתמש במספר רזולוציות כך שתיראה באופן המיטבי על סוגים שונים של מכשירים.
בכדי לעשות רקע המשתמש ב-Gradient בדיוק כמו שתכננו נבצע את הדברים הבאים:
- לחיצה ימנית על התיקייה drawable.
- New > File.
- בתיבת ה-File Name נקליד main_background.xml.
- נאשר את החלון (Finish).
- נעתיק את הקוד הבא:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <gradient android:startColor="#00508d" android:endColor="#8dd3ff" android:angle="90" /> </shape>
הקוד הנ"ל מאפשר לנו ליצור Linear Gradient בקלות. אנו רק מתארים את הצבע ההתחלתי, הצבע הסופי והזווית שבה ה-Gradient יצטייר. ניתן לקרוא על Drawables מסוג זה בעמוד הבא.
עיצוב המסך באמצעות XML
כעת נפתח את מסמך ה-main.xml אשר נמצא בתיקיית ה-res/layout. סביבת הפיתוח מספקת לנו רכיבים שונים אשר עלינו להרכיבם בכדי ליצור מסכים שונים. ניתן לקרוא על ממשק ה- UIבעמוד הבא. בכמה מילים, רכיב כמו LinearLayout מאפשר לנו לשים את כל רכיבי האנדרויד שבתוכו כך שיסודרו האחד מתחת לשני או האחד ליד השני (תלוי בתצורה). זה הוא רכיב ברירת המחדל אשר נוצר עם ה-main.xml. לעומתו רכיב ה-RelativeLayout מאפשר לנו לסדר רכיבים בתוכו באופן יחסי האחד לשני. ז"א אם רכיב כלשהו נמצא במרכז המסך, נוכל לשים רכיב נוסף מתחתיו כך שבעצם הוא ישב תמיד מתחת לרכיב הראשון. אפילו אם הרכיב הראשון יזוז למקומות שונים.
אנו נשתמש ברכיב ה-RelativeLayout – כך שהלוגו יוצמד לחלק העליון של המסך, והטקסט של תיאור המשחק יופיע מתחתיו. את כפתור ה-Start נצמיד לתחתית המסך.
נחליף את הקוד המופיע ב-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" android:background="@drawable/main_background" android:orientation="vertical"> </RelativeLayout>
אם אינכם רואים את הקוד שמופיע במסמך ה-main.xml ככול הנראה אתם במצב של Graphical Layout המאפשר לנו ליראות ולערוך את המסמך בצורה גרפית. נלחץ על main.xml שמופיע בתחתית החלון (ישר מתחת לקוד) וכך נוכל ליראות את הקוד:
כעת פשוט נחליף את הקוד המופיע לקוד הכתוב למעלה. כעת אם נעבור חזרה למצב ה-Graphical Layout ניראה את התוצאה:
יבאנו את הרקע שכתבנו בתיקיית ה-Drawable באמצעות השורה:
android:background="@drawable/main_background"
סביבת העבודה Eclipse מאפשרת לנו לעצב את ה-Activity שלנו בשני צורות: באמצעות קוד או באמצעות ממשק גרפי. במדריך זה נעצב את ה-Activity באמצעות קוד בלבד. למרות זאת, מומלץ להתנסות עם הממשק הגרפי (לגרור רכיבים מהצד לתוך החלון) ולעבור לקוד וכך להתנסות יותר ולהבין את הקוד טוב יותר.
אבני היסוד – מרכיבי המסך הראשי איזה רכיבים נצטרך בכדי ליצור את התפריט הראשי?
- אם ניזכר במסך הראשי של התוכנה, בחלק העליון יש לוגו, מה שאומר שעלינו להשתמש ברכיב המציג תמונה. לרכיב זה קוראים ImageView וניתן לקרוא עליו בעמוד הבא ובתיעוד הרשמי.
- בחלק המרכזי, ישר מתחת ללוגו פירוט המשחק יוצג. רכיבים המציגים טקסט נקראים TextView. משתמשים בתכונת ה-Text שלהם בכדי לקבוע את התוכן שהם יציגו. התוכן יכול להיות תוכן ישיר הרשום לתוך הרכיב או אחד מן המחרוזות הנמצאים במסמך ה-strings.xml תחת תיקיית ה-values. ניתן לקרוא עליו בתיעוד הרשמי. את פירוט המשחק נרשום במסמך ה-strings.xml.
- בחלק התחתון יש כפתור Start – עלינו להשתמש ברכיב כפתור המאפשר לנו להלביש עליו תמונה של כפתור משלנו. לרכיב זה קוראים ImageButton. על כפתורים בכללי ניתן לקרוא בעמוד הבא. בנוסף ניתן גם לקרוא על רכיב ספציפי זה בתיעוד הרשמי.
כעת נחזור לקוד ה-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" android:background="@drawable/main_background" android:orientation="vertical"> <ImageView android:id="@+id/logo" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:src="@drawable/logo" android:adjustViewBounds="true" android:layout_marginTop="-20dp"/> <TextView android:id="@+id/descriptionLabel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/logo" android:text="@string/game_description" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_margin="15dp"/> <ImageButton android:id="@+id/startButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:src="@drawable/startbutton_selector" android:adjustViewBounds="true" android:scaleType="fitCenter" android:background="@android:color/transparent" android:layout_margin="5dp"/> </RelativeLayout>
כפי שניתן ליראות, הוספנו 3 רכיבים:
- ImageView – מציג את הלוגו העליון. תכונת ה-android:layout_alignParentTop מאפשרת לנו "להדביק" את הלוגו לחלק העליון של החלון. תכונת ה-android:layout_marginTop מעלה את הלוגו שלנו קצת מחוץ למסך החלון כך שהאצבע המופיעה על הלוגו תופיעה בחלקה רק (בדיוק כמו שניראה במסמך ה-PSD). אם עדיין לא הבנתם את הכוונה, הביטו בתמונת ה-logo.png שהורדתם ותיראו שהאצבע מופיעה במלואה ולא כמו שאנו רוצים. לרכיב זה נתנו ID של logo כך שנוכל להתייחס אליו באמצעות מזהה זה.
- TextView – רכיב האחראי להציג טקסט. נשתמש בו בכדי להציג את פירוט המשחק. למסמך ה-strings.xml הוספנו את המחרוזת game_description לאחר מכן את תכונת ה-android:text הפנינו לאותה המחרוזת. כפי שניתן ליראות השתמשנו בתכונות ה-android:layout_below אשר בעצם אומרת לרכיב תחת איזה רכיב בדיוק להתמקם.
- ImageButton – מציג את הכפתור התחתון. כפתור זה ממוקם בתחתית החלון ולכן עלינו להשתמש בתכונת ה-android:layout_alignParentBottom אשר מקבעת את הרכיב לתחתית המסך. השתמשנו בתכונת ה-android:src מאפשרת לנו לקבוע איזה תמונה תוצג בתוך הכפתור. כפי שניתן ליראות אנו מצביעים בתכונה זו על Selector בשם startbutton_selector אשר נמצאת בתיקיית ה-drawables. מיד נלמד מה הוא Selector ומה השימוש שלו. תכונה נוספת אשר בולטת היא תכונת ה-android:background אשר קובעת את רקע הכפתור. כברירת המחדל הכפתור יראה כמו כפתור אנדרואיד רגיל ולכן עלינו להעלים את הרקע שלו על ידי קביעת רקע שקוף – כך רק תמונת הכפתור שהכנו תוצג.
Selectors מאפשרים לנו לקבוע מה יוצג בכל מצב ומצב על אותו הרכיב. בכדי שכפתור ה-Start שלנו יוצג כלחוץ כאשר נלחץ עליו עלינו ליצור Selector אשר יעשה זאת.
נוסיף קובץ חדש לתיקיית ה-drawable בשם startbutton_selector.xml. כעת נעתיק את הקוד הבא:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/startbutton_down" /> <!– pressed –> <item android:drawable="@drawable/startbutton" /> <!– default –> </selector>
מה שבעצם מסמך זה אומר זה הדבר הבא: כאשר זוהתה לחיצה, שנה את התמונה לתמונת כפתור ה-Start הלחוצה (startbutton_down.png). כאשר הכפתור אינו לחוץ, שים את תמונת הכפתור הרגיל (startbutton.png). התוצאה הסופית שלנו תיראה פחות או יותר כך:
כעת מה שנשאר לנו זה רק החלק התכנותי של המסך הראשי. אין לנו הרבה מה לתכנת – אלא רק לקרוא ל-GameActivity כאשר לוחצים על כפתור ה-Start.
קצת Java נפתח את מסמך ה-MainActivity אשר נמצא בתיקיית ה-src תחת ה-Package היחיד שנמצא. הקוד שנמצא שם יראה כך:
package nemex.PushToScore; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }
כעת נדבר על מחזור החיים של Activities. הסתכלו באיור הבא:
איור זה מתאר לנו את השלבים ש-Activity עובר מתחילת חייו ועד "מותו". נעבור על מחזור החיים שבאיור:
- Activity Starts – המערכת קראה למסך שלנו להופיע – מכאן מתחיל "המסע".
- onCreate() – מתודה זו נקראת בפעם הראשונה כאשר החלון שלנו נוצר. כאן בד"כ מבצעים את כל הדברים הראשונים כאשר הפונקציה עולה כמו: יצירת Views, טעינת הגדרות חשובות וכו…
- onStart() – מתודה זו נקראת לאחר שהחלון שלנו מופיע. אחרי מתודה זו נקראות אחת מן המתודות הבאות: onRestart כאשר החלון מופיע מול המשתמש או onStopכאשר החלון נעלם (מתחבא).
- onRestart() – מתודה זו נקראת כאשר החלון שלנו נעצר ומתחיל שוב.
- onPause() – מתודה זו נקראת כאשר המערכת המערכת עומדת להריץ Activity אחר (כאשר החלון שלנו כבר לא יהיה החלון המופיע למשתמש). נהוג במתודה הזו לשמור שינויים שיש לבצע.
- onStop() – מתודה זו נקראת כאשר החלון שלנו כבר אינו ניראה יותר למשתמש מפני שחלון אחר נמצא מעל החלון שלנו. סיבה נוספת היא בגלל שהחלון שלנו עומדת להיהרס על ידי המערכת – במקרים כאלה פונקציית ה-onDestroy() נקראת לאחר מכן.
- onDestroy() – מתודה זו נקראת כאשר החלון שלנו עומד להיהרס. אחת מן הסיבות לכך שהחלון שלנו ייהרס היא או בגלל שמישהו קרא לפונקציית ה-finish אשר סוגרת את החלון או בגלל שהמערכת הורסת את החלון באופן זמני בכדי לחסוך במשאבים. ניתן להבחין בין השניים באמצעות המתודה isFinishing() .
ניתן לקרוא עוד על מחזור החיים של Activity בתיעוד הרשמי.
לאחר שהבנו את מחזור החיים כעת ניתן לחזור ל-MainActivity שלנו. כיצד נוכל לזהות שהמשתמש לחץ על כפתור ה-Start? נעשה זאת על ידי Callbacks. Callbacks מאפשרים לנו להגיד לרכיבים "לדווח" לנו כאשר נעשה אירוע מסוים עליהם. מבחינת התיאוריה זה עובד כך:
- אנו מספקים לרכיב ממשק שמימשנו.
- הרכיב קורא לפונקציות בממשק וכך מדווח לנו כאשר התרחש אירוע מסוים.
נחזור לקוד ה-MainActivity המחודש:
package nemex.PushToScore; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; public class MainActivity extends Activity { ImageButton startButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); startButton = (ImageButton) findViewById(R.id.startButton); startButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, GameActivity.class)); } }); } }
כפי שניתן ליראות הכרזנו על משתנה מסוג ImageButton בשם startButton. משתנה זה בעצם יהיה כפתור ה-Start שהמשתמש ילחץ עליו. כאשר מתודת ה-onCreate נקראת כאשר הפונקציה שלנו עולה אנו עושים את הדברים הבאים:
- אומרים ל-Activity שלנו שאנו רוצים להציג את ה-Layout שהכנו (main.xml) באמצעות פונקציית ה-setContentView.
- נותנים למשתנה ה-startButton את הערך של הכפתור שייצרנו ב-main.xml באמצעות פונקציית ה-findViewById. פונקציה זו מחפשת אחר הכפתור בתצורה שיצרנו ומחזירה אותו. מפני שהפונקציה מחזירה לנו View עלינו להמיר אותו ל-ImageButton. רכיבי ImageButton יורשים את רכיבי ה-View ולכן ההמרה אפשרית.
- משתמשים במתודת ה-setOnClickListener בכדי להגיב לאירועי לחיצה של הכפתור. הפרמטר שהמתודה מקבלת הוא ממשק OnClickListener. נספק לפונקציה ממשק משלנו אשר את פונקציית ה-onClick נממש כאשר הכפתור נלחץ. במילים אחרות – כל פעם שהמשתמש ילחץ על הכפתור החלון שלנו ייגש לפונקציית ה-onClick.
כעת כל מה שנשאר לנו זה לקרוא ל-GameActivity כאשר הכפתור נלחץ – במתודת ה-onClick שמימשנו כתבנו את הקוד הבא:
startActivity(new Intent(MainActivity.this, GameActivity.class));
זוכרים שדיברנו על Intents? בכדי שנוכל להתחיל Activity חדש עלינו להשתמש ב-Intents.
מה שעשינו זה ליצור Intent חדש, ה-Intent מקבל שני פרמטרים: Context ו-המחלקה של ה-Activity שאותו אנו רוצים.
הפרמטר הראשון מכיל מידע הנחוץ ל-Intent על סביבת האפליקציה בכדי לרוץ. הפרמטר השני מתאר בעצם איזה Activity אנו רוצים שאנדרואיד יריץ.
אם ננסה להריץ כעת את האפליקציה ניראה שכאשר נלחץ על כפתור ה-Start האפליקציה תקרוס. הסיבה לכך היא פשוטה: לא הכרזנו על GameActivity במסמך ה-AndroidManifest. זוכרים שדיברנו על כך שמסמך זה אמור להכיל מידע על כל ה-Activities? בדיוק לזה התכוונו.
נגש למסמך ה-AndroidManifest.xml ונשנה את הקוד המופיע לקוד הבא:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="nemex.PushToScore" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".MainActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:label="@string/app_name" android:name=".GameActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> </activity> </application> </manifest>
במסמך זה ביצענו מספר שינויים:
- הוספנו לאלמנט ה-activity את התכונה android:theme. תכונה זו מאפשרת לנו להגיד ל-Android שכאשר האפליקציה תרוץ אנו מעוניינים שהיא תרוץ ללא TitleBar ובמסך מלא. במילים האחרות אנו מעוניינים שה-Activity תרוץ על כל מסך המכשיר.
- הצהרנו על ה-GameActivity על ידי הוספת אלמנט activity נוסף. תכונת ה-android:name אומרת לאנדרואיד ששם ה-Activity הוא GameActivity. כך מערכת האנדרואיד מזהה את ה-Activity ולא גורמת לתוכנה לקרוס.
בניגוד ל-MainActivity ה-GameActivity לא מכיל את תג ה-intent-filter בתוכו. כפי שאמרנו, תג ה-intent-filter מאפשר לנו להגיד לאנדרואיד שה-Activity שלנו מסוגל להגיב ל"כוונות" (Intents) מסוימות, כגון הכוונה לרוץ בתור החלון הראשי שבדיוק בה השתמשנו למטרה זו.
זהו כעת סיימנו עם חלון ה-MainActivity! כעת נעבור ללב של האפליקציה ה-GameActivity!
מדריך איכותי בטירוף
תודה רבה!!
כל הכבוד
סוף סוף מדריך מ- א ועד ת.
מדריך מעולה !
ממש מדריך טוב ! תודה !
תודה@
נהדר תודה לך
איזה מקצוענות…כל הכבוד !
מדריך מעולה!
קצר וקולע, כל הכבוד!
הורדה של הכתבה ?
אפשר להוריד את הכתבה בפורמט pdf ?
כל הכבוד.
דרך אגב מישהו פעם ניסה לפתח עם flex?
זה מומלץ?
שי, יש אפשרות ליצור איתך קשר במייל?
אם כן, אשמח אם תשלח לי מייל לכתובת הבאה: [email protected]
אני זקוק לעזרה קטנה, שאני מאמין שלא תיהיה לך בעיה מיוחדת לעזור בה, תודה.
פששש
אחלה, כל הכבוד על ההשקעה.
hwzone – תמשיכו להביא כאלו כתבות !
מדריך מצויין אך
רק דבר אחד חסר לי וזה הסבר על google adsense ואיך משתמשים ומשלבים באפליקציה.
תותחים!!
כל הכבוד לhwzone תמשיכו להפציץ במדריכים מעולים!!
שאלה
לא הבנתי מאיפה מחלצים את resources.rar
קישור
איפה הקישור למדריך ?
מדריך מושקע לפיתוח אפליקציות
כל הכבוד על המדריך
רעיון לאפליקציה
שלום יש לי רעיון.
אפליקציה בשם המשמרת שלי . האפליקציה חיונית כיום בכל מפעל שמכבד את עצמו.כולנו בעלי סמארטפונים , אנחנו רוצים כל יום לדעת את המשמרת שלנו בעבודה . האפליקציה שאני בונה תסונכרן מול מחשבי החברה ותתריע על כל משמרת שאתה עושה. באיזה שעה מתחילה ובאיזה מסתיימת . שעת איסוף ועוד .. איזה משכורת אתה מקבל , כמה שעות אתה עובד. כמה % יש תוספת , מי שמעוניין לבנות איתי את האפילקציה ולהתחלק ברווחים שייצור קשר.
מדריך מצויין !!יש אפשרות ליצור איתך קשר?
שי אשמח אם תיצור איתי קשר במייל יש לי כמה שאלות ואשמח אם תוכל לעזור לי
[email protected]
בעניין תוכנת הeclipse
מלבד החלון הראשי שנוצר עם הפרויקט שלנו (MainActivity) אשר יכיל את התפריט הראשי של המשחק, ניצור חלון נוסף אשר יכיל את המשחק עצמו.
נעשה זאת על ידי העתקת קובץ ה-MainActivity ושינוי שמו ל-GameActivity. כעת נעשה את אותו הדבר לקובץ ה-main.xml שבתיקיית ה-reslayout ונקרא לו game.xml.
אני חייב עזרה בזה לא הבנתי איזה קובץ בדיוק להעתיק מאיפה ולאיפה אשמח למי שיעזור לי . המייל שלי [email protected] תודה
כל הכבוד!!!! מאמר מעולה.
מדריך טוב,
אבל הקבצים להורדה לא עובדים.
אם אפשר לסדר/יש למישהו ויכול להעלות שוב…
תודה!