יום שישי, אוקטובר 29

Widgets - מבוא לווידג'טים

ווידג'טים הם אלמנטים בממשק המשתמש (UI) לשימוש במסך האפליקציה. למשל -  כפתורים, חלונות תצוגה. האפליקציה הבאה מדגימה שימוש בכפתורים , ואלמנטי טקסט. ה-UI כולל:
  • איזור קלט אליו אפשר להקליד טקסט.
  • איזור פלט לתצוגת טקסט.
  • כפתור להעתקת הקלט לאיזור הפלט.
  • כפתור לניקוי איזור הפלט.

לחץ על הקישור להורדת קבצי המקור.

נבחן תחילה את בקובץ main.xml:



  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:orientation="vertical"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent">
  6.    
  7.     <EditText
  8.     android:id="@+id/edit_box"
  9.     android:layout_width="fill_parent"
  10.     android:layout_height="wrap_content"
  11.     android:autoText="true"
  12. />
  13.    
  14.     <Button android:id="@+id/copy_button"
  15.     android:text="@string/copy"
  16.     android:layout_width="wrap_content"
  17.     android:layout_height="wrap_content" />
  18.    
  19. <TextView 
  20.     android:id="@+id/text_box"
  21.     android:layout_width="fill_parent"
  22.     android:layout_height="wrap_content"
  23.     />
  24.  <Button android:id="@+id/clean_button"
  25.     android:text="@string/clean"
  26.     android:layout_width="wrap_content"
  27.     android:layout_height="wrap_content" />
  28.    
  29. </LinearLayout>
 הסברים:

שורה 7-12: הגדרה של חלון קלט טקסט.
שורה 14-17:הגדרת כפתור העתקה.
שורה 19-22: הגדרת חלון פלט טקסט.
שורה 24-27: הגדרת כפתור מחיקת טקסט.

נבחן את קוד הג'אווה בקובץ MyWidget.java:



  1. package com.ahs.ronen.widgetIntro;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.widget.Button;
  6. import android.widget.EditText;
  7. import android.widget.TextView;
  8. public class MyWidget extends Activity {
  9.     TextView    textBox     ;
  10.     EditText    editBox     ;
  11.     Button        cleanButton ;
  12.     Button        copyButton     ;
  13.      /** Called when the activity is first created. */
  14.     @Override
  15.     public void onCreate(Bundle savedInstanceState) {
  16.    
  17.         super.onCreate(savedInstanceState);
  18.         setContentView(R.layout.main);
  19.         textBox     = (TextView)findViewById(R.id.text_box);
  20.         editBox     = (EditText)findViewById(R.id.edit_box);
  21.         cleanButton = (Button)findViewById(R.id.clean_button);
  22.         copyButton     = (Button)findViewById(R.id.copy_button);
  23.        cleanButton.setOnClickListener(new View.OnClickListener() {
  24.             public void onClick(View view) {
  25.                 textBox.setText("");
  26.              }
  27.         });
  28.        copyButton.setOnClickListener(new View.OnClickListener() {
  29.             public void onClick(View view) {
  30.                 textBox.setText("");
  31.                 textBox.setText((editBox.getText().toString()));
  32.              }
  33.         });
  34.     }
  35. }

שורה 8: זוהי מחלקה\class היורשת את Activity,  ומטפלת ביצירת חלון ליצירת ממשקי המשתמש.
שורה 9-12: הכרזה של האובייקטים בהם נשתמש:
  1.  TextView הוא אובייקט להצגת טקסט
  2. EditText הוא אובייקט לקליטת טקסט
  3. Button הוא אובייקט לכפתור אינטראקטיבי.
