Como faço para criar uma sobreposição de ajuda como você vê em alguns aplicativos Android e ICS?

93

Estou querendo criar sobreposições de ajuda como as que você vê quando o ICS é carregado pela primeira vez ou em aplicativos como ES File Explorer ou Apex Launcher (há mais, mas não consigo pensar neles agora). Este é apenas um layout relativo com uma visualização posicionada sobre a outra? Não consegui encontrar nenhum código de amostra para fazer uma coisa dessas. Alguém sabe como isso é feito ou tem alguma ideia?

ES File Explorer ES File Explorer

ssuperz28
fonte

Respostas:

84

Vamos supor que você normalmente chamaria setContentView(R.layout.main), mas na primeira execução, você deseja ter essa sobreposição.

Etapa 1: Crie um FrameLayoutem código Java e passe-o para setContentView().

Etapa # 2: use LayoutInflaterpara inflar R.layout.mainno FrameLayout.

Etapa # 3: use LayoutInflaterpara inflar a sobreposição no FrameLayout.

Etapa 4: quando o usuário tocar no botão (ou qualquer outro) para dispensar a sobreposição, chame removeView()para remover a sobreposição do FrameLayout.

Como a sobreposição é filha posterior de FrameLayout, ela flutuará sobre o conteúdo de R.layout.main.

CommonsWare
fonte
6
@ ssuperz28: Sim, bem, exceto pelas pontas de flecha e bolhas desenhadas à mão. Você está sozinho para isso. :-)
CommonsWare
Não sei se você conseguiu fazer o que queria, mas aqui está outra alternativa. stackoverflow.com/questions/8841240/… Se você mantiver a solução fornecida por CommonsWare, a única coisa que me ocorre para definir as setas, é definir o FrameLayout das instruções com um resourceImage ou backgroundImage já com a imagem com as setas (e transparência).
Edison Santos
1
Existe uma maneira de fazer isso, mas em relação à posição das crianças que estão abaixo do FrameLayout?
4gus71n
@CommonsWare - senhor, isso funcionaria independentemente de qualquer dispositivo que seja?
Rat-a-tat-a-tat Ratatouille,
2
@ user3364963: Ajuste dinamicamente a posição das coisas. Minha resposta foi um tanto simplificada. Presumo que eles determinem a posição dos elementos a serem destacados e ajustem as coordenadas das "marcas do treinador". Um costume ViewGrouppara a camada de "marcas de coach" poderia lidar com isso, e há bibliotecas (por exemplo, ShowcaseView) que oferecem implementações enlatadas desse padrão.
CommonsWare
80

"Coach mark" é "Help overlay" no UX talk :-)

coach_mark.xml é o seu layout de marca de coach

coach_mark_master_view é o id da visão superior (raiz) em 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();
}

Adicionando amostra de coach_mark.xml (a esta excelente solução fornecida por Oded Breiner), então é fácil para o ppl copiar e colar para ver o exemplo de trabalho rapidamente.

Amostra de coach_mark.xml aqui, altere o -> drawable / coach_marks para sua imagem:

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>

E, opcionalmente, use este tema para remover o preenchimento:

<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
fonte
Olá, como você pode esticar este diálogo para coincidir com a tela? Da documentação A dialog is a small window that prompts [...]. A dialog does not fill the screen and is normally used for modal events [...].,. Se eu usar esse código, minha visualização principal será compactada em uma pequena parte da tela. Se eu definir android:layout_width="640dp" android:layout_height="480dp"(ou seja, os valores reais da tela com a qual estou testando), ele funcionará corretamente. (claro que esta não é uma solução viável)
ocramot
@ocramot: o exemplo acima deve estar em tela inteira por causa de match_parent e Window.FEATURE_NO_TITLE
Oded Breiner
Então deve haver algum outro problema, porque estou vendo de uma maneira diferente
ocramot
1
Eu sei que isso tem pelo menos alguns meses, mas essa pergunta em tela inteira foi resolvida?
cbhedd de
3
Para aqueles que não sabem como definir o tema da caixa de diálogo, apenas instancie a caixa de diálogo da seguinte forma:new Dialog(getContext(), R.style.WalkthroughTheme);
w3bshark
4

Você pode fazer isso muito rapidamente. Você adiciona, por exemplo, um LinearLayout onde você coloca uma imagem com alfa que corresponde às suas informações de ajuda e o que você deseja desenhar como uma sobreposição. No xml de sua atividade, você coloca este layout em um RelativeLayout após o layout de sua atividade com a visibilidade Gone. Quando você deseja desenhar as informações de ajuda, você só precisa definir essa visibilidade como visível.

Espero, estou claro, se você tiver alguma dúvida, terei o prazer de respondê-la.

FUBUs
fonte
Obrigado pela sua contribuição. É assim que imaginei ser feito. Eu tenho que dar crédito à resposta abaixo, pois é assim que eu vou construir. Parece mais gerenciável e não preciso alterar o layout da minha atividade principal.
ssuperz28
1

Veja minha outra resposta como mostrar programaticamente um layout de sobreposição no topo da atividade atual. O layout.xml da atividade não precisa saber nada sobre a capa de sobreposição. Você pode colocar sobreposição semitransparente, cobrir apenas uma parte da tela, uma ou mais textview e botões nela ... Como sobrepor um botão programamicamente?

  • crie res / layout / paused.xml template RelativeLayout ou use qualquer layout toplevel
  • crie uma função para mostrar a sobreposição
  • A chave é obter o identificador para layout.xml, usar a classe LayoutInflater para analisar o xml para visualizar o objeto, adicionar a visualização de sobreposição à estrutura de layout atual
  • Meu exemplo usa um cronômetro para destruir o objeto de sobreposição, removendo-o completamente da estrutura da visualização. Provavelmente, é isso que você também deseja para se livrar dele sem deixar vestígios.

Meu objetivo era que as atividades principais não soubessem de nenhuma capa de sobreposição, as sobreposições vêm e vão, muitas sobreposições diferentes, ainda capazes de usar arquivos de texto overlay1.xml como modelo, e o conteúdo deve ser atualizado programaticamente. Eu faço praticamente o que CommonsWare nos disse que meu post mostra o código do programa real para começar.

isenção de responsabilidade: OPs "Obrigado por sua contribuição. É assim que imaginei que fosse feito. Devo dar crédito à resposta abaixo" o comentário não significa minha resposta, mas a resposta do CommonsWare. Stackoverflow mudou os pedidos de postagem.

Quem eu
fonte