2017-12-28 23 views
1

내 프로젝트에 google maps을 사용하고 있습니다. 마커가 화면에 나타나지 않으면 화살표를 화면에 놓고 싶습니다. 어떻게 화면을 제어 할 수 있습니까?Google지도 화면 제어

+0

왜 화살표를 추가 하시겠습니까 : 그런 뭔가를 얻을 거라고? –

+0

마커 방향을 표시하고 싶습니다. (마커가 오른쪽 화살표로 표시되면 오른쪽에 나타납니다) –

+1

카메라 중심의 위도와 경도를 가져 와서 마커 방향을 얻습니다. 각도에 따라지도 상단에 오른쪽, 왼쪽, 위쪽, 아래쪽 화살표를 중첩 할 수 있습니다. –

답변

0

실제로 질문에 대한 답변은 lakshman.pasala 개의 댓글이지만 구현은 조금 복잡합니다 (TLDR).

Google지도 스크린 컨트롤을 얻는 가장 좋은 방법은 MapView 클래스 인 implement custom view입니다. 이 경우 뷰 캔버스에서 그림을 완전히 제어 할 수 있습니다. 이를 수행하려면 MapViewFrameLayoutViewGroup까지 확장되어 있기 때문에 dispatchDraw() 메서드를 무시하고 해당 화살표 드로잉 내에 구현해야합니다. 뭐 그런 :

@Override 
public void dispatchDraw(Canvas canvas) { 
    super.dispatchDraw(canvas); 
    canvas.save(); 
    drawArrowToMarker(canvas); 
    canvas.restore(); 
} 

하고 모든 맵 이동/확대/회전에 invalidate()를 통해 그것을 호출해야합니다. 지도 이동/확대/축소를 감지하려면 GoogleMap (정확히 GoogleMap.setOnCameraMoveListener() 메쏘드)가 필요합니다. 사용자 지정 MapView 클래스 내에 GoogleMap 개체를 선언하고 setter를 통해 설정할 수 있지만 사용자 지정 MapView 클래스가 OnMapReadyCallback 인터페이스를 구현하고 onMapReady() 콜백에 있으면 더 좋습니다. 세그먼트 교차점을 결정, 추가/마커를 제거 또한 당신의 필요 여러 유틸리티 방법, 방향 등 사용자 지정보기의 전체 소스 코드 (예 : EnhanchedMapView)은 같이 할 수있다 :

public class EnhanchedMapView extends MapView implements OnMapReadyCallback { 

    private final static int ARROW_PADDING = 50; 
    private final static double ARROW_ANGLE = Math.PI/6; 
    private final static double ARROW_LENGTH = 100; 
    private final static double ARROW_SIZE = 50; 

    private OnMapReadyCallback mMapReadyCallback; 
    private GoogleMap mGoogleMap; 
    private Marker mMarker; 
    private Paint mPaintArrow; 

    public EnhanchedMapView(@NonNull Context context) { 
     super(context); 
     init(); 
    } 

    public EnhanchedMapView(@NonNull Context context, @Nullable AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public EnhanchedMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(); 
    } 

    public EnhanchedMapView(@NonNull Context context, @Nullable GoogleMapOptions options) { 
     super(context, options); 
     init(); 
    } 

    @Override 
    public void dispatchDraw(Canvas canvas) { 
     super.dispatchDraw(canvas); 
     canvas.save(); 
     drawArrowToMarker(canvas); 
     canvas.restore(); 
    } 

