Estou tentando personalizar InfoWindow
depois de clicar em um marcador com a nova API do Google Maps v2. Quero que pareça no aplicativo de mapas original do Google. Como isso:
Quando estou ImageButton
lá dentro, não está funcionando - o todo InfoWindow
é cortado e não apenas o ImageButton
. Eu li que é porque não existe um em View
si, mas é um instantâneo; portanto, itens individuais não podem ser distinguidos um do outro.
EDIT: Na documentação (graças ao Disco S2 ):
Conforme mencionado na seção anterior, nas janelas de informações, uma janela de informações não é uma Visualização ao vivo, mas a visualização é renderizada como uma imagem no mapa. Como resultado, todos os ouvintes configurados na exibição são desconsiderados e você não pode distinguir entre os eventos de clique em várias partes da exibição. É recomendável não colocar componentes interativos - como botões, caixas de seleção ou entradas de texto - em sua janela de informações personalizadas.
Mas se o Google usá-lo, deve haver alguma maneira de fazê-lo. Alguém tem alguma ideia?
fonte
View.draw(Canvas)
) ... Isso significa que quaisquer alterações subsequentes na visualização não serão refletidas pela janela de informações no mapa. Para atualizar a janela de informações posteriormente Além disso, a janela de informações não respeitará a interatividade típica de uma exibição normal, como eventos de toque ou gestos. No entanto, você pode ouvir um evento de clique genérico em toda a janela de informações, conforme descrito na seção abaixo. ... no seu exemplo é apenas textviewRespostas:
Eu estava procurando uma solução para esse problema, sem sorte, então tive que criar minha própria, que gostaria de compartilhar aqui com você. (Por favor, desculpe meu inglês ruim) (É um pouco louco responder a outro cara tcheco em inglês :-))
A primeira coisa que tentei foi usar uma boa e velha
PopupWindow
. É bem fácil - basta ouvirOnMarkerClickListener
e mostrar um costumePopupWindow
acima do marcador. Alguns outros caras aqui no StackOverflow sugeriram esta solução e ela realmente parece muito boa à primeira vista. Mas o problema com esta solução aparece quando você começa a mover o mapa. Você precisa mudar dePopupWindow
alguma maneira o que é possível (ouvindo alguns eventos onTouch), mas IMHO não pode fazer com que pareça bom o suficiente, especialmente em alguns dispositivos lentos. Se você fizer isso da maneira simples, "pula" de um ponto para outro. Você também pode usar algumas animações para polir esses saltos, mas dessa formaPopupWindow
, sempre estará "um passo atrás" onde deveria estar no mapa, do qual eu simplesmente não gosto.Neste ponto, eu estava pensando em alguma outra solução. Percebi que realmente não preciso de tanta liberdade - para mostrar minhas visualizações personalizadas com todas as possibilidades que as acompanham (como barras de progresso animadas etc.). Eu acho que há uma boa razão pela qual até os engenheiros do Google não fazem dessa maneira no aplicativo Google Maps. Tudo o que preciso é de um ou dois botões no InfoWindow que mostrem um estado pressionado e acionem algumas ações quando clicados. Então, eu vim com outra solução que se divide em duas partes:
Primeira parte:
a primeira parte é conseguir capturar os cliques nos botões para acionar alguma ação. Minha ideia é a seguinte:
MapFragment
(ouMapView
) dentro de um ViewGroup personalizado (o meu é chamado MapWrapperLayout)MapWrapperLayout
dispatchTouchEvent e (se o InfoWindow estiver sendo exibido no momento) primeiro direcione os MotionEvents para o InfoWindow criado anteriormente. Se ele não consumir os MotionEvents (como porque você não clicou em nenhuma área clicável dentro do InfoWindow etc.), então (e somente então) deixou os eventos descerem para a superclasse do MapWrapperLayout, para que eventualmente sejam entregues no mapa.Aqui está o código fonte do MapWrapperLayout:
Tudo isso tornará as visualizações dentro do InfoView "ativas" novamente - os OnClickListeners começarão a ser acionados etc.
Segunda parte: O problema restante é que, obviamente, você não pode ver nenhuma alteração na interface do seu InfoWindow na tela. Para fazer isso, você deve chamar manualmente Marker.showInfoWindow. Agora, se você realizar alguma alteração permanente no InfoWindow (como alterar o rótulo do botão para outra coisa), isso é bom o suficiente.
Mas mostrar um estado pressionado por botão ou algo dessa natureza é mais complicado. O primeiro problema é que (pelo menos) não consegui fazer com que o InfoWindow mostrasse o estado pressionado do botão normal. Mesmo se eu pressionasse o botão por um longo tempo, ele permaneceria pressionado na tela. Eu acredito que isso é algo tratado pela própria estrutura do mapa, que provavelmente garante que não mostre nenhum estado transitório nas janelas de informações. Mas eu posso estar errado, não tentei descobrir isso.
O que fiz foi outro truque desagradável - anexei um
OnTouchListener
no botão e troquei manualmente o plano de fundo quando o botão foi pressionado ou liberado para dois drawables personalizados - um com um botão no estado normal e o outro no estado pressionado. Isso não é muito bom, mas funciona :). Agora pude ver o botão alternando entre os estados normal e pressionado na tela.Ainda existe uma última falha - se você clicar no botão rápido demais, ele não mostra o estado pressionado - ele permanece no estado normal (embora o clique em si seja acionado, o botão "funcionará"). Pelo menos é assim que aparece no meu Galaxy Nexus. Então a última coisa que fiz foi atrasar um pouco o botão no estado pressionado. Isso também é bastante feio e não tenho certeza de como funcionaria em alguns dispositivos mais antigos e lentos, mas suspeito que mesmo a estrutura do mapa faça algo assim. Você pode tentar você mesmo - quando você clicar em todo o InfoWindow, ele permanecerá pressionado por mais algum tempo e os botões normais (novamente - pelo menos no meu telefone). E é assim que funciona mesmo no aplicativo original do Google Maps.
Enfim, escrevi para mim mesma uma classe personalizada que lida com as alterações de estado dos botões e todas as outras coisas que mencionei, então aqui está o código:
Aqui está um arquivo de layout personalizado do InfoWindow que eu usei:
Arquivo de layout de atividade de teste (
MapFragment
estando dentro doMapWrapperLayout
):E, finalmente, o código fonte de uma atividade de teste, que cola tudo isso:
É isso aí. Até agora, só testei isso no meu Galaxy Nexus (4.2.1) e Nexus 7 (também 4.2.1). Vou testá-lo em um telefone Gingerbread quando tiver chance. Uma limitação que encontrei até agora é que você não pode arrastar o mapa de onde está o botão na tela e movê-lo. Provavelmente poderia ser superado de alguma forma, mas por enquanto eu posso viver com isso.
Sei que esse é um truque feio, mas não encontrei nada melhor e preciso tanto desse padrão de design que seria realmente um motivo para voltar ao quadro v1 do mapa (que, aliás. Eu realmente gostaria de evitar para um novo aplicativo com fragmentos etc.). Só não entendo por que o Google não oferece aos desenvolvedores uma maneira oficial de ter um botão no InfoWindows. É um padrão de design tão comum, além disso, esse padrão é usado mesmo no aplicativo oficial do Google Maps :). Entendo os motivos pelos quais eles não podem simplesmente tornar suas visualizações "vivas" no InfoWindows - isso provavelmente prejudicaria o desempenho ao mover e rolar o mapa. Mas deve haver alguma maneira de obter esse efeito sem usar visualizações.
fonte
view.setBackground(bgDrawablePressed);
porif (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { view.setBackgroundDrawable(bgDrawablePressed); }else{ view.setBackground(bgDrawablePressed); }
para funcionar no Android Gingerbread, Observação: há mais uma ocorrênciaview.setBackground
no código.Vejo que essa pergunta já é antiga, mas ainda ...
Criamos uma biblioteca simples em nossa empresa para alcançar o que é desejado - uma janela de informações interativa com visualizações e tudo mais. Você pode conferir no github .
Espero que ajude :)
fonte
Aqui está a minha opinião sobre o problema. Crio uma
AbsoluteLayout
sobreposição que contém a Janela de informações (uma exibição regular com todos os recursos de interatividade e desenho). Então começo,Handler
que sincroniza a posição da janela de informações com a posição do ponto no mapa a cada 16 ms. Parece loucura, mas realmente funciona.Vídeo de demonstração: https://www.youtube.com/watch?v=bT9RpH4p9mU (leve em consideração que o desempenho diminuiu devido ao emulador e gravação de vídeo sendo executados simultaneamente).
Código da demonstração: https://github.com/deville/info-window-demo
Um artigo que fornece detalhes (em russo): http://habrahabr.ru/post/213415/
fonte
Para aqueles que não conseguiram obter
choose007's
resposta em funcionamentoSe
clickListener
não estiver funcionando corretamente o tempo todo nachose007's
solução, tente implementar emView.onTouchListener
vez declickListener
. Manipule o evento de toque usando qualquer uma das açõesACTION_UP
ouACTION_DOWN
. Por alguma razão, os mapasinfoWindow
causam algum comportamento estranho ao serem enviados paraclickListeners
.Edit: Isto é como eu fiz isso passo a passo
Primeiro, inflar sua própria janela de entrada (variável global) em algum lugar da sua atividade / fragmento. O meu está dentro de um fragmento. Verifique também se a visualização raiz no layout da janela de entrada é layout linear (por algum motivo, o relativelayout estava ocupando toda a largura da tela na janela de entrada)
Em seguida, no retorno de chamada onMapReady da API do Google Maps para Android (siga isto se você não sabe o que é onMapReady Mapas> Documentação - Introdução )
MapWrapperLayout
inicialização http://stackoverflow.com/questions/14123243/google-maps-android-api-v2- infowindow-interativo-como-no-original-android-go / 15040761 # 15040761 # 15040761 39 - altura padrão do marcador 20 - deslocamento entre o borda inferior padrão do InfoWindow e seu conteúdo borda inferior * /Método SetInfoWindow
Manipular o clique do marcador separadamente
fonte
Apenas uma especulação, não tenho experiência suficiente para experimentá-lo ...) -:
Como o GoogleMap é um fragmento, deve ser possível capturar o marcador no evento Click e mostrar a exibição personalizada do fragmento . Um fragmento de mapa ainda estará visível em segundo plano. Alguém tentou? Alguma razão para que não funcionasse?
A desvantagem é que o fragmento do mapa seria congelado no backgroud, até que um fragmento de informação personalizado retornasse o controle a ele.
fonte
Eu construí um projeto de estúdio android de amostra para esta pergunta.
capturas de tela de saída: -
Faça o download do código fonte completo do projeto Clique aqui
Observe: você precisa adicionar sua chave de API no Androidmanifest.xml
fonte
É realmente simples.
Basta adicionar o código acima na sua classe onde você está usando o GoogleMap. R.layout.info_window_layout é o nosso layout personalizado que mostra a visualização que será substituída pela janela de infowindow. Acabei de adicionar a visualização de texto aqui. Você pode adicionar uma visualização adicional aqui para torná-la como a amostra. Meu info_window_layout era
Eu espero que isso ajude. Podemos encontrar um exemplo prático de janela de infow personalizada em http://wptrafficanalyzer.in/blog/customizing-infowindow-contents-in-google-map-android-api-v2-using-infowindowadapter/#comment-39731
EDITADO: Este código mostra como podemos adicionar uma exibição personalizada no infoWindow. Este código não tratou dos cliques nos itens da Visualização Personalizada. Portanto, está perto de responder, mas não é exatamente a resposta, por isso não é aceito como resposta.
fonte