Android 定義Layouts

2018-08-02 17:51 更新

編寫: roya 原文:https://developer.android.com/training/wearables/ui/layouts.html

可穿戴設(shè)備使用與手持Android設(shè)備同樣的布局技術(shù),但需要有具體的約束來設(shè)計。不要以一個手持app的角度開發(fā)功能和UI并期待得到一個好的體驗。關(guān)于如何設(shè)計優(yōu)秀的可穿戴應(yīng)用的更多信息,請閱讀Android Wear Design Guidelines

當(dāng)為Android Wear應(yīng)用創(chuàng)建layout時,我們需要同時考慮方形和圓形屏幕的設(shè)備。在圓形Android Wear設(shè)備上所有放置在靠近屏幕邊角的內(nèi)容可能會被剪裁掉,所以為方形屏幕設(shè)計的layouts在圓形設(shè)備上不能很好地顯示出來。對這類問題的示范請查看這個視頻Full Screen Apps for Android Wear。

舉個例子,figure 1展示了下面的layout在圓形和方形屏幕上的效果:

Figure 1. 為方形屏幕設(shè)計的layouts在圓形設(shè)備上不能很好顯示的示范

<LinearLayout 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"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_square" />
</LinearLayout>

上述范例的文本沒有正確地顯示在圓形屏幕上。

Wearable UI庫為這個問題提供了兩種不同的解決方案:

  • 為圓形和方形屏幕定義不同的layouts。我們的app會在運行時檢查設(shè)備屏幕形狀并inflate正確的layout。

  • 用一個包含在庫里面的特殊layout同時適配方形和圓形設(shè)備。這個layout會在不同形狀的設(shè)備屏幕窗口中插入不同的間隔。

當(dāng)我們希望應(yīng)用在不同形狀的屏幕上看起來不同時,一般會使用第一種方案。當(dāng)我們希望用一個相似的layout在兩種屏幕上且在圓形屏幕上沒有視圖被邊緣剪裁時,可以使用第二種方案。

添加Wearable UI庫

當(dāng)我們使用Android Studio的工程向?qū)r,Android Studio會自動地在wear模塊中包含Wearable UI庫。為了在工程中編譯到這個庫,確保 Extras > Google Repository 包已經(jīng)被安裝在Android SDK manager里,下面的依賴被包含在wear模塊的build.gradle文件中:

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

要實現(xiàn)以下的布局方法需要用到 'com.google.android.support:wearable' 依賴。

瀏覽API reference documentation查看Wearable UI庫的類。

為方形和圓形屏幕指定不同的Layouts

包含在Wearable UI庫中的WatchViewStub類允許我們?yōu)榉叫魏蛨A形屏幕指定不同的layout。這個類會在運行時檢查屏幕形狀并inflate相應(yīng)的layout。

為了在我們的應(yīng)用中使用這個類以應(yīng)對不同的屏幕形狀,我們需要:

  • 添加WatchViewStub作為activity的layout的主元素。
  • 使用rectLayout屬性為方形屏幕指定一個layout文件。
  • 使用roundLayout屬性為圓形屏幕指定一個layout文件。

類似下面定義activity的layout:

<android.support.wearable.view.WatchViewStub
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/watch_view_stub"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:rectLayout="@layout/rect_activity_wear"
    app:roundLayout="@layout/round_activity_wear">
</android.support.wearable.view.WatchViewStub>

在activity中inflate這個layout:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_wear);
}

然后為方形和圓形屏幕創(chuàng)建不同的layout文件,在這個例子中,我們需要創(chuàng)建res/layout/rect_activity_wear.xmlres/layout/round_activity_wear.xml兩個文件。像創(chuàng)建手持應(yīng)用的layouts一樣定義這些layouts,但需要考慮可穿戴設(shè)備的限制。系統(tǒng)會在運行時根據(jù)屏幕形狀來inflate適合的layout。

取得layout views

我們?yōu)榉叫位驁A形屏幕定義的layouts在WatchViewStub檢測到屏幕形狀之前不會被inflate,所以你的app不能立即取得它們的view。為了取得這些view,需要在我們的activity中設(shè)置一個listener,當(dāng)屏幕適配的layout被inflate時會通知這個listener:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_wear);

    WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
        @Override public void onLayoutInflated(WatchViewStub stub) {
            // Now you can access your views
            TextView tv = (TextView) stub.findViewById(R.id.text);
            ...
        }
    });
}

使用感知形狀的Layout

包含在Wearable UI庫中的BoxInsetLayout類繼承自 FrameLayout,該類允許我們定義一個同時適配方形和圓形屏幕的layout。這個類適用于需要根據(jù)屏幕形狀插入間隔的情況,并讓我們?nèi)菀椎貙iew對其到屏幕的邊緣或中心。

Figure 2. 在圓形屏幕上的窗口間隔

figure 2中灰色的部分顯示了在應(yīng)用了窗口間隔之后,BoxInsetLayout自動將它的子view放置在圓形屏幕的區(qū)域。為了顯示在這個區(qū)域內(nèi),子view需要用下面這些值指定 layout_box屬性:

  • 一個topbottom、leftright的組合。比如,"left|top"將子view的左和上邊緣定位在figure 2的灰色區(qū)域里面。
  • all將所有子view的內(nèi)容定位在figure 2的灰色區(qū)域里面。

在方形屏幕上,窗口間隔為0,layout_box屬性會被忽略。

Figure 3. 同一個layout工作在方形和圓形屏幕上

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

<android.support.wearable.view.BoxInsetLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="@drawable/robot_background"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:padding="15dp">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="5dp"
        app:layout_box="all">

        <TextView
            android:gravity="center"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:text="@string/sometext"
            android:textColor="@color/black" />

        <ImageButton
            android:background="@null"
            android:layout_gravity="bottom|left"
            android:layout_height="50dp"
            android:layout_width="50dp"
            android:src="@drawable/ok" />

        <ImageButton
            android:background="@null"
            android:layout_gravity="bottom|right"
            android:layout_height="50dp"
            android:layout_width="50dp"
            android:src="@drawable/cancel" />
    </FrameLayout>
</android.support.wearable.view.BoxInsetLayout>

注意layout中的這些部分:

  • android:padding="15dp"

這行指定了BoxInsetLayout元素的padding。因為在圓形設(shè)備上窗口間隔大于15dp,所以這個padding只應(yīng)用在方形屏幕上。

  • android:padding="5dp"

這行指定內(nèi)部FrameLayout元素的padding。這個padding同時應(yīng)用在方形和圓形屏幕上。在方形屏幕上,按鈕和窗口間隔總的padding是20dp(15+5),在圓形屏幕上是5dp。

  • app:layout_box="all"

這行聲明FrameLayout和它的子views都被放在圓形屏幕上窗口間隔定義的區(qū)域里。這行在方形屏幕上沒有任何效果。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號