    private void drawArrowToMarker(Canvas canvas) { 
     if (mGoogleMap == null || mMarker == null) { 
      return; 
     } 

     VisibleRegion visibleRegion = mGoogleMap.getProjection().getVisibleRegion(); 
     LatLngBounds screenBounds = visibleRegion.latLngBounds; 

     LatLng mapCenter = screenBounds.getCenter(); 
     Projection mapProjection = mGoogleMap.getProjection(); 

     final Point pointMapCenter = mGoogleMap.getProjection().toScreenLocation(mapCenter); 

     final Point pointTopLeft = mapProjection.toScreenLocation(visibleRegion.farLeft); 
     final Point pointTopRight = mapProjection.toScreenLocation(visibleRegion.farRight); 
     final Point pointBottomLeft = mapProjection.toScreenLocation(visibleRegion.nearLeft); 
     final Point pointBottomRight = mapProjection.toScreenLocation(visibleRegion.nearRight); 
     final Point pointMarker = mapProjection.toScreenLocation(mMarker.getPosition()); 

     final Point tl = new Point(pointTopLeft.x + ARROW_PADDING, pointTopLeft.y + ARROW_PADDING); 
     final Point tr = new Point(pointTopRight.x - ARROW_PADDING, pointTopRight.y + ARROW_PADDING); 
     final Point br = new Point(pointBottomRight.x - ARROW_PADDING, pointBottomRight.y - ARROW_PADDING); 
     final Point bl = new Point(pointBottomLeft.x + ARROW_PADDING, pointBottomLeft.y - ARROW_PADDING); 

     final Point pointIntersection = getBoundsIntersection(tl, tr, br, bl, pointMapCenter, pointMarker); 
     if (pointIntersection != null) { 
      double angle = Math.atan2(pointMarker.y - pointMapCenter.y, pointMarker.x - pointMapCenter.x); 

      int arrowX, arrowY; 
      arrowX = (int) (pointIntersection.x - ARROW_LENGTH * Math.cos(angle)); 
      arrowY = (int) (pointIntersection.y - ARROW_LENGTH * Math.sin(angle)); 
      canvas.drawLine(pointIntersection.x, pointIntersection.y, arrowX, arrowY, mPaintArrow); 

      arrowX = (int) (pointIntersection.x - ARROW_SIZE * Math.cos(angle + ARROW_ANGLE)); 
      arrowY = (int) (pointIntersection.y - ARROW_SIZE * Math.sin(angle + ARROW_ANGLE)); 
      canvas.drawLine(pointIntersection.x, pointIntersection.y, arrowX, arrowY, mPaintArrow); 

      arrowX = (int) (pointIntersection.x - ARROW_SIZE * Math.cos(angle - ARROW_ANGLE)); 
      arrowY = (int) (pointIntersection.y - ARROW_SIZE * Math.sin(angle - ARROW_ANGLE)); 
      canvas.drawLine(pointIntersection.x, pointIntersection.y, arrowX, arrowY, mPaintArrow); 
     } 
    } 

    private void init() { 
     setWillNotDraw(false); 

     mPaintArrow = new Paint(); 
     mPaintArrow.setColor(Color.BLUE); 
     mPaintArrow.setStrokeWidth(15); 
    } 

    @Override 
    public void getMapAsync(OnMapReadyCallback callback) { 
     mMapReadyCallback = callback; 
     super.getMapAsync(this); 
    } 

