在 Wear 上退出全屏活动

尝试 Compose 方式
Wear OS 上的 Jetpack Compose 是 Wear OS 推荐的 UI 工具包。

用户可以通过从左向右滑动来退出 Wear OS 活动。如果应用有水平滚动,用户则需要导航到内容的边缘,然后从左向右滑动才能退出。按下电源按钮也会将用户返回到表盘。

滑动关闭手势

用户从左向右滑动以关闭当前屏幕。因此,我们建议您使用以下方式:

  • 垂直布局
  • 内容容器

我们还建议您的应用不要包含水平滑动手势。

关闭活动

活动自动支持滑动关闭。从左向右滑动活动会导致活动被关闭,应用会沿返回堆栈向下导航。

关闭 fragment

要在 fragment 中支持滑动关闭,您必须将包含 fragment 的视图包装在 SwipeDismissFrameLayout 类中。在决定是否使用 fragment 时,请考虑这一点。使用 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;
    }
}

注意:当您在活动中使用 fragment 时,请使用 FragmentManager.add 而不是 FragmentManager.replace 来支持滑动关闭手势。这有助于确保您的上一个 fragment 在顶部 fragment 被滑走时在其下方渲染。

水平可滚动视图

在某些情况下,例如在包含支持平移的地图的视图中,用户界面无法阻止水平滑动。在这种情况下,有两种选择:

  • 如果返回堆栈很短,用户可以通过按电源按钮关闭应用并返回到表盘主屏幕。
  • 如果您希望用户沿返回堆栈向下导航,可以将视图包装在支持边缘滑动的 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>

然后,您可以在用户首次使用您的应用时告知他们可以通过按下电源按钮退出应用。

通过电源按钮关闭

按下物理电源按钮会发送电源键事件。因此,您不能将电源按钮用作返回按钮或用于一般导航。

按下时,电源按钮会将用户返回到表盘主屏幕。有两个例外:

  • 如果用户正在使用输入法编辑器 (IME),例如手写识别屏幕,按下按钮会关闭 IME 并将用户返回到应用。
  • 如果用户在表盘上,按下硬件按钮会打开应用启动器。

请注意,当电源按钮被按下时,Activity 类的 isFinishing() 方法不会返回 true,并且您无法拦截键事件。

如需了解更多信息,请参阅导航