Wear で全画面表示のアクティビティを終了する

ユーザーは、左から右にスワイプすることによって Wear OS のアクティビティを終了できます。アプリに水平スクロール機能がある場合、ユーザーはコンテンツの端で、左から右にスワイプすることによって終了できます。また、電源ボタンを押すことによってもウォッチフェイスに戻れます。

スワイプして閉じる操作

ユーザーは左から右にスワイプすることによって現在の画面を閉じることができます。そのため、以下を使用することをおすすめします。

  • 縦型レイアウト
  • コンテンツ コンテナ

また、水平方向のスワイプ操作はアプリに含めないことをおすすめします。

アクティビティを閉じる

アクティビティは、スワイプして閉じる操作を自動的にサポートします。アクティビティを左から右にスワイプすると、アクティビティが終了し、アプリがバックスタックに移動します。

フラグメントを閉じる

スワイプして閉じる操作をサポートするには、フラグメントを含むビューを SwipeDismissFrameLayout クラスにラップする必要があります。フラグメントを使用するかどうか決定する際に考慮してください。以下に示すように、SwipeDismissFrameLayout クラスを使用します。

Kotlin

class SwipeDismissFragment : Fragment() {
    private val callback = object : SwipeDismissFrameLayout.Callback() {
        override fun onSwipeStarted(layout: SwipeDismissFrameLayout) {
            // Optional
        }

        override fun onSwipeCanceled(layout: SwipeDismissFrameLayout) {
            // Optional
        }

        override fun onDismissed(layout: SwipeDismissFrameLayout) {
            // Code here for custom behavior, such as going up the
            // back stack and destroying the fragment but staying in the app.
        }
    }

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View =
            SwipeDismissFrameLayout(activity).apply {

                // If the fragment should fill the screen (optional), then in the layout file,
                // in the androidx.wear.widget.SwipeDismissFrameLayout element,
                // set the android:layout_width and android:layout_height attributes
                // to "match_parent".

                inflater.inflate(
                        R.layout.swipe_dismiss_frame_layout,
                        this,
                        false
                ).also { inflatedView ->
                    addView(inflatedView)
                }
                addCallback(callback)
            }
}

Java

public class SwipeDismissFragment extends Fragment {
  private final Callback callback =
    new Callback() {
      @Override
        public void onSwipeStart() {
          // Optional
        }

        @Override
        public void onSwipeCancelled() {
          // Optional
        }

        @Override
        public void onDismissed(SwipeDismissFrameLayout layout) {
          // Code here for custom behavior, such as going up the
          // back stack and destroying the fragment but staying in the app.
        }
      };

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    SwipeDismissFrameLayout swipeLayout = new SwipeDismissFrameLayout(getActivity());

    // If the fragment should fill the screen (optional), then in the layout file,
    // in the androidx.wear.widget.SwipeDismissFrameLayout element,
    // set the android:layout_width and android:layout_height attributes
    // to "match_parent".

    View inflatedView = inflater.inflate(R.layout.swipe_dismiss_frame_layout, swipeLayout, false);
    swipeLayout.addView(inflatedView);
    swipeLayout.addCallback(callback);

    return swipeLayout;
    }
}

注: アクティビティでフラグメントを使用する場合、スワイプして閉じる操作をサポートするため、FragmentManager.replace ではなく FragmentManager.add を使用してください。これにより、スワイプされた前のフラグメントが一番上のフラグメントの下に表示されるようになります。

水平スクロールが可能なビュー

パンをサポートする地図を含むビューなどでは、ユーザー インターフェースによって水平方向のスワイプが妨げられることがあります。このようなシナリオでは、次の 2 つの選択肢があります。

  • バックスタックが短い場合、ユーザーは電源ボタンを押すことによってアプリを閉じ、ウォッチフェイスのホーム画面に戻ることができます。
  • ユーザーをバックスタックに移動させたい場合は、エッジスワイプをサポートする SwipeDismissFrameLayout オブジェクトにビューをラップできます。canScrollHorizontally() を呼び出した結果、ビューまたはその子ビューが true を返すと、エッジスワイプが有効化されます。エッジスワイプでは、ユーザーはビューの任意の位置ではなく、画面の左端 10% の領域からスワイプしてビューを閉じることができます。

次の例は、SwipeDismissFrameLayout オブジェクト内でビューをラップする方法を示しています。

<androidx.wear.widget.SwipeDismissFrameLayout
    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:id="@+id/swipe_dismiss_root" >

    <TextView
        android:id="@+id/test_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Swipe me to dismiss me." />
</androidx.wear.widget.SwipeDismissFrameLayout>

Kotlin

activity?.findViewById<SwipeDismissFrameLayout>(R.id.swipe_dismiss_root)?.apply {
    addCallback(object : SwipeDismissFrameLayout.Callback() {

        override fun onDismissed(layout: SwipeDismissFrameLayout) {
            layout.visibility = View.GONE
        }
    })
}

Java

SwipeDismissFrameLayout testLayout =
    (SwipeDismissFrameLayout) activity.findViewById(R.id.swipe_dismiss_root);
testLayout.addCallback(new SwipeDismissFrameLayout.Callback() {
    @Override
    public void onDismissed(SwipeDismissFrameLayout layout) {
        layout.setVisibility(View.GONE);
    }
  }
);

非推奨: スワイプして閉じる操作を無効にする

一般的に、スワイプして閉じる操作を無効にすることはおすすめしません。ユーザーはスワイプするとすべての画面が閉じられると考えています。例外的なケースとして、次のコードサンプルに示すように、スタイル リソースでデフォルトのテーマを拡張し、android:windowSwipeToDismiss 属性を false に設定できます。

<resources>
  <style name="AppTheme" parent="@android:style/Theme.DeviceDefault">
    <item name="android:windowSwipeToDismiss">false</item>
  </style>
</resources>

さらに、電源ボタンを押すことによってアプリを終了できることを、ユーザーがアプリを初めて使用するときに伝えることができます。

電源ボタンによる終了

物理的な電源ボタンを押すと、電源キーのイベントが送信されます。このため通常は、電源ボタンを [戻る] ボタンとして、または移動用に使用することはできません。

電源ボタンを押すと、ウォッチフェイスのホーム画面に戻ります。ただし、次の 2 つの例外があります。

  • 手書き入力認識画面などのインプット メソッド エディタ(IME)の操作中にボタンを押すと、IME が終了し、アプリに戻ります。
  • ウォッチフェイスが表示されているときにユーザーがハードウェア ボタンを押すと、アプリ ランチャーが起動します。

注: 電源ボタンが押されたとき、Activity クラスの isFinishing() メソッドは true を返さず、キーイベントをインターセプトすることもできません。

詳細については、ナビゲーションをご覧ください。