    @Override 
    public void onMapReady(GoogleMap googleMap) { 
     mGoogleMap = googleMap; 
     mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() { 
      @Override 
      public void onCameraMove() { 
       invalidate(); 
      } 
     }); 
     if (mMapReadyCallback != null) { 
      mMapReadyCallback.onMapReady(googleMap); 
     } 
    } 

    public void addMarker(MarkerOptions markerOptions) { 
     removeMarker(); 
     mMarker = mGoogleMap.addMarker(markerOptions); 
    } 

    public void removeMarker() { 
     mGoogleMap.clear(); 
    } 

    private static boolean floatEquals(float f1, float f2) { 
     final double EPS = 1e-6; 
     return (Math.abs(f1 - f2) < EPS); 
    } 

    private static Point getBoundIntersection(Point p11, Point p12, Point p21, Point p22) { 
     double x, y; 
     Point intersectionPoint = null; 

     // test intersection with vertical bound 
     if (floatEquals(p12.x, p11.x) || floatEquals(p22.x, p21.x)) { 
      if (floatEquals(p12.x, p11.x) && floatEquals(p22.x, p21.x) && !floatEquals(p11.x, p21.x)) { 
       return null; 
      } else { 
       if (floatEquals(p12.x, p11.x)) { 
        x = p11.x; 
        y = (x - p21.x)/(p22.x - p21.x) * (p22.y - p21.y) + p21.y; 

        if (x >= Math.min(p21.x, p22.x) && x <= Math.max(p21.x, p22.x) 
          && y >= Math.min(p11.y, p12.y) && y <= Math.max(p11.y, p12.y)) { 
         intersectionPoint = new Point((int) x, (int) y); 
        } 
       } else { 
        x = p21.x; 
        y = (x - p11.x)/(p12.x - p11.x) * (p12.y - p11.y) + p11.y; 

        if (x >= Math.min(p11.x, p12.x) && x <= Math.max(p11.x, p12.x) 
          && y >= Math.min(p21.y, p22.y) && y <= Math.max(p21.y, p22.y)) { 
         intersectionPoint = new Point((int) x, (int) y); 
        } 
       } 
      } 
     } else { 
      // test intersection with horizontal bound 
      if (floatEquals(p12.y, p11.y) || floatEquals(p22.y, p21.y)) { 
       if (floatEquals(p12.y, p11.y) && floatEquals(p22.y, p21.y) && !floatEquals(p11.y, p21.y)) { 
        return null; 
       } else { 
        if (floatEquals(p12.y, p11.y)) { 
         y = p12.y; 
         x = (y - p21.y)/(p22.y - p21.y) * (p22.x - p21.x) + p21.x; 

         if (x >= Math.min(p11.x, p12.x) && x <= Math.max(p11.x, p12.x) 
           && y >= Math.min(p21.y, p22.y) && y <= Math.max(p21.y, p22.y)) { 
          intersectionPoint = new Point((int) x, (int) y); 
         } 
        } else { 
         y = p21.y; 
         x = (y - p11.y)/(p12.y - p11.y) * (p12.x - p11.x) + p11.x; 

         if (x >= Math.min(p21.x, p22.x) && x <= Math.max(p21.x, p22.x) 
           && y >= Math.min(p11.y, p12.y) && y <= Math.max(p11.y, p12.y)) { 
          intersectionPoint = new Point((int) x, (int) y); 
         } 
        } 

       } 
      } 
     } 

     return intersectionPoint; 
    } 

    private static Point getBoundsIntersection(Point tl, Point tr, Point br, Point bl, Point p1, Point p2) { 
     Point intersectionPoint = null; 
     if ((intersectionPoint = getBoundIntersection(tl, tr, p1, p2)) != null) { 
      return intersectionPoint; 
     } else if ((intersectionPoint = getBoundIntersection(tr, br, p1, p2)) != null) { 
      return intersectionPoint; 
     } else if ((intersectionPoint = getBoundIntersection(br, bl, p1, p2)) != null) { 
      return intersectionPoint; 
     } else if ((intersectionPoint = getBoundIntersection(bl, tl, p1, p2)) != null) { 
      return intersectionPoint; 
     } 
     return null; 
    } 

} 

그리고 당신은 MainActivity이 방법에서 사용할 수 있습니다 : 당신은 말아야 결과

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="{YOUR_PACKAGE_NAME}.MainActivity"> 

    <{YOUR_PACKAGE_NAME}.EnhanchedMapView 
     android:id="@+id/mapview" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     /> 

</RelativeLayout> 

:

public class MainActivity extends AppCompatActivity { 

    private static final String MAP_VIEW_BUNDLE_KEY = "MapViewBundleKey"; 
    static final LatLng KYIV = new LatLng(50.450311, 30.523730); 

    private EnhanchedMapView mMapView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     Bundle mapViewBundle = null; 
     if (savedInstanceState != null) { 
      mapViewBundle = savedInstanceState.getBundle(MAP_VIEW_BUNDLE_KEY); 
     } 

     mMapView = (EnhanchedMapView) findViewById(R.id.mapview); 
     mMapView.onCreate(mapViewBundle); 
     mMapView.getMapAsync(new OnMapReadyCallback() { 
      @Override 
      public void onMapReady(GoogleMap googleMap) { 
       mMapView.addMarker(new MarkerOptions().position(KYIV).title("Kyiv")); 
      } 
     }); 

    } 

    @Override 
    public void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 

     Bundle mapViewBundle = outState.getBundle(MAP_VIEW_BUNDLE_KEY); 
     if (mapViewBundle == null) { 
      mapViewBundle = new Bundle(); 
      outState.putBundle(MAP_VIEW_BUNDLE_KEY, mapViewBundle); 
     } 

     mMapView.onSaveInstanceState(mapViewBundle); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     mMapView.onResume(); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     mMapView.onStart(); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     mMapView.onStop(); 
    } 
    @Override 
    protected void onPause() { 
     mMapView.onPause(); 
     super.onPause(); 
    } 
    @Override 
    protected void onDestroy() { 
     mMapView.onDestroy(); 
     super.onDestroy(); 
    } 
    @Override 
    public void onLowMemory() { 
     super.onLowMemory(); 
     mMapView.onLowMemory(); 
    } 

} 

activity_main.xml처럼가 될 수 있습니다

Arrow to marker