Quais APIs são usadas para desenhar sobre outros aplicativos (como os Chat Heads do Facebook)?

226

Como o Facebook cria os Chat Heads no Android? Qual é a API para criar as visualizações flutuantes sobre todas as outras visualizações?

Daniel A. White
fonte
6
Este aplicativo tem também "cabeças de bate-papo" play.google.com/store/apps/details?id=com.ninja.sms
Oli
11
Se você está procurando um exemplo, consulte github.com/marshallino16/FloatingNotification
marshallino16
5
Você pode encontrar uma demonstração e uma biblioteca simples aqui: github.com/ericbhatti/floaties Usando esta biblioteca, você pode criar janelas flutuantes usando apenas 2 linhas.
Eric B.

Respostas:

217

Este aqui :

Permite que um aplicativo abra janelas usando o tipo TYPE_SYSTEM_ALERT, mostrado no topo de todos os outros aplicativos. Muito poucos aplicativos devem usar esta permissão; essas janelas destinam-se à interação no nível do sistema com o usuário.

Valor constante: "android.permission.SYSTEM_ALERT_WINDOW"

// EDIT: O código completo aqui :

public class ChatHeadService extends Service {

  private WindowManager windowManager;
  private ImageView chatHead;

  @Override public IBinder onBind(Intent intent) {
    // Not used
    return null;
  }

  @Override public void onCreate() {
    super.onCreate();

    windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

    chatHead = new ImageView(this);
    chatHead.setImageResource(R.drawable.android_head);

    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.TYPE_PHONE,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT);

    params.gravity = Gravity.TOP | Gravity.LEFT;
    params.x = 0;
    params.y = 100;

    windowManager.addView(chatHead, params);
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    if (chatHead != null) windowManager.removeView(chatHead);
  }
}

Não se esqueça de iniciar o serviço de alguma forma:

startService(new Intent(context, ChatHeadService.class));

.. E adicione este serviço ao seu manifesto.

Waza_Be
fonte
4
Há coisas mais estranhas, eu acho. Que tal lidar com entradas fora da "cabeça" e com capacidade de arrastar? Eu acho que você precisaria pelo menos de FLAG_NOT_TOUCH_MODAL , além de alguma lógica inteligente para atualizar os atributos do Windows (por exemplo, movê-lo) enquanto o arrasta.
Delyan
2
em que como remover cabeças de bate-papo?
Nirav Mehta
6
Pensava que vale a pena mencionar um SDK I desenvolvido para criar flutuante UI: www.tooleap.com
Arik
@NiravMehta Você é capaz de remover as cabeças de bate-papo?
KK_07k11A0585
como remover a margem de head.Because bate-papo na saída do código acima do círculo ter algum espaço do border.In Facebook a bolha não tem esse espaço
Debugger
51

Como regra, as atividades do Android são de tela cheia, UIs conceitualmente dedicadas que levam toda a interação. Existem algumas exceções para isso. Para começar, existem caixas de diálogo pop-up que não preenchem a tela. Outro é o brinde do Android, que é um pop-up não interativo - você não pode tocá-lo e, se tentar, irá para o que estiver por baixo.

Você também pode criar suas próprias interfaces de usuário especiais. Você pode adicionar visualizações diretamente ao WindowManager, especificando um sinalizador de tipo. O Chat Heads provavelmente usa TYPE_PHONE . Existem alguns tipos semelhantes, mas o objetivo é o mesmo: sobreposições de propósito especial que podem aparecer por cima de qualquer outra coisa sem que o aplicativo pai aparentemente esteja presente.

Isso só leva você até agora, por causa de problemas com a interação. No início, sua sobreposição absorverá toda a interação, para que a cabeça não apenas receba eventos, mas também bloqueie a interação com tudo que está por baixo.

Você configura esse comportamento usando o LayoutParams . FLAG_NOT_TOUCH_MODALsignifica que os eventos fora da sua área de exibição vão para as UIs subjacentes. Agora você verá que funciona, mas outras coisas ruins ainda acontecem, como os botões voltar / menu não são direcionados para aplicativos, além de nenhum teclado. Para resolver o que você precisa FLAG_NOT_FOCUSABLE.

Você também obtém um efeito colateral do bit não focalizável, que não é mais uma boa interação com a sobreposição, por exemplo, pressionamentos de botão. No entanto, você pode obter alguns eventos básicos de toque, nos quais sempre é possível fazer matemática, e isso provavelmente é suficiente para os Chat Heads. Esteja ciente de que isso deixa você sozinho em muitas áreas, como animação da interface do usuário.

Uma boa visão geral dos detalhes, inclusive permitindo o consumo seletivo de interação, pode ser encontrada neste encadeamento StackOverflow . Em particular, um dos links de resposta o levará até aqui , que é um bom exemplo de projeto. Observe que o ICS mudou como isso funciona um pouco, mas os threads explicam isso.

Isso é tudo sobre API pública, mas não parece realmente algo comum que devíamos estar fazendo normalmente. A documentação está repleta de referências a comportamentos especiais de aplicativos do sistema e por boas razões; e se todo mundo fizesse isso?

Rob Pridham
fonte
Posso bloquear de alguma forma as alterações de orientação para essas visualizações? Se a atividade subjacente muda de orientação, minha visão também muda sua orientação.
MG
1
Não. A mudança de orientação é para todo o dispositivo, não apenas para a atividade.
Rob Pridham
7

As cabeças elásticas proporcionam um comportamento baseado nas molas das cabeças de bate-papo fora da caixa. Tudo o que você precisa definir é o desenho para o cabeçalho do bate-papo e o fragmento para abrir assim que o cabeçalho for clicado. As cabeças do bate-papo são recolhidas quando minimizadas e seguem o dedo quando arrastadas.

O projeto inclui um aplicativo de demonstração que demonstra todas as funcionalidades incorporadas. Para usá-lo, você precisa adicioná-lo às dependências do gradle.

compile 'com.flipkart.springyheads:library:0.9.6'
Kiran Kumar
fonte
Ei, @KiranKumar, você criou uma biblioteca muito clara. Eu simplesmente adoro. Estou tentando aprender vários aspectos dessa biblioteca. Estou tentando executá-la fora da janela do aplicativo. De alguma forma, sou um pouco bem-sucedido em fazer que sim .. Mas, o problema surge quando eu clico no cabeçalho do bate-papo fora da janela do aplicativo .. o fragmento não poderia abrir e retornar java.lang.OutOfMemoryError .. se fosse possível do seu lado para dá-me alguma forma através deste .. será bom grado honrado ..
ArrayStack
@arraystack agora você pode executá-lo em um serviço. Verifique a lista se filiais no GitHub repo
Kiran Kumar
@KiranKumar Obrigado, O problema com a nova lib é a permissão do Draw over application na versão Marshmallow
arraystack