ממשק משתמש

מסמך זה מסביר כיצד לעקוב אחר סגנון Glass וליישם שיטות מומלצות לעבודה עם ממשק המשתמש, שיכולות לשפר את חוויית המשתמש. הוא כולל את רכיבי ממשק המשתמש הבאים:

עיצוב

העיצוב של Glass שאנחנו ממליצים להשתמש בו כולל את המאפיינים הבאים:

  • הצגת פעילויות במסך מלא ללא סרגל פעולות.
  • יש להחיל רקע בצבע שחור מלא.
  • מגדיר את הגוון הצבעוני לאפקט של קצה הצבע.
  • החלת צבע טקסט לבן.

הנה הגדרות העיצוב המומלצות עבור Glass:

 <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
   <item name="android:windowBackground">@android:color/black</item>
   <item name="android:colorEdgeEffect">@android:color/white</item>
   <item name="android:textColor">@android:color/white</item>
 </style>

פריסות XML

הנה שתי פריסות בסיסיות של כרטיסים שהמקטעים שלהם יכולים לנפח:

פריסה ראשית

הפריסה הזו מגדירה את המרווח הסטנדרטי והתחתון המומלץ לכרטיס. עליך להזין את מספר הצפיות שלך FrameLayout ריק.

האריזה במרכז תופסת את רוב השטח של המסך ב-560 על 240 פיקסלים, עם סרגל קטן בחלק התחתון בגודל 560 על 40 פיקסלים.
          יש גם ארבעה בלוקים קטנים של 40 על 40 פיקסלים, אחד בכל פינה

הנה דוגמה לפריסת XML:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <FrameLayout
      android:id="@+id/body_layout"
      android:layout_width="0dp"
      android:layout_height="0dp"
      android:layout_margin="@dimen/glass_card_margin"
      app:layout_constraintBottom_toTopOf="@id/footer"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent">

    <!-- Put your widgets inside this FrameLayout. -->

  </FrameLayout>

  <!-- The footer view will grow to fit as much content as possible while the
         timestamp view keeps its width. If the footer text is too long, it
         will be ellipsized with a 40dp margin between it and the timestamp. -->

  <TextView
      android:id="@+id/footer"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="@dimen/glass_card_margin"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toStartOf="@id/timestamp"
      app:layout_constraintStart_toStartOf="parent" />

  <TextView
      android:id="@+id/timestamp"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAlignment="viewEnd"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

פריסת העמודה השמאלית

הפריסה הזו מגדירה עמודה שמאלית ברוחב של שלישי ועמודה ימנית ברוחב של שני שלישים בצורת שתי כיתות FrameLayout שאפשר להוסיף להן את מספר הצפיות. כדי לראות דוגמה, אפשר לעיין בתמונה הבאה.

הצגת עמודה שמאלית בגודל 240 על 360 פיקסלים, שדוחפת את הפריסה הראשית מעל.
          גודלו נדחס כדי להתאים אותו, והאזור הראשי הוא בגודל 330 על 240 פיקסלים, עם פס תחתון קטן יותר בגודל 330 על 40 פיקסלים. לשתי הפינות הימניות יש שתי תיבות קטנות בגודל 40 על 40 פיקסלים, ויש ארבע תיבות נוספות בגודל 30 על 40 פיקסלים, שתיים בפינות התחתונות של העמודה השמאלית ושתיים בצד שמאל של הפריסה הראשית, אחת בחלק העליון ואחת בחלק התחתון.

הנה דוגמה לפריסת XML:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <FrameLayout
      android:id="@+id/left_column"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:background="#303030"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintWidth_percent=".333">

    <!-- Put widgets for the left column inside this FrameLayout. -->

  </FrameLayout>

  <FrameLayout
      android:id="@+id/right_column"
      android:layout_width="0dp"
      android:layout_height="0dp"
      android:layout_marginTop="@dimen/glass_card_two_column_margin"
      android:layout_marginStart="@dimen/glass_card_two_column_margin"
      android:layout_marginBottom="@dimen/glass_card_two_column_margin"
      android:layout_marginEnd="@dimen/glass_card_margin"
      app:layout_constraintBottom_toTopOf="@id/footer"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toEndOf="@id/left_column"
      app:layout_constraintTop_toTopOf="parent">

    <!-- Put widgets for the right column inside this FrameLayout. -->

  </FrameLayout>

  <!-- The footer view will grow to fit as much content as possible while the
         timestamp view keeps its width. If the footer text is too long, it
         will be ellipsized with a 40dp margin between it and the timestamp. -->

  <TextView
      android:id="@+id/footer"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="@dimen/glass_card_margin"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toStartOf="@id/timestamp"
      app:layout_constraintStart_toEndOf="@id/left_column" />

  <TextView
      android:id="@+id/timestamp"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginEnd="@dimen/glass_card_margin"
      android:layout_marginBottom="@dimen/glass_card_margin"
      android:ellipsize="end"
      android:singleLine="true"
      android:textAlignment="viewEnd"
      android:textAppearance="?android:attr/textAppearanceSmall"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

