Estoy tratando de personalizar InfoWindow
después de hacer clic en un marcador con la nueva API de Google Maps v2. Quiero que se vea como en la aplicación de mapas original de Google. Me gusta esto:
Cuando tengo ImageButton
adentro, no funciona: todo InfoWindow
se elige y no solo el ImageButton
. Leí que es porque no hay un View
sí mismo, sino una instantánea, por lo que los elementos individuales no se pueden distinguir entre sí.
EDITAR: En la documentación (gracias a Disco S2 ):
Como se mencionó en la sección anterior sobre ventanas de información, una ventana de información no es una Vista en vivo, sino que la vista se representa como una imagen en el mapa. Como resultado, los escuchas que establezca en la vista no se tienen en cuenta y no puede distinguir entre los eventos de clic en varias partes de la vista. Se recomienda no colocar componentes interactivos, como botones, casillas de verificación o entradas de texto, dentro de su ventana de información personalizada.
Pero si Google lo usa, debe haber alguna forma de hacerlo. ¿Alguien tiene alguna idea?
fuente
View.draw(Canvas)
) ... Esto significa que cualquier cambio posterior a la vista no se reflejará en la ventana de información del mapa. Para actualizar la ventana de información más adelante Además, la ventana de información no respetará ninguna de las interactividades típicas de una vista normal, como eventos táctiles o gestuales. Sin embargo, puede escuchar un evento de clic genérico en toda la ventana de información como se describe en la sección a continuación. ... en su ejemplo es solo una vista de textoRespuestas:
Estaba buscando una solución a este problema sin suerte, así que tuve que rodar la mía que me gustaría compartir aquí con ustedes. (Disculpe mi mal inglés) (Es un poco loco responder a otro checo en inglés :-))
Lo primero que intenté fue usar un buen viejo
PopupWindow
. Es bastante fácil: solo hay que escucharOnMarkerClickListener
y luego mostrar una costumbrePopupWindow
sobre el marcador. Algunos otros tipos aquí en StackOverflow sugirieron esta solución y en realidad se ve bastante bien a primera vista. Pero el problema con esta solución aparece cuando comienzas a mover el mapa. Tienes que moverlo dePopupWindow
alguna manera, lo cual es posible (escuchando algunos eventos onTouch), pero en mi humilde opinión, no puedes hacer que se vea lo suficientemente bien, especialmente en algunos dispositivos lentos. Si lo hace de la manera simple, "salta" de un lugar a otro. También podría usar algunas animaciones para pulir esos saltos, pero de esta maneraPopupWindow
siempre estará "un paso atrás" donde debería estar en el mapa, lo que simplemente no me gusta.En este punto, estaba pensando en alguna otra solución. Me di cuenta de que en realidad no necesito tanta libertad, para mostrar mis vistas personalizadas con todas las posibilidades que conlleva (como barras de progreso animadas, etc.). Creo que hay una buena razón por la cual incluso los ingenieros de Google no lo hacen de esta manera en la aplicación Google Maps. Todo lo que necesito es un botón o dos en la ventana de información que mostrará un estado presionado y desencadenará algunas acciones al hacer clic. Entonces se me ocurrió otra solución que se divide en dos partes:
Primera parte:
la primera parte es poder capturar los clics en los botones para activar alguna acción. Mi idea es la siguiente:
MapFragment
(oMapView
) dentro de un ViewGroup personalizado (el mío se llama MapWrapperLayout)MapWrapperLayout
'dispatchTouchEvent' y (si la ventana de información se muestra actualmente) primero enrute los eventos de movimiento a la ventana de información creada anteriormente. Si no consume los MotionEvents (como porque no hizo clic en ningún área en la que se pueda hacer clic dentro de InfoWindow, etc.), entonces (y solo entonces) deje que los eventos pasen a la superclase de MapWrapperLayout para que finalmente se entregue al mapa.Aquí está el código fuente de MapWrapperLayout:
Todo esto hará que las vistas dentro de InfoView estén "en vivo" nuevamente: los OnClickListeners comenzarán a activarse, etc.
Segunda parte: el problema restante es que, obviamente, no puede ver ningún cambio en la interfaz de usuario de su InfoWindow en la pantalla. Para hacerlo, debe llamar manualmente a Marker.showInfoWindow. Ahora, si realiza algún cambio permanente en su InfoWindow (como cambiar la etiqueta de su botón a otra cosa), esto es lo suficientemente bueno.
Pero mostrar un estado de botón presionado o algo de esa naturaleza es más complicado. El primer problema es que (al menos) no pude hacer que la ventana de información muestre el estado presionado del botón normal. Incluso si presioné el botón durante mucho tiempo, simplemente no se presionó en la pantalla. Creo que esto es algo que es manejado por el marco del mapa en sí mismo que probablemente se asegura de no mostrar ningún estado transitorio en las ventanas de información. Pero podría estar equivocado, no intenté descubrir esto.
Lo que hice fue otro truco desagradable: adjunté un
OnTouchListener
botón al botón y cambié manualmente su fondo cuando se presionó el botón o se soltó a dos elementos dibujables personalizados, uno con un botón en un estado normal y el otro en un estado presionado. Esto no es muy agradable, pero funciona :). Ahora pude ver cómo el botón cambiaba de estado normal a presionado en la pantalla.Todavía hay una última falla: si hace clic en el botón demasiado rápido, no muestra el estado presionado, simplemente permanece en su estado normal (aunque el clic en sí mismo se activa para que el botón "funcione"). Al menos así es como aparece en mi Galaxy Nexus. Así que lo último que hice es retrasar un poco el botón cuando está presionado. Esto también es bastante feo y no estoy seguro de cómo funcionaría en algunos dispositivos más antiguos y lentos, pero sospecho que incluso el marco del mapa hace algo como esto. Puede probarlo usted mismo: cuando hace clic en toda la ventana de información, permanece presionada un poco más, luego los botones normales lo hacen (nuevamente, al menos en mi teléfono). Y así es como funciona incluso en la aplicación original de Google Maps.
De todos modos, escribí una clase personalizada que maneja los cambios de estado de los botones y todas las otras cosas que mencioné, así que aquí está el código:
Aquí hay un archivo de diseño personalizado de InfoWindow que utilicé:
Probar el archivo de diseño de actividad (
MapFragment
estar dentro delMapWrapperLayout
):Y finalmente, el código fuente de una actividad de prueba, que une todo esto:
Eso es. Hasta ahora solo probé esto en mi Galaxy Nexus (4.2.1) y Nexus 7 (también 4.2.1), lo intentaré en algún teléfono Gingerbread cuando tenga la oportunidad. Una limitación que encontré hasta ahora es que no puedes arrastrar el mapa desde donde está tu botón en la pantalla y mover el mapa. Probablemente podría superarse de alguna manera, pero por ahora, puedo vivir con eso.
Sé que este es un truco feo, pero simplemente no encontré nada mejor y necesito tanto este patrón de diseño que realmente sería una razón para volver al marco del mapa v1 (que por cierto, realmente me gustaría evitar para una nueva aplicación con fragmentos, etc.). Simplemente no entiendo por qué Google no ofrece a los desarrolladores alguna forma oficial de tener un botón en InfoWindows. Es un patrón de diseño tan común, además, este patrón se usa incluso en la aplicación oficial de Google Maps :). Entiendo las razones por las que no pueden simplemente hacer que sus vistas "vivan" en InfoWindows; esto probablemente mataría el rendimiento al mover y desplazar el mapa. Pero debería haber alguna forma de lograr este efecto sin usar vistas.
fuente
view.setBackground(bgDrawablePressed);
conif (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { view.setBackgroundDrawable(bgDrawablePressed); }else{ view.setBackground(bgDrawablePressed); }
para trabajar en Android Gingerbread, Nota: hay una ocurrencia másview.setBackground
en el código.Veo que esta pregunta ya es vieja pero aún así ...
Hicimos una biblioteca de sipmle en nuestra empresa para lograr lo que se desea: una ventana de información interactiva con vistas y todo. Puedes verlo en github .
Espero que ayude :)
fuente
Aquí está mi opinión sobre el problema. Creo una
AbsoluteLayout
superposición que contiene la ventana de información (una vista normal con cada bit de interactividad y capacidades de dibujo). Luego comienzo,Handler
que sincroniza la posición de la ventana de información con la posición del punto en el mapa cada 16 ms. Suena loco, pero en realidad funciona.Video de demostración: https://www.youtube.com/watch?v=bT9RpH4p9mU (tenga en cuenta que el rendimiento disminuye debido a que el emulador y la grabación de video se ejecutan simultáneamente).
Código de la demostración: https://github.com/deville/info-window-demo
Un artículo que proporciona detalles (en ruso): http://habrahabr.ru/post/213415/
fuente
Para aquellos que no pudieron obtener
choose007's
respuesta en funcionamientoSi
clickListener
no funciona correctamente en todo momento en lachose007's
solución, intente implementar enView.onTouchListener
lugar declickListener
. Manejar evento táctil usando cualquiera de las accionesACTION_UP
oACTION_DOWN
. Por alguna razón, los mapasinfoWindow
causan un comportamiento extraño cuando se envía aclickListeners
.Editar: así es como lo hice paso a paso
Primero infle su propia ventana de información (variable global) en algún lugar de su actividad / fragmento. La mía está dentro del fragmento. También asegúrese de que la vista raíz en el diseño de su ventana de información es lineal (por alguna razón, la distribución relativa ocupaba todo el ancho de la pantalla en la ventana de información)
Luego, en onMapReady callback de la API de Android de Google Maps (siga esto si no sabe qué es onMapReady Maps> Documentation - Getting Started )
MapWrapperLayout
inicialización http://stackoverflow.com/questions/14123243/google-maps-android-api-v2- interactive-infowindow-like-in-original-android-go / 15040761 # 15040761 39 - altura predeterminada del marcador 20 - desplazamiento entre el borde inferior de InfoWindow predeterminado y su borde inferior de contenido * /Método SetInfoWindow
Manejar el marcador de clic por separado
fuente
Solo una especulación, no tengo suficiente experiencia para probarlo ...) -:
Como GoogleMap es un fragmento, debería ser posible capturar el marcador en el evento Click y mostrar una vista de fragmento personalizada . Un fragmento del mapa seguirá siendo visible en el fondo. ¿Alguien lo intentó? ¿Alguna razón por la que no podría funcionar?
La desventaja es que el fragmento de mapa se congelaría en el fondo, hasta que un fragmento de información personalizado le devuelva el control.
fuente
He creado un proyecto de estudio de Android de muestra para esta pregunta.
capturas de pantalla de salida: -
Descargar el código fuente completo del proyecto Haga clic aquí
Tenga en cuenta: debe agregar su clave API en Androidmanifest.xml
fuente
Es realmente simple
Simplemente agregue el código anterior en su clase donde está usando GoogleMap. R.layout.info_window_layout es nuestro diseño personalizado que muestra la vista en lugar de la ventana de información. Acabo de agregar la vista de texto aquí. Puede agregar una vista adicional aquí para que se parezca al complemento de muestra. Mi info_window_layout fue
Espero que sea de ayuda. Podemos encontrar un ejemplo de funcionamiento de la ventana de información personalizada en http://wptrafficanalyzer.in/blog/customizing-infowindow-contents-in-google-map-android-api-v2-using-infowindowadapter/#comment-39731
EDITADO: Este código muestra cómo podemos agregar una vista personalizada en infoWindow. Este código no manejó los clics en los elementos de Vista personalizada. Por lo tanto, está cerca de responder, pero no es exactamente la respuesta, por eso no se acepta como respuesta.
fuente