如何更改GoogleMap V2相机中心?

时间:2018-01-10 14:53:51

标签: android google-maps-android-api-2

我正在尝试将Google地图V2相机中心位置更改为地图视图的中心位置。

到目前为止,在this

等一些解决方案的帮助下,我已经部分成功实现了这一目标。

此解决方案完成了这项工作,但实际的相机位置仍然保留在地图的中心! 它“按下”目标位置,但相机仍在“查看”MapView的中心。

当您想在导航中进行动画制作和地图移动时,会出现此方法的问题。

您需要计算从GPS获得的每个位置的偏移量,当您进行硬转弯时,偏移量与摄像机动画路线不在我的控制范围内不同。

例如,如果我向前移动某个方向,然后突然我转180度,动画将推动我的目标位置,直到动画完成然后它看起来不错,那是因为地图旋转和动画总是在凸轮位置周围,始终位于视图的中心。

Fo实例,在谷歌地图导航中 - 导航标记位于地图的底部,它似乎围绕该位置旋转和动画,而不是围绕视图中心。

以下是我从上述解决方案中获得的结果的屏幕截图: The camera position is always in the center

我想要的是相机位置将在我的目标位置。

谷歌地图导航: enter image description here

2 个答案:

答案 0 :(得分:1)

您应该使用Map Padding,即setPadding(int left, int top, int right, int bottom)方法:

created_at

其中... public void onMapReady(GoogleMap googleMap) { mGoogleMap = googleMap; mGoogleMap.setPadding(0, dHeight, 0, 0); ... } ... 。你应该移动罗盘按钮,就像在thisVignon回答中一样,在剪裁区域之外绘制罗盘的一些变化:

dHeight = Target_pos.y - cam_pos.y

你也可以尝试那种肮脏的解决方案(见图)

Recenered map

是将try { final ViewGroup parent = (ViewGroup) mMapFragment.getView().findViewWithTag("GoogleMapMyLocationButton").getParent(); parent.post(new Runnable() { @Override public void run() { try { Resources r = getResources(); //convert our dp margin into pixels int marginPixels = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, r.getDisplayMetrics()); // Get the map compass view View mapCompass = parent.getChildAt(4); View v = mapCompass; while (v.getParent() != null && v.getParent() instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) v.getParent(); viewGroup.setClipChildren(false); viewGroup.setClipToPadding(false); v = viewGroup; } // create layoutParams, giving it our wanted width and height(important, by default the width is "match parent") RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(mapCompass.getHeight(),mapCompass.getHeight()); // position on top right rlp.addRule(RelativeLayout.ALIGN_PARENT_LEFT); rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0); rlp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0); rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 0); //give compass margin rlp.setMargins(marginPixels, dHeight, marginPixels, marginPixels); mapCompass.setLayoutParams(rlp); } catch (Exception ex) { ex.printStackTrace(); } } }); } catch (Exception ex) { ex.printStackTrace(); } MapFragment)的高度缩放到MapView,然后可见区域(屏幕高度),其中:

dHeight

其中dHeight = (int) (k * MapFragment.height) 。在这种情况下,地图中心会精确地移动到您想要的点(但是底部(图片上的白色)部分地图将不可见)。此外,您应该向上移动缩放控件,因为默认情况下它也位于地图的底部,也不会显示。您可以在this回答中执行此操作。但请记住,根据Google Maps APIs Terms of Service,您的申请不得删除或隐藏Google徽标或版权声明。

似乎正确的解决方案是创建自定义视图,该视图扩展为MapFragmentMapView,例如就像在that回答一样,做你所有的位置偏移计算其中的魔法。

答案 1 :(得分:0)

最后我来到了解决方案!!

填充解决方案适用于静态地图但是当你想在地图上像导航一样进行连续动画时,填充会导致不期望的轮流移动,特别是当地图倾斜和缩放时!

MapView尺寸解决方案是正确的选择,因为它只是推动地图的中心。

这种方法的问题在于它还会降低变焦控制,最重要的是必须可见的Google徽标。

因此,您必须明确设置缩放控件和Google徽标底部边距,以便它们再次可见!这不会给地图视图本身添加任何填充。

或者,您可以将控件和徽标位置设置为不同的角落,如果它可以满足您的需要,我决定只设置它们的边距。

这是我的代码:

final ViewTreeObserver observer = mapView.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mainParentLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            int parentHeight = ((ViewGroup)mapView.getParent()).getHeight() - toolbar.getHeight();
            int mapHeight = parentHeight + parentHeight/2;
            mapView.getLayoutParams().height = mapHeight;
            int margin = mapHeight - parentHeight + 2*((int)(getResources().getDimension(R.dimen.small_image) + getResources().getDimension(R.dimen.small_pargin)));
            Log.i(TAG, "onGlobalLayout: parent height: " +  parentHeight + ", map new height: " + mapHeight + ", margin: " + margin);

            setMapControlsMargin(margin);
        }
    });

此代码等待显示地图视图,然后计算地图父视图高度(在我的例子中为ConstraintLayout),然后将地图高度设置为parentHeight * 1.5。这将推动相机中心! 然后,设置Google徽标和缩放控件的边距。

 private void setMapControlsMargin(final int margin){
    try {
        //Find the Zoom controls parent 
        final ViewGroup parent = (ViewGroup) mapView.findViewWithTag("GoogleMapMyLocationButton").getParent();

        //Find the Google logo parent view group
        final ViewGroup googleLogo = (ViewGroup) mapView.findViewWithTag("GoogleWatermark").getParent();

        Log.i(TAG, "setMapControlsMargin: found Google logo " + (googleLogo != null));

        //Set the margin for the Google logo
        if (googleLogo != null) {
            FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) googleLogo.getLayoutParams();
            layoutParams.bottomMargin = margin;
        }


        parent.post(() -> {
            try {
                View zoomControls = parent.getChildAt(2);  //Zoom controls
                ViewGroup.LayoutParams layoutParams1 = zoomControls.getLayoutParams();

                //Read the zoom controls original margin, this will be added to the offset margin
                int origBotMargin = ((RelativeLayout.LayoutParams) layoutParams1).bottomMargin;
                int origRightMargin = ((RelativeLayout.LayoutParams) layoutParams1).rightMargin;


                // create layoutParams, giving it our wanted width and height(important, by default the width is "match parent")
                RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(zoomControls.getWidth(),zoomControls.getHeight());
                // position on bottom right
                rlp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
                rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,  RelativeLayout.TRUE);
                //set the new margin
                rlp.setMargins(0, 0, origRightMargin, origBotMargin + margin);
                zoomControls.setLayoutParams(rlp);

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

我被this发帖帮助移动了Google徽标。