שורה 15: onCreate היא מתודה המופעלת עם הפעלת האובייקט.
שורה 17: הפעלת המתודה של ה"אבא". המימוש שלנו עוקף את מתודת ה- onCreate המקורית של מחלקת ה- Activity -  ראה override שורה 14. יחד עם זאת עלינו לקרוא למתודה המקורית.
שורה 18: הגדרת ה- UI. המתודה ( setContentView(R.layout.main מגדירה את ממשק המשתמש על פי ה-layout עליו היא מצביעה, במקרה הנ"ל קובץ layout בשם main הנמצא בספריית layout. הקובץ R.java, מכיל אינדקסים ל-resources שהוגדרו עבור ה- UI. (עניין זה נידון כבר ה- Hello World). שימו לב: setContentView חיית להיות מופעלת לפני כל מתודה הקשורה ל- UI. אחרת תתקבל  Error בזמן ההרצה.
שורה 19-23:
        textBox     = (TextView)findViewById(R.id.text_box);
        editBox     = (EditText)findViewById(R.id.edit_box);
        cleanButton = (Button)findViewById(R.id.clean_button);
        copyButton     = (Button)findViewById(R.id.copy_button);


findViewById שולפת את הגדרות הווידג'טים לתוך האובביקטים שלהן - שני הכפתורים ושני אובייקטים של טקסט.

שורה 24-27:
חיבור (רגיסטרציה) של פונקציה  שתופעל עם הלחיצה על כפתור clean, מה שנקרא callback. 

  1.     cleanButton.setOnClickListener(new View.OnClickListener() {
  2.             public void onClick(View view) {
  3.                 textBox.setText("");
  4.              }
  5.         });
שורה setOnClickListener- 1 המתודה של מחלקת ה-Button שעושה את הרגיסטרציה ל- callback.
שורה 2. המתודה שתופעל עם לחיצת הכפתור היא onClick השייכת ל-Interface - OnClickListener הנבנה כאן בצורה "אנונימית". 
שורה 3. המתודה שתקרא מתוך ה- callBack היא setText של האובייקט textBox. מתודה זו מעבירה את הטקסט לתוך האוביקט-textBox. במקרה הזה, הטקסט ריק ולכן המסך ינוקה.


שורות 28-31: רגיסטרציה של מתודה שתופעל עם לחיצה על כפתור copy. דומה לכפתור ה- clean שתואר למעלה.

  1.        copyButton.setOnClickListener(new View.OnClickListener() {
  2.             public void onClick(View view) {
  3.                 textBox.setText("");
  4.                 textBox.setText((editBox.getText().toString()));
שורה 4 מעבירה לאוביקט התצוגה textBox את קלט מהאובייקט editBox.

11 תגובות:

  1. יש לי שאלה בנושא שימוש בזיכרון , מה עדיף , להגדיר את האוביקטים כמו שאתה הגדרתה בתוך הCLASS (את הכפתורים ...) או להגדיר אותם בתוך הHENDEL (setOnClickListene)של הלחיצה ,כי זה יצור אותם רק בלחיצה עליו, או שזה לא משנה מבחינת הקצאות זיכרון לאובייקט?

    השבמחק
  2. הי לאוניד, בהחלט עדיף להגדיר את האובייקטים בתחום הדרוש בלבד. אנא הצע פתרון יעיל יותר אם ניתן. רונן.

    השבמחק
  3. מה אתה אומר על הדוגמה הזאות ? (התחשבות להקצאות זיכרון מה עדיף?)

    Button btRemoveIcon = (Button) findViewById(R.id.remove_icon);

    btRemoveIcon.setOnClickListener(new View.OnClickListener() {

    public void onClick(View view) {

    //Code here

    }

    });

    השבמחק
  4. לאוניד, בהחלט פתרון יעיל יותר. רונן.

    השבמחק
  5. הפיתרון יעיל רק בהנחה שאתה לא תרצה לשנות מאפיינים של הווידג'ט מאוחר יותר בתוך הקוד. (כפתורים בד"כ נשארים קבועים)

    אבל אם אתה מתכנן לבצע שינויים בווידג'ט (כמו ב TextView למשל הרי שלדעתי עדיף כבר להחזיק רפרנס קבוע אליו, מאשר לקרוא כל פעם ל findViewByID.

    הרי ממילא החיסכון שלך בזיכרון הוא זניח מאוד.
    מדוע? כי בג'אווה אתה מתעסק רק ברפרנס (פויינטר) ולא באובייקט עצמו, ולכן אם יש לך כפתור מוצג על המסך, אז הוא ממילא טעון ב RAM, וכל התוספת של להחזיק רפרנס לכפתור באופן קבוע זה רק תוספת של רפרנס ל Button ולא אובייקט Button שלם, שהרי לא אתה יצרת אותו.

    השבמחק
  6. שלום רונן,
    איני מצליח לראות את צילומי המסך מלבד פוסטים בודדים..
    לפני כמה ימים זה כן עבד,
    אם הבעיה לא אצלי - יש מצב שתוכל לסדר את העניין (זה מאוד עוזר להבנה)
    תודה רבה..

    השבמחק
  7. הבעיה אצלי לא קיימת. נסה להחליף דפדפן או לנקות את ה-cache.

    השבמחק
  8. היי רונן
    נורא אוהבת את המדריכים שלך הם עזרו לי מאוד!
    אני עובדת על אפליקציה שהיא בעצם מדריך שכולל מאמרים ותמונות.
    הצלחתי להכניס gallery לפי המדריך שלך :)
    אבל אני לא מצליחה להכניס קובץ טקסט... אשמח אם תוכל לעזור לי...

    השבמחק
  9. שאלה: כשכותבים טקסט כמו למשל ה hello world יש לפניו הרי את ה / string@ ורק אז הטקסט. כשאני מפעילה באימולטור, אני רואה גם את זה כחלק מהטקסט למרות שזה לא. אם אני מוחקת, מן הסתם המערכת צועקת על שגיאה. איך פותרים זאת? אני התחלתי רק לימודים

    השבמחק
  10. שאלה: במקום להשתמש באמולטור (איטי ומסורבל) אני פשוט מרי לטלפון, אבל האפליקציו נשארות עליו. יש דרך להגדיר שהן ירוצו ווירטואלית או יותקנו וימחקו לאחר הרצה?

    השבמחק
  11. איך מסתדרים עם יישור לימין? כשאני כותב טקסט הוא מופיע הפוך.
    הצלחתי להצמיד לימין (לאפשר את זה בmainfest, ולהגדיר gravity לימין) אבל הטקסט הפוך... יש פתרון נורמלי חוץ מלהקליד הכל הפוך?

    השבמחק