MapFragment
, without which embedding maps into an application built on fragments is impossible. Or, for example, such a trifle as the ability to specify a key in a single place in AndroidManifest.xml
, and not in each MapView
, as in the first version of the library. New chips, like Fluent Interface. Beauty.InfoWindowAdapter
, but it ... uh ... is somewhat limited. Documentation tells us:Note: This is a live view. The view is rendered as an image (using View. Draw (Canvas)) at the time it is returned. This is a reflection on the map. To update the info window later (for example, after an image has loaded), call showInfoWindow ().
showInfoWindow()
. This is enough to, for example, display an image downloaded from the network, but what about, for example, a ProgressBar
'which needs to be redrawn constantly? How to draw states (pressed, focused, etc.) View
in a window?Furthermore, it is typical for a normal view, such as touch or gesture events. However, you can’t read it in this section below.
OnInfoWindowClickListener
using OnInfoWindowClickListener
.MapView
and intercept input events by manually switching states. According to him, this is extremely dreary, and it is not possible to make it all work normally. It would seem, on this you can give up.View
in the container, you can think of a bike, but, fortunately, there is no need - we remember that we have an outdated but not completely cut AbsoluteLayout
(we don’t incinerate me for using it). ). <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:id="@+id/container_map" android:layout_width="wrap_content" android:layout_height="wrap_content" > <!-- --> </FrameLayout> <AbsoluteLayout android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/container_popup" android:layout_x="0dp" android:layout_y="0dp" android:layout_width="wrap_content" android:layout_height="wrap_content" > <!-- --> </LinearLayout> </AbsoluteLayout> </RelativeLayout>
public class MapFragment extends com.google.android.gms.maps.MapFragment { // private static final int ANIMATION_DURATION = 500; // private LatLng trackedPosition; // , private int popupXOffset; private int popupYOffset; // private int markerHeight; //, private ViewTreeObserver.OnGlobalLayoutListener infoWindowLayoutListener; // private View infoWindowContainer; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment, null); FrameLayout containerMap = (FrameLayout) rootView.findViewById(R.id.container_map); View mapView = super.onCreateView(inflater, container, savedInstanceState); containerMap.addView(mapView, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); infoWindowContainer= rootView.findViewById(R.id.container_popup); // infoWindowLayoutListener = new InfoWindowLayoutListener(); infoWindowContainer.getViewTreeObserver().addOnGlobalLayoutListener(infoWindowLayoutListener ); return rootView; } @Override public void onDestroyView() { super.onDestroyView(); // infoWindowContainer.getViewTreeObserver().removeGlobalOnLayoutListener(infoWindowLayoutListener ); } @Override public void onMapClick(LatLng latLng) { // , infoWindowContainer.setVisibility(INVISIBLE); } @Override public boolean onMarkerClick(Marker marker) { // // GoogleMap map = getMap(); Projection projection = map.getProjection(); trackedPosition = marker.getPosition(); // Point trackedPoint = projection.toScreenLocation(trackedPosition); trackedPoint.y -= popupYOffset / 2; LatLng newCameraLocation = projection.fromScreenLocation(trackedPoint); map.animateCamera(CameraUpdateFactory.newLatLng(newCameraLocation), ANIMATION_DURATION, null); // //… infoWindowContainer.setVisibility(VISIBLE); return true; } private class InfoWindowLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener { @Override public void onGlobalLayout() { // , popupXOffset = infoWindowContainer.getWidth() / 2; popupYOffset = infoWindowContainer.getHeight(); } } }
onTouchEvent()
and changing the position of the window in the same place. As it turned out, the method is completely useless - due to the fact that input events are grouped before it gets into onTouchEvent()
, it is called with an arbitrary periodicity, so the pop-up window moves in spurts. Looks disgusting.Handler
and Runnable
to help: public class MapFragment extends com.google.android.gms.maps.MapFragment { // . // 60 fps, 1000 ms / 60 = 16 ms . private static final int POPUP_POSITION_REFRESH_INTERVAL = 16; //Handler, private Handler handler; //Runnable, private Runnable positionUpdaterRunnable; @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); handler = new Handler(Looper.getMainLooper()); positionUpdaterRunnable = new PositionUpdaterRunnable(); // handler.post(positionUpdaterRunnable); } @Override public void onDestroyView() { super.onDestroyView(); // handler.removeCallbacks(positionUpdaterRunnable); handler = null; } private class PositionUpdaterRunnable implements Runnable { private int lastXPosition = Integer.MIN_VALUE; private int lastYPosition = Integer.MIN_VALUE; @Override public void run() { // handler.postDelayed(this, POPUP_POSITION_REFRESH_INTERVAL); // , if (trackedPosition != null && infoWindowContainer.getVisibility() == VISIBLE) { Point targetPosition = getMap().getProjection().toScreenLocation(trackedPosition); // , if (lastXPosition != targetPosition.x || lastYPosition != targetPosition.y) { // overlayLayoutParams = (AbsoluteLayout.LayoutParams) infoWindowContainer.getLayoutParams(); overlayLayoutParams.x = targetPosition.x - popupXOffset; overlayLayoutParams.y = targetPosition.y - popupYOffset - markerHeight; infoWindowContainer.setLayoutParams(overlayLayoutParams); // lastXPosition = targetPosition.x; lastYPosition = targetPosition.y; } } } } }
Source: https://habr.com/ru/post/213415/
All Articles