¿Cómo creo una superposición de ayuda como la que se ve en algunas aplicaciones de Android e ICS?

93

Quiero crear superposiciones de ayuda como las que ves cuando ICS se carga por primera vez o en aplicaciones como ES File Explorer o Apex Launcher (hay más, pero no puedo pensar en ellas en este momento). ¿Es esto solo un diseño relativo con una vista encima de la otra? No he podido encontrar ningún código de muestra para hacer tal cosa. ¿Alguien sabe cómo se hace esto o tiene alguna idea?

Explorador de archivos ES Explorador de archivos ES

ssuperz28
fuente

Respuestas:

84

Supongamos que normalmente llamaría setContentView(R.layout.main), pero en la primera ejecución, desea tener esta superposición.

Paso # 1: Cree un FrameLayoutcódigo en Java y páselo a setContentView().

Paso # 2: Úselo LayoutInflaterpara inflar R.layout.mainen el FrameLayout.

Paso # 3: Úselo LayoutInflaterpara inflar la superposición en el FrameLayout.

Paso # 4: Cuando el usuario toca el botón (o lo que sea) para descartar la superposición, llame removeView()para eliminar la superposición del FrameLayout.

Dado que la superposición es un elemento secundario posterior de FrameLayout, flotará sobre el contenido de R.layout.main.

CommonsWare
fuente
6
@ ssuperz28: Sí, bueno, excepto por las puntas de flecha y la burbuja dibujadas a mano. Estás solo para esos. :-)
CommonsWare
No sé si lograste hacer lo que querías, pero aquí hay otra alternativa. stackoverflow.com/questions/8841240/… Si mantienes la solución dada por CommonsWare, lo único que se me ocurre para configurar las flechas, es definir el FrameLayout de instrucciones con una resourceImage o backgroundImage ya con la imagen con las flechas (y transparencia).
Edison Santos
1
¿Hay alguna manera de hacer esto pero hacerlo en relación con la posición de los niños que están debajo del FrameLayout?
4gus71n
@CommonsWare, señor, ¿esto funcionaría independientemente del dispositivo que sea?
Rat-a-tat-a-tat Ratatouille
2
@ user3364963: ajusta dinámicamente las posiciones de las cosas. Mi respuesta fue algo simplificada. Supongo que determinan la posición de los elementos a resaltar y ajustan las coordenadas de las "marcas de entrenador". Una costumbre ViewGrouppara la capa de "marcas de entrenador" podría manejar eso, y hay bibliotecas (por ejemplo, ShowcaseView) que ofrecen implementaciones enlatadas de ese patrón.
CommonsWare
80

La "marca del entrenador" es "Superposición de ayuda" en la charla UX :-)

coach_mark.xml es su diseño de marca de entrenador

coach_mark_master_view es el ID de la vista más alta (raíz) en coach_mark.xml

public void onCoachMark(){

    final Dialog dialog = new Dialog(this);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
    dialog.setContentView(R.layout.coach_mark);
    dialog.setCanceledOnTouchOutside(true);
    //for dismissing anywhere you touch
    View masterView = dialog.findViewById(R.id.coach_mark_master_view);
    masterView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            dialog.dismiss();
        }
    });
    dialog.show();
}

Añadiendo una muestra de coach_mark.xml (a esta excelente solución proporcionada por Oded Breiner), por lo que es fácil para las personas copiar y pegar para ver el ejemplo de trabajo rápidamente.

Muestra de coach_mark.xml aquí, cambie -> drawable / coach_marks a su imagen:

coach_mark.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/coach_mark_master_view">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
         <ImageView
             android:id="@+id/coach_marks_image"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_centerInParent="true"
             android:layout_gravity="center_horizontal"
             android:src="@drawable/coach_marks" />
    </RelativeLayout>
</LinearLayout>

Y, opcionalmente, use este tema para eliminar el relleno:

<style name="WalkthroughTheme" parent="Theme.AppCompat">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>
Oded Breiner
fuente
Hola, ¿cómo puedes estirar este diálogo para que coincida con la pantalla? De la documentación A dialog is a small window that prompts [...]. A dialog does not fill the screen and is normally used for modal events [...].,. Si utilizo este código, obtengo mi vista maestra comprimida en una pequeña porción de la pantalla. Si configuro android:layout_width="640dp" android:layout_height="480dp"(es decir, los valores reales de la pantalla con la que estoy probando), funciona correctamente. (por supuesto, esta no es una solución factible)
ocramot
@ocramot: el ejemplo anterior debería ser de pantalla completa debido a match_parent y Window.FEATURE_NO_TITLE
Oded Breiner
Entonces debe haber algún otro problema, porque lo veo de una manera diferente
ocramot
1
Sé que esto tiene al menos unos meses, pero ¿alguna vez se resolvió esa pregunta de pantalla completa?
cbhedd
3
Para aquellos que no saben cómo configurar el tema del diálogo, simplemente cree una instancia del diálogo así:new Dialog(getContext(), R.style.WalkthroughTheme);
w3bshark
4

Puedes hacerlo bastante rápido. Agrega, por ejemplo, un LinearLayout donde coloca una imagen con alfa que corresponde a su información de ayuda y lo que desea dibujar como una superposición. En su xml de su actividad, coloca este diseño en un RelativeLayout después del diseño de su actividad con la visibilidad Gone. Cuando desee dibujar la información de ayuda, solo necesita configurar esta visibilidad como visible.

Espero, lo tengo claro, si tiene alguna pregunta, será un placer responderla.

FUBU
fuente
Gracias por tu contribución. Así es como me imaginé que se haría. Sin embargo, debo dar crédito a la respuesta a continuación, ya que esa es la forma en que lo voy a construir. Parece más manejable y no tengo que alterar el diseño de mi actividad principal.
ssuperz28
1

Vea mi otra respuesta sobre cómo mostrar programáticamente un diseño de superposición sobre la actividad actual. El layout.xml de la actividad no necesita saber nada sobre la máscara de superposición. Puede colocar una superposición semitransparente, cubrir solo una parte de la pantalla, una o más vistas de texto y botones ... ¿Cómo superponer un botón mediante programación?

  • crear res / layout / paused.xml plantilla RelativeLayout o usar cualquier diseño de nivel superior
  • crear una función para mostrar la máscara de superposición
  • la clave es obtener el control de layout.xml, usar la clase LayoutInflater para analizar xml para ver el objeto, agregar una vista de superposición a la estructura de diseño actual
  • Mi ejemplo usa un temporizador para destruir el objeto de superposición eliminándolo por completo de la estructura de la vista. Esto es probablemente lo que también desea deshacerse de él sin dejar rastro.

Mi objetivo era que las actividades principales no fueran conscientes de ningún aspecto de superposición, las superposiciones iban y venían, muchas superposiciones diferentes, aún podían usar archivos de texto overlay1.xml como plantilla, y el contenido debería actualizarse mediante programación. Hago más o menos lo que CommonsWare nos dijo que mi publicación muestra el código del programa real para comenzar.

descargo de responsabilidad: OPs "Gracias por sus comentarios. Así es como me imaginé que se haría. Tengo que dar crédito a la respuesta a continuación". El comentario no significa mi respuesta, sino la respuesta de CommonsWare. Stackoverflow ha cambiado el orden de las publicaciones.

Quien
fuente