Bu dokümanda, Glass stilini takip etme ve GDK'yı kullanırken yaygın kullanıcı arayüzü en iyi uygulamalarının nasıl uygulanacağı açıklanmaktadır.
Cam teması
Glass, Glassware'inize standart bir tema uyguladığından kullanıcı arayüzünün geri kalanıyla tutarlı olması sağlanır. Tema aşağıdaki özelliklere sahiptir:
- Roboto yazı karakteri kullanıyor
- Etkinlikleri durum çubuğu veya işlem çubuğu olmadan tam ekran olarak gösterir
- Düz, siyah arka plan uygulanır
Glass temasını uygulamak için Android Manifest'inizde tema beyan etmeyin.
Glassware'inizin parçaları için özel bir stiliniz varsa ve diğer her şey için varsayılan Google Glass temasını kullanmak istiyorsanız parent
özelliğiyle Theme.DeviceDefault
ürününden devralın:
<resources>
<style name="CustomTheme" parent="@android:style/Theme.DeviceDefault">
<!-- Theme customization goes here. -->
</style>
</resources>
Tema oluşturma hakkında daha fazla bilgi için Stiller ve Temalar ile ilgili Android geliştirici kılavuzuna bakın.
Cam tarzı kartlar
CardBuilder
sınıfı, bir mülk grubu göz önünde bulundurulduğunda iyi oluşturulmuş kartlar oluşturur. İçeriğinizin Glass'taki diğer içerikler gibi görünmesi için mümkün olduğunda CardBuilder.Layout
tarafından sağlanan düzenleri kullanın.
CardBuilder
uygulamasını kullanmak için:
CardBuilder.Layout
öğesinden istediğiniz düzeni vererekCardBuilder
örneğini oluşturun.- Kart özelliklerini (ör. metin, dipnot ve zaman damgası) ayarlayın.
- Kartı Android'e
View
dönüştürmek içinCardBuilder.getView()
komutunu veyaRemoteViews
nesnesine dönüştürmek içinCardBuilder.getRemoteViews()
numaralı telefonu çağırın. View
öğesini etkinliklerinizde, düzenlerinizde veyaCardScrollView
içinde ya daLiveCard
içindeRemoteViews
kullanın.
Genel kullanıcı arayüzü özellikleri
CardBuilder
tarafından sağlanan düzenlerin birçoğu, aşağıda açıklanan yaygın kullanıcı arayüzü özelliklerini destekler. Her kart türü tarafından desteklenen özelliklerin listesi için CardBuilder.Layout
'teki düzenlerle ilgili dokümanlara bakın.
İlişkilendirme simgesi
İlişkilendirme simgesi, kartın sağ alt köşesinde ve zaman damgasının sağında görünen, isteğe bağlı 36 × 36 piksellik bir simgedir. Özellikle canlı kartlarda uygulamanızı tanımlamak için CardBuilder.setAttributionIcon()
numaralı telefonu arayarak bu simgeyi ayarlayın. Böylece kullanıcı, karttaki bilgilerin kaynağına hızlıca göz atabilir.
Yığın göstergesi
CardBuilder.showStackIndicator()
tarafından kontrol edilen yığın göstergesi, kartın sağ üst köşesinde görünen, köşeye katlanan bir göstergedir. Bunu, kartınızın kullanıcının doğrudan dokunabileceği diğer kart paketini temsil ettiğinin görsel bir göstergesi olarak kullanın.
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();
Düzenler
Aşağıdaki örnekler, CardBuilder
ile kullanılabilen düzenleri gösterir.
TEXT
ve TEXT_FIXED
CardBuilder.Layout.TEXT
düzeni, arka planda isteğe bağlı bir resim mozaiğiyle birlikte tam çerçeve metin gösterir. Metin, mevcut alana en uygun şekilde dinamik olarak yeniden boyutlandırılır.
CardBuilder.Layout.TEXT_FIXED
benzerdir ancak metni daha küçük bir boyuta sabitler.
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
ve COLUMNS_FIXED
CardBuilder.Layout.COLUMNS
düzeninde kartın sol tarafında bir resim mozaiği veya simge, sağ tarafında ise metin gösteriliyor. Metin, mevcut alana en uygun şekilde
dinamik olarak boyutlandırılır. Metin boyutunu sabit tutmak için CardBuilder.Layout.COLUMNS_FIXED
değerini kullanın.
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
düzeninin arka planında bir resim mozaiği ve kartın alt kısmına hizalı kısa bir başlık metni bulunur. Altyazının yanına, örneğin kart içeriğiyle ilişkili bir kişinin kimliğini temsil edecek bir simge de yerleştirilebilir.
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
düzeninin arka planında, ortalanmış bir başlık ve kartın alt kısmında isteğe bağlı bir simge bulunan bir resim mozaiği bulunuyor. Bu düzen genellikle kişileri temsil etmek veya hedefleri paylaşmak için kullanılır. Dipnot ve zaman damgası bu düzende desteklenmez.
View view = new CardBuilder(context, CardBuilder.Layout.TITLE)
.setText("TITLE Card")
.setIcon(R.drawable.ic_phone)
.addImage(R.drawable.beach)
.getView();
AUTHOR
Yazarın odak noktası olduğu bir mesajı veya görüşmeyi görüntülemek için CardBuilder.Layout.AUTHOR
düzenini kullanın. Arka planda bir resim mozaiği, yazarın avatarı olarak kullanılan bir simge ve tanımlayıcı bilgileri listeleyebileceğiniz bir başlık ve alt başlığı destekler.
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
düzeni standart bir Glass menüsüne benzer. Ortalanmış bir simge, başlık ve isteğe bağlı bir dipnot bulunur. Onay ekranları için bu düzeni kullanın (örneğin, kullanıcı bir menü öğesi seçtikten sonra "Silme"den "Silindi"ye geçiş). Gerçek bir menüye ihtiyacınız varsa bunun yerine
standart seçenekler menüsünü kullanmalısınız.
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
düzeni, standart Glass kart şablonuna kendi tasarımınıza ait özel bir düzen XML'i yerleştirir. Bu, uygulamanız için özel bir kullanıcı arayüzü tasarlamanıza, ancak gerekirse kart dipnotunun, zaman damgasının, ilişkilendirme simgesinin ve yığın göstergesinin doğru yerleşimine sahip olmasını sağlar.
CardBuilder.getView()
çağrısından sonra, yerleştirilmiş düzeninizdeki görünümlere erişmek için sonuçta findViewById()
tuşunu kullanın. Benzer şekilde, CardBuilder.getRemoteViews()
yöntemini çağırırsanız bunların kimliklerini doğrudan RemoteViews
belirleyici yöntemlerine geçirerek yerleştirilmiş düzeninizin görünümlerini değiştirebilirsiniz.
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
Daha ayrıntılı bir örnek için GitHub ApiDemo projesine bakın.
ALERT
CardBuilder.Layout.ALERT
düzeninde, birincil mesaj ve dipnotun bulunduğu büyük bir ortalanmış simge bulunur. Glassware'inizde önemli bir bilgilendirme mesajı, uyarı veya hata göstermek için bu düzeni Dialog
içinde kullanın.
Aşağıdaki örnekte bir AlertDialog
uygulaması gösterilmektedir. Ayrıca, kullanıcı karta dokunduğunda kartı kapatıp kablosuz ağ ayarlarını açmaktadır:
Dialog
kapsamını genişleten bir sınıf oluşturun.CardBuilder
kodunuCardBuilder.Layout.ALERT
düzeniyle oluşturun ve ardından bu kartla içerik görünümünü ayarlayın.(İsteğe bağlı) Bu karttaki kullanıcı hareketlerini işlemek için bir
GestureDetector
oluşturun.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); } }
(İsteğe bağlı) Etkinliğinizde, kullanıcı dokunduğunda ek akışları işlemek için bir
OnClickListener
uygulayın. Kablosuz bağlantı gibi ayarları başlatma hakkında daha fazla bilgi için Başlangıç ayarları'na bakın.Uyarı kartını görüntülemek için
AlertDialog
oluşturucuyu çağırın.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 düzenleri
CardBuilder sınıfı ihtiyaçlarınızı karşılamazsa kullanabileceğiniz iki temel kart düzenini aşağıda bulabilirsiniz.
Ana düzen
Bu düzen, bir kart için standart dolguyu ve altbilgiyi tanımlar. Boş RelativeLayout
içine kendi görünümlerinizi girin.
<?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>
Sol sütun düzeni
Bu, görünümlerinizi yerleştirebileceğiniz iki RelativeLayout
biçiminde, 240 piksel sol ve 400 piksel sağ sütunu tanımlar.
<?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>
Standart boyutlar
Standart Glass stiline bağlı kalmak için bu dosyayı önceki düzenlerle veya kendi düzenlerinizle birlikte kullanın. Bu dosyayı Android projenizde res/values/dimens.xml
olarak oluşturun.
<?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>