Sair de atividades em tela cheia no Wear

Os usuários podem sair de uma atividade do Wear OS deslizando da esquerda para a direita. Se o app tiver rolagem horizontal (por exemplo, o tipo de rolagem disponível em um app que contenha mapas), os usuários sairão dele navegando até a borda do conteúdo e, em seguida, deslizando da esquerda para a direita.

Ao pressionar o botão liga/desliga, os usuários voltarão para o mostrador do relógio.

Confira os seguintes recursos relacionados:

Gesto de deslizar para dispensar

Os usuários deslizam da esquerda para a direita para fechar a tela atual. Portanto, é recomendável que você use o seguinte:

Também é recomendável que seu app não contenha gestos de deslizamento horizontais.

Dispensar uma atividade

Uma atividade é compatível automaticamente com o recurso de deslizar para dispensar. Deslizar uma atividade da esquerda para a direita faz com que ela seja dispensada, e o app navegará para a pilha de retorno.

Fragmentos

Você pode envolver uma visualização que contenha fragmentos na classe SwipeDismissFrameLayout da seguinte maneira:

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 android.support.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 android.support.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;
        }
    }
    

Observação: a classe SwipeDismissFrameLayout substitui uma classe obsoleta semelhante na Biblioteca de Suporte de Wearables.

Visualizações roláveis horizontais

Em alguns casos, como em uma visualização que contém um mapa compatível com movimento panorâmico, a interface do usuário não impede o deslizamento horizontal. Nessa situação, há duas opções:

  • Se a pilha de retorno for curta, o usuário poderá dispensar o app e retornar à tela inicial (mostrador do relógio) pressionando o botão liga/desliga.
  • Se você quiser que o usuário vá para a pilha de retorno, envolva a visualização em um objeto SwipeDismissFrameLayout, que é compatível com o deslizamento de borda. O deslizamento de borda é ativado quando a visualização ou as filhas delas retornam true de uma chamada canScrollHorizontally(). O deslizamento de borda permite que o usuário dispense a visualização deslizando a partir do lado mais à esquerda da tela (atualmente definido como 10% da largura da tela) e não apenas em qualquer lugar da visualização.

Para envolver uma visualização em um objeto SwipeDismissFrameLayout, consulte os seguintes exemplos:

XML para um arquivo de layout

    <android.support.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." />
    </android.support.wear.widget.SwipeDismissFrameLayout>
    

Snippet de código

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);
        }
      }
    );
    

Geralmente não recomendado: desativar a ação de deslizar para dispensar

Normalmente, a desativação da opção "deslizar para dispensar" não é recomendada porque o usuário espera dispensar qualquer tela deslizando o dedo. Em um caso excepcional, você pode estender o tema padrão (em um recurso de estilo) e configurar o atributo android:windowSwipeToDismiss como false:

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

Você pode, então, informar aos usuários (no primeiro uso do app) que eles podem sair do app pressionando o botão liga/desliga.

Comportamento de dispensar antes do Wear 2.0

Antes do Wear 2.0, a classe DismissOverlayView era usada para implementar um toque longo para o usuário dispensar um app. A classe DismissOverlayView não deve mais ser usada.

Além disso, o toque longo para dispensar um app não é mais recomendável. Não implemente a função de toque longo para dispensar atividades em tela cheia (atividades panorâmicas ou imersivas, como o Google Maps).

Dispensar pelo botão liga/desliga

Pressionar o botão físico liga/desliga envia um evento de tecla Liga/desliga. Portanto, você não pode usar o botão liga/desliga como botão "Voltar" ou para a navegação em geral.

Quando pressionado, o botão liga/desliga retorna o usuário para a tela inicial (mostrador do relógio). Há duas exceções:

  • Se o usuário estiver em um IME (um Editor de método de entrada, por exemplo, uma tela de reconhecimento de escrita à mão) e pressionar o botão, o IME será fechado e o usuário será levado de volta ao app.
  • Se o usuário estiver no mostrador do relógio, pressionar o botão físico abrirá o inicializador de apps.

Observe que quando o botão liga/desliga é pressionado, o método isFinishing() da classe Activity não retorna true (nem você pode interceptar o evento de tecla).