מאפיינים רגילים

כדי ליצור קובץ שתואם לסגנון של Glass&#39, יש להשתמש בתווים הבאים: יצירת הקובץ הזה כ-res/values/dimens.xml בפרויקט Android שלך.

<?xml version="1.0" encoding="utf-8"?>
<resources>

  <!-- The recommended margin for the top, left, and right edges of a card. -->
  <dimen name="glass_card_margin">40dp</dimen>

  <!-- The recommended margin between the bottom of the card and the footer. -->
  <dimen name="glass_card_footer_margin">50dp</dimen>

  <!-- The recommended margin for the left column of the two-column card. -->
  <dimen name="glass_card_two_column_margin">30dp</dimen>

</resources>

אנחנו ממליצים להשתמש ב- RecyclerView כדי ליצור תפריטים. הקבצים צריכים להתבסס על קובץ התפריט הרגיל של Android ממשאבי הפרויקט ב-Android Studio. Android מאפשר לך לבטל את יצירת התפריט הרגיל ולהחליף אותה בהטמעה. לשם כך, צריך:

  1. יוצרים את הפריסה באמצעות RecyclerView ומגדירים אותה כתצוגה עבור Activity.
  2. יש להגדיר את RecyclerView ואת המתאם שלו לשימוש באוסף החדש שנוצר של אפשרויות בתפריט.
  3. יש לבטל את השיטה onCreateOptionsMenu.
    1. מגדילים את התפריט ומוסיפים את הרכיב החדש לאוסף עבור כל פריט בתפריט.
    2. יש להפעיל את השיטה notifyDataSetChanged במתאם.

    Kotlin

        override fun onCreateOptionsMenu(menu: Menu): Boolean {
            val menuResource = intent
                .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE)
            if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) {
                menuInflater.inflate(menuResource, menu)
                for (i in 0 until menu.size()) {
                    val menuItem = menu.getItem(i)
                    menuItems.add(
                        GlassMenuItem(
                            menuItem.itemId, menuItem.icon,
                            menuItem.title.toString()
                        )
                    )
                    adapter.notifyDataSetChanged()
                }
            }
            return super.onCreateOptionsMenu(menu)
        }
        

    Java

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
          final int menuResource = getIntent()
              .getIntExtra(EXTRA_MENU_KEY, EXTRA_MENU_ITEM_DEFAULT_VALUE);
          if (menuResource != EXTRA_MENU_ITEM_DEFAULT_VALUE) {
            final MenuInflater inflater = getMenuInflater();
            inflater.inflate(menuResource, menu);
    
            for (int i = 0; i < menu.size(); i++) {
              final MenuItem menuItem = menu.getItem(i);
              menuItems.add(
                  new GlassMenuItem(menuItem.getItemId(), menuItem.getIcon(),
                      menuItem.getTitle().toString()));
              adapter.notifyDataSetChanged();
            }
          }
          return super.onCreateOptionsMenu(menu);
        }
        
  4. יש להשתמש במאפיינים OnScrollListener יחד עם LayoutManager ו- SnapHelper כדי לקבוע איזו אפשרות נבחרה.
  5. מאזינים לתנועה של TAP כדי לטפל באירוע שנבחר בתפריט.
  6. יוצרים Intent מידע על המנה שנבחרה.
  7. יש להגדיר את התוצאה של הפעילות הזו ולסיים אותה.
  8. צריך להתקשר אל startActivityForResult מהקטע או מהפעילות שבהם רוצים לקבל תפריט. יש להשתמש בתנועה TAP למטרה זו.
  9. מבטלים את הערך onActivityResult בקטע הפעילות או בקטע השיחות כדי לטפל בפריט שנבחר בתפריט.

הנחיות

בהמשך מופיעה רשימת הצעות להגדרת פריסת התפריט:

התמונה הבאה היא דוגמה לפריסת תפריט מותאמת אישית:

התמונה הפשוטה הזו מציגה רקע שחור עם המילים &#39;MENU פריסה&#39; במרכז המסך וסמל טלפון צמוד.

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

דפים שניתן להחליק

מסך ה-Glass ולוח המגע פועלים ביחד להצגת כרטיסים שניתן להחליק. באמצעות ה-API הסטנדרטי של Android ViewPager אפשר ליצור דפים שניתנים להחלקה בפעילות.

לקבלת מידע נוסף על השימוש ב-Android ViewPager אפשר לגלול במסמכי התיעוד של שקף המסך.