يتناول هذا المستند كيفية اتباع نمط Glass وتنفيذ أفضل الممارسات الشائعة لواجهة المستخدم عند استخدام GDK.
مظهر Glass
يطبق Glass مظهرًا قياسيًا على Glassware، بحيث يظل متسقًا مع بقية واجهة المستخدم. المظهر له السمات التالية:
- يستخدم الخط الطباعي Roboto
- عرض الأنشطة في وضع ملء الشاشة بدون شريط حالة أو شريط إجراءات
- يتم تطبيق خلفية سوداء خالصة
لتطبيق مظهر Glass، يجب عدم تعريفه في بيان Android.
إذا كان لديك نمط مخصص لأجزاء من Glassware
وتريد مظهر Glass التلقائي لكل شيء آخر،
يمكنك اكتسابه من Theme.DeviceDefault
مع السمة parent
:
<resources>
<style name="CustomTheme" parent="@android:style/Theme.DeviceDefault">
<!-- Theme customization goes here. -->
</style>
</resources>
يمكنك الاطّلاع على دليل مطوّري برامج Android حول الأنماط والمظاهر للحصول على مزيد من المعلومات عن إنشاء المظاهر.
بطاقات بنمط زجاجي
تنشئ الفئة CardBuilder
بطاقات جيدة الإعداد وفقًا لمجموعة من السمات. استخدِم التنسيقات
المتوفّرة في CardBuilder.Layout
كلما أمكن
لجعل المحتوى يبدو كأي محتوى آخر على Glass.
لاستخدام CardBuilder
:
- يمكنك إنشاء مثيل من
CardBuilder
، وتوفير التنسيق الذي تريده منCardBuilder.Layout
. - ضبط خصائص البطاقة، مثل النص والحاشية السفلية والطابع الزمني
- يمكنك طلب الرقم
CardBuilder.getView()
لتحويل البطاقة إلى جهاز AndroidView
، أوCardBuilder.getRemoteViews()
لتحويلها إلى عنصرRemoteViews
. - يمكنك استخدام
View
في أنشطتك أو تنسيقاتك أو فيCardScrollView
، أو استخدامRemoteViews
فيLiveCard
.
الميزات الشائعة لواجهة المستخدم
يتوافق العديد من التنسيقات التي يوفّرها CardBuilder
مع الميزات الشائعة لواجهة المستخدم الموضّحة أدناه. راجِع مستندات التنسيقات الفردية في CardBuilder.Layout
للحصول على قائمة بالميزات المتوافقة مع كل نوع من البطاقات.
رمز تحديد المصدر
رمز تحديد المصدر هو رمز اختياري بحجم 36 × 36 بكسل يظهر في أسفل يسار البطاقة وعلى يسار الطابع الزمني. يمكنك ضبط هذا الرمز من خلال استدعاء الرمز
CardBuilder.setAttributionIcon()
لتحديد تطبيقك، خاصةً إذا كنت تستخدم البطاقات المباشرة، ما يتيح للمستخدم إلقاء نظرة سريعة على مصدر المعلومات على تلك البطاقة.
مؤشر التكديس
مؤشر التكديس، الذي يتم التحكم فيه من خلال
CardBuilder.showStackIndicator()
،
هو طيّ زاوية الرؤية في أعلى يسار البطاقة. ويمكنك استخدام هذه البطاقة كمؤشّر مرئي على أنّ بطاقتك تمثّل حزمة من البطاقات الأخرى التي يمكن للمستخدم النقر عليها مباشرةً.
View view = new CardBuilder(context, CardBuilder.Layout.TEXT)
.setText("A stack indicator can be added to the corner of a card...")
.setAttributionIcon(R.drawable.ic_smile)
.showStackIndicator(true)
.getView();
التنسيقات
توضِّح الأمثلة التالية التنسيقات المتاحة باستخدام
CardBuilder
.
TEXT
وTEXT_FIXED
يعرض تنسيق CardBuilder.Layout.TEXT
نصًا كاملاً مع لوحة فسيفساء اختيارية في الخلفية. يتم تغيير حجم النص بشكل ديناميكي ليلائم المساحة المتاحة على أفضل وجه.
يُعد CardBuilder.Layout.TEXT_FIXED
مشابهًا ولكنه يعمل على إصلاح النص إلى حجم أصغر.
View view1 = new CardBuilder(context, CardBuilder.Layout.TEXT)
.setText("This is the TEXT layout. The text size will adjust dynamically.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.getView();
View view2 = new CardBuilder(context, CardBuilder.Layout.TEXT)
.setText("You can also add images to the background of a TEXT card.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.image1)
.addImage(R.drawable.image2)
.addImage(R.drawable.image3)
.addImage(R.drawable.image4)
.addImage(R.drawable.image5)
.getView();
View view3 = new CardBuilder(context, CardBuilder.Layout.TEXT_FIXED)
.setText("This is the TEXT_FIXED layout. The text size is always the same.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.getView();
COLUMNS
وCOLUMNS_FIXED
يعرض تنسيق CardBuilder.Layout.COLUMNS
صورة من الفسيفساء أو الرمز على الجانب الأيسر من البطاقة والنص على الجانب الأيسر. يتم تغيير حجم النص ديناميكيًا
ليتناسب مع المساحة المتاحة على أفضل نحو. للحفاظ على حجم النص ثابتًا، استخدِم CardBuilder.Layout.COLUMNS_FIXED
.
View view1 = new CardBuilder(context, CardBuilder.Layout.COLUMNS)
.setText("This is the COLUMNS layout with dynamic text.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.image1)
.addImage(R.drawable.image2)
.addImage(R.drawable.image3)
.addImage(R.drawable.image4)
.addImage(R.drawable.image5)
.getView();
View view2 = new CardBuilder(context, CardBuilder.Layout.COLUMNS)
.setText("You can even put a centered icon on a COLUMNS card instead of a mosaic.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.setIcon(R.drawable.ic_wifi)
.getView();
View view3 = new CardBuilder(context, CardBuilder.Layout.COLUMNS_FIXED)
.setText("This is the COLUMNS_FIXED layout. The text size is always the same.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.image1)
.addImage(R.drawable.image2)
.addImage(R.drawable.image3)
.addImage(R.drawable.image4)
.addImage(R.drawable.image5)
.getView();
CAPTION
يحتوي تنسيق
CardBuilder.Layout.CAPTION
على صورة فسيفساء في الخلفية
ونص شرح موجز تتم محاذاته في أسفل البطاقة. يمكن أيضًا وضع أيقونة بجانب الشرح لتمثيل، على سبيل المثال، هوية الشخص المرتبط بمحتوى البطاقة.
![](https://developers.google.cn/static/glass/images/glass-screens/card_caption.png?authuser=8&hl=ar)
![](https://developers.google.cn/static/glass/images/glass-screens/card_caption_icon.png?authuser=8&hl=ar)
View view1 = new CardBuilder(context, CardBuilder.Layout.CAPTION)
.setText("The caption layout.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.beach)
.setAttributionIcon(R.drawable.ic_smile)
.getView();
View view2 = new CardBuilder(context, CardBuilder.Layout.CAPTION)
.setText("The caption layout with an icon.")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.addImage(R.drawable.beach)
.setIcon(R.drawable.ic_avatar)
.setAttributionIcon(R.drawable.ic_smile)
.getView();
TITLE
يحتوي تصميم
CardBuilder.Layout.TITLE
على صورة فسيفساء في الخلفية
مع عنوان في الوسط ورمز اختياري في أسفل البطاقة. غالبًا ما يستخدم هذا التخطيط
لتمثيل جهات الاتصال أو مشاركة الأهداف. الحاشية السفلية والطابع الزمني
غير متوافقين مع هذا التنسيق.
View view = new CardBuilder(context, CardBuilder.Layout.TITLE)
.setText("TITLE Card")
.setIcon(R.drawable.ic_phone)
.addImage(R.drawable.beach)
.getView();
AUTHOR
يمكنك استخدام تنسيق
CardBuilder.Layout.AUTHOR
لعرض رسالة أو محادثة
حيث يكون التركيز على المؤلف. وهو يدعم فسيفساء الصورة في الخلفية،
وأيقونة تستخدم كالصورة الرمزية للمؤلف، وعنوانا وعنوان فرعيا حيث يمكنك
إدراج معلومات التعريف.
View view = new CardBuilder(context, CardBuilder.Layout.AUTHOR)
.setText("The AUTHOR layout lets you display a message or conversation "
+ " with a focus on the author.")
.setIcon(R.drawable.ic_avatar)
.setHeading("Joe Lastname")
.setSubheading("Mountain View, California")
.setFootnote("This is the footnote")
.setTimestamp("just now")
.getView();
MENU
يبدو تصميم
CardBuilder.Layout.MENU
كقائمة Glass عادية. يحتوي على أيقونة متوسيطة وعنوان وحاشية سفلية اختيارية. استخدم هذا التنسيق لشاشات التأكيد (الانتقال من "الحذف" إلى "المحذوف" بعد أن يحدد المستخدم عنصر قائمة، على سبيل المثال). إذا كنت بحاجة إلى قائمة حقيقية، فيجب عليك استخدام
قائمة خيارات قياسية بدلاً من ذلك.
View view = new CardBuilder(context, CardBuilder.Layout.MENU)
.setText("MENU layout")
.setIcon(R.drawable.ic_phone)
.setFootnote("Optional menu description")
.getView();
EMBED_INSIDE
يتضمّن تنسيق
CardBuilder.Layout.EMBED_INSIDE
تنسيق XML مخصّص لتصميمك داخل نموذج بطاقة Glass
القياسية. يتيح لك ذلك تصميم واجهة مستخدم مخصّصة لتطبيقك، مع الاحتفاظ بالموضع الصحيح للحاشية السفلية للبطاقة والطابع الزمني ورمز الإحالة ومؤشر تسلسل استدعاء الدوال البرمجية، إذا كانت هناك حاجة إليها.
بعد استدعاء الرمز
CardBuilder.getView()
،
استخدِم findViewById()
في النتيجة للوصول إلى طرق العرض داخل التنسيق المضمّن. وبالمثل، إذا استدعيت
CardBuilder.getRemoteViews()
،
يمكنك تعديل طرق عرض التنسيق المضمّن من خلال تمرير أرقام التعريف الخاصة بها مباشرةً
إلى طرق الإعداد
RemoteViews
.
View view = new CardBuilder(context, CardBuilder.Layout.EMBED_INSIDE)
.setEmbeddedLayout(R.layout.food_table)
.setFootnote("Foods you tracked")
.setTimestamp("today")
.getView();
TextView textView1 = (TextView) view.findViewById(R.id.text_view_1);
textView1.setText("Water");
// ...and so on
للحصول على مثال أكثر تفصيلاً، يُرجى الاطّلاع على مشروع ApiDemo في GitHub.
ALERT
يحتوي التنسيق
CardBuilder.Layout.ALERT
على رمز كبير في الوسط مع رسالة أساسية وحاشية سفلية. يمكنك استخدام هذا التنسيق في Dialog
لعرض رسالة إعلامية مهمة أو تحذير أو خطأ في Glassware.
يوضح المثال التالي طريقة تنفيذ AlertDialog
ويغلق البطاقة
ويفتح إعدادات Wi-Fi عندما ينقر المستخدم على البطاقة:
- أنشِئ صفًا يمتد إلى
Dialog
. - يمكنك إنشاء البطاقة باستخدام
CardBuilder
وتنسيقCardBuilder.Layout.ALERT
، ثم ضبط عرض المحتوى باستخدام هذه البطاقة. (اختياري) يمكنك إنشاء
GestureDetector
للتعامل مع إيماءات المستخدم على هذه البطاقة.public class AlertDialog extends Dialog { private final DialogInterface.OnClickListener mOnClickListener; private final AudioManager mAudioManager; private final GestureDetector mGestureDetector; /** * Handles the tap gesture to call the dialog's * onClickListener if one is provided. */ private final GestureDetector.BaseListener mBaseListener = new GestureDetector.BaseListener() { @Override public boolean onGesture(Gesture gesture) { if (gesture == Gesture.TAP) { mAudioManager.playSoundEffect(Sounds.TAP); if (mOnClickListener != null) { // Since Glass dialogs do not have buttons, // the index passed to onClick is always 0. mOnClickListener.onClick(AlertDialog.this, 0); } return true; } return false; } }; public AlertDialog(Context context, int iconResId, int textResId, int footnoteResId, DialogInterface.OnClickListener onClickListener) { super(context); mOnClickListener = onClickListener; mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mGestureDetector = new GestureDetector(context).setBaseListener(mBaseListener); setContentView(new CardBuilder(context, CardBuilder.Layout.ALERT) .setIcon(iconResId) .setText(textResId) .setFootnote(footnoteResId) .getView()); } /** Overridden to let the gesture detector handle a possible tap event. */ @Override public boolean onGenericMotionEvent(MotionEvent event) { return mGestureDetector.onMotionEvent(event) || super.onGenericMotionEvent(event); } }
(اختياري) في نشاطك، نفِّذ
OnClickListener
للتعامل مع أي مسارات إضافية عندما ينقر المستخدم. لمزيد من المعلومات حول بدء أنشطة الإعدادات مثل WiFi، راجع إعدادات البدء.عليك استدعاء الدالة الإنشائية
AlertDialog
لعرض بطاقة التنبيه.public class MyActivity extends Activity { ... private final DialogInterface.OnClickListener mOnClickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int button) { // Open WiFi Settings startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); } }; @Override protected void onCreate(Bundle bundle) { ... new AlertDialog(context, R.drawable.ic_cloud_sad_150, R.string.alert_text, R.string.alert_footnote_text, mOnClickListener).show(); ... } }
تنسيقات XML
فيما يلي تنسيقان أساسيان للبطاقات يمكنك استخدامهما إذا كانت فئة CardBuilder لا تلبي احتياجاتك.
التخطيط الرئيسي
يحدد هذا التنسيق المساحة المتروكة والتذييل القياسية للبطاقة. ضع طرق العرض الخاصة بك
في RelativeLayout
الفارغ.
![](https://developers.google.cn/static/glass/images/grids/main-template.png?authuser=8&hl=ar)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:id="@+id/body_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/glass_card_body_height"
android:layout_marginLeft="@dimen/glass_card_margin"
android:layout_marginTop="@dimen/glass_card_margin"
android:layout_marginRight="@dimen/glass_card_margin"
tools:ignore="UselessLeaf"
>
<!-- Put your widgets inside this RelativeLayout. -->
</RelativeLayout>
<LinearLayout
android:id="@+id/footer_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|left"
android:layout_marginLeft="@dimen/glass_card_margin"
android:layout_marginBottom="@dimen/glass_card_footer_margin"
android:layout_marginRight="@dimen/glass_card_margin"
android:orientation="horizontal"
>
<!-- The footer view will grow to fit as much content as possible while the
timestamp view keeps a fixed width. If the footer text is too long, it
will be ellipsized with a 40px margin between it and the timestamp. -->
<TextView
android:id="@+id/footer"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
<TextView
android:id="@+id/timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/glass_card_margin"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
</LinearLayout>
</FrameLayout>
تنسيق العمود الأيسر
يحدد هذا عمودًا أيسرًا بحجم 240 بكسل وعمودًا أيمنًا بحجم 400 بكسل على شكل عمودين RelativeLayout
يمكنك وضع طرق العرض فيهما.
![](https://developers.google.cn/static/glass/images/grids/left-column-template.png?authuser=8&hl=ar)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:id="@+id/left_column"
android:layout_width="@dimen/glass_card_left_column_width"
android:layout_height="match_parent"
>
<!-- Put widgets for the left column inside this RelativeLayout. -->
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="@dimen/glass_card_body_height"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="@dimen/glass_card_two_column_margin"
android:layout_marginRight="@dimen/glass_card_margin"
android:layout_marginTop="@dimen/glass_card_margin"
android:layout_toRightOf="@+id/left_column"
tools:ignore="UselessLeaf"
>
<!-- Put widgets for the right column inside this RelativeLayout. -->
</RelativeLayout>
<LinearLayout
android:id="@+id/footer_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_gravity="bottom|left"
android:layout_marginBottom="@dimen/glass_card_footer_margin"
android:layout_marginLeft="@dimen/glass_card_two_column_margin"
android:layout_marginRight="@dimen/glass_card_margin"
android:layout_toRightOf="@+id/left_column"
android:orientation="horizontal"
>
<!--
The footer view will grow to fit as much content as possible while the
timestamp view keeps a fixed width. If the footer text is too long, it
will be ellipsized with a 40px margin between it and the timestamp.
-->
<TextView
android:id="@+id/footer"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
<TextView
android:id="@+id/timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/glass_card_margin"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
</LinearLayout>
</RelativeLayout>
السمات العادية
استخدم هذا الملف إلى جانب التنسيقات السابقة أو التنسيقات الخاصة بك للالتزام بنمط Glass القياسي. أنشِئ هذا الملف باسم
"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">40px</dimen>
<!-- The recommended margin between the bottom of the card and the footer. This is
an adjusted value so that the baseline of the text in the footer sits 40px
from the bottom of the card, matching the other margins. -->
<dimen name="glass_card_footer_margin">33px</dimen>
<!-- The recommended margin for the left column of the two-column card. -->
<dimen name="glass_card_two_column_margin">30px</dimen>
<!-- The maximum height of the body content inside a card. -->
<dimen name="glass_card_body_height">240px</dimen>
<!-- The width of the left column in the two-column layout. -->
<dimen name="glass_card_left_column_width">240px</dimen>
</resources>