定义Layouts

    可穿戴设备使用与手持Android设备同样的布局技术,但需要有具体的约束来设计。不要以一个手持app的角度开发功能和UI并期待得到一个好的体验。关于如何设计优秀的可穿戴应用的更多信息,请阅读Android Wear Design Guidelines

    当为Android Wear应用创建layout时,我们需要同时考虑方形和圆形屏幕的设备。在圆形Android Wear设备上所有放置在靠近屏幕边角的内容可能会被剪裁掉,所以为方形屏幕设计的layouts在圆形设备上不能很好地显示出来。对这类问题的示范请查看这个视频。

    举个例子,figure 1展示了下面的layout在圆形和方形屏幕上的效果:

    Figure 1. 为方形屏幕设计的layouts在圆形设备上不能很好显示的示范

    上述范例的文本没有正确地显示在圆形屏幕上。

    Wearable UI库为这个问题提供了两种不同的解决方案:

    • 为圆形和方形屏幕定义不同的layouts。我们的app会在运行时检查设备屏幕形状并inflate正确的layout。

    • 用一个包含在库里面的特殊layout同时适配方形和圆形设备。这个layout会在不同形状的设备屏幕窗口中插入不同的间隔。

    当我们希望应用在不同形状的屏幕上看起来不同时,一般会使用第一种方案。当我们希望用一个相似的layout在两种屏幕上且在圆形屏幕上没有视图被边缘剪裁时,可以使用第二种方案。

    1. dependencies {
    2. compile fileTree(dir: 'libs', include: ['*.jar'])
    3. compile 'com.google.android.support:wearable:+'
    4. compile 'com.google.android.gms:play-services-wearable:+'
    5. }

    要实现以下的布局方法需要用到 'com.google.android.support:wearable' 依赖。

    浏览API reference documentation查看Wearable UI库的类。

    包含在Wearable UI库中的WatchViewStub类允许我们为方形和圆形屏幕指定不同的layout。这个类会在运行时检查屏幕形状并inflate相应的layout。

    为了在我们的应用中使用这个类以应对不同的屏幕形状,我们需要:

    • 添加WatchViewStub作为activity的layout的主元素。
    • 使用rectLayout属性为方形屏幕指定一个layout文件。
    • 使用roundLayout属性为圆形屏幕指定一个layout文件。

    类似下面定义activity的layout:

    在activity中inflate这个layout:

    1. @Override
    2. protected void onCreate(Bundle savedInstanceState) {
    3. super.onCreate(savedInstanceState);
    4. setContentView(R.layout.activity_wear);
    5. }

    然后为方形和圆形屏幕创建不同的layout文件,在这个例子中,我们需要创建res/layout/rect_activity_wear.xmlres/layout/round_activity_wear.xml两个文件。像创建手持应用的layouts一样定义这些layouts,但需要考虑可穿戴设备的限制。系统会在运行时根据屏幕形状来inflate适合的layout。

    我们为方形或圆形屏幕定义的layouts在WatchViewStub检测到屏幕形状之前不会被inflate,所以你的app不能立即取得它们的view。为了取得这些view,需要在我们的activity中设置一个listener,当屏幕适配的layout被inflate时会通知这个listener:

    包含在Wearable UI库中的BoxInsetLayout类继承自 FrameLayout,该类允许我们定义一个同时适配方形和圆形屏幕的layout。这个类适用于需要根据屏幕形状插入间隔的情况,并让我们容易地将view对其到屏幕的边缘或中心。

    Figure 2. 在圆形屏幕上的窗口间隔

    figure 2中灰色的部分显示了在应用了窗口间隔之后,BoxInsetLayout自动将它的子view放置在圆形屏幕的区域。为了显示在这个区域内,子view需要用下面这些值指定 layout_box属性:

    • all将所有子view的内容定位在figure 2的灰色区域里面。

    在方形屏幕上,窗口间隔为0,layout_box属性会被忽略。

    定义Layouts - 图3

    Figure 3. 同一个layout工作在方形和圆形屏幕上

    在figure 3中展示的layout使用了BoxInsetLayout,该layout在圆形和方形屏幕上都可以使用:

    1. <android.support.wearable.view.BoxInsetLayout
    2. xmlns:android="http://schemas.android.com/apk/res/android"
    3. xmlns:app="http://schemas.android.com/apk/res-auto"
    4. android:background="@drawable/robot_background"
    5. android:layout_height="match_parent"
    6. android:layout_width="match_parent"
    7. android:padding="15dp">
    8. <FrameLayout
    9. android:layout_width="match_parent"
    10. android:layout_height="match_parent"
    11. android:padding="5dp"
    12. app:layout_box="all">
    13. <TextView
    14. android:gravity="center"
    15. android:layout_width="match_parent"
    16. android:textColor="@color/black" />
    17. <ImageButton
    18. android:background="@null"
    19. android:layout_gravity="bottom|left"
    20. android:layout_height="50dp"
    21. android:layout_width="50dp"
    22. android:src="@drawable/ok" />
    23. <ImageButton
    24. android:background="@null"
    25. android:layout_gravity="bottom|right"
    26. android:layout_height="50dp"
    27. android:layout_width="50dp"
    28. android:src="@drawable/cancel" />
    29. </FrameLayout>
    30. </android.support.wearable.view.BoxInsetLayout>

    注意layout中的这些部分:

    • android:padding="15dp"

    这行指定了BoxInsetLayout元素的padding。因为在圆形设备上窗口间隔大于15dp,所以这个padding只应用在方形屏幕上。

    • android:padding="5dp"

    这行指定内部FrameLayout元素的padding。这个padding同时应用在方形和圆形屏幕上。在方形屏幕上,按钮和窗口间隔总的padding是20dp(15+5),在圆形屏幕上是5dp。

    这行声明FrameLayout和它的子views都被放在圆形屏幕上窗口间隔定义的区域里。这行在方形屏幕上没有任何效果。