问题 隐藏在透明操作栏后面的MyLocation按钮,如何重新定位? [重复]


这个问题在这里已有答案:


10784
2018-01-13 00:29


起源

stackoverflow.com/a/20750956/1066839 - John


答案:


不要创建自己的按钮,只需根据操作栏大小移动内置按钮。
这段代码适用于我,按钮就是按钮的位置(就像谷歌地图一样):

// Gets the my location button
View myLocationButton = getSherlockActivity().findViewById(R.id.MainContainer).findViewById(2); 

// Checks if we found the my location button        
if (myLocationButton != null){
        int actionBarHeight = 0;
        TypedValue tv = new TypedValue();

           // Checks if the os version has actionbar in it or not
           if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
              if (getSherlockActivity().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
                actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
           }
           // Before the action bar was added to the api
           else if(getSherlockActivity().getTheme().resolveAttribute(com.actionbarsherlock.R.attr.actionBarSize, tv, true)){
                actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
           }

        // Sets the margin of the button
        ViewGroup.MarginLayoutParams marginParams = new ViewGroup.MarginLayoutParams(myLocationButton.getLayoutParams());
        marginParams.setMargins(0, actionBarHeight + 20, 20, 0);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
        myLocationButton.setLayoutParams(layoutParams);
}


只需将此代码放在onActivityCreated中(如果将它放在onCreateOptionsMenu中,它将不支持3.0之前的版本 - 因为生命周期不同。
另一件事,“R.id.MainContainer”是地图片段的容器。

我正在使用ActionBar Sherlock,但它也适用于常规操作栏,只需进行一些修改。


6
2018-04-01 08:28



请尝试使用此代码,如果它适用于您,请将其标记为答案,以便其他人可以使用它。这个对我有用.. - Or Kazaz
对于我来说,在示例代码的第二行中的findViewById调用中列出了神奇的数字2似乎是不好的做法。您没有说明您找到该号码的位置以及我们是否可以指望该号码不会更改,特别是如果它不是Google记录的ID。如果他们决定更改ID,那么你就会被打破。 - Steven
该ID来自层次结构查看器。我同意,如果Google会更改它,您还需要更改它。但是您可以控制自己的发布,如果Google更新了他们的google-play-services,您需要在发布之前实施它。在最糟糕的情况下,如果他们将更改它,请检查层次结构查看器中的新ID。并且不要忘记这只是他们将解决此问题: code.google.com/p/gmaps-api-issues/issues/detail?id=4670 - Or Kazaz
我认为,只要Google决定将Google Play服务更新推送到用户的手机,地图就会更新...我们开发时使用的Google Play服务只是他们推送到Google Play服务中的方法存根设备在后台。如果我对Google Play服务如何运作的理解是正确的,这意味着他们可以随时打破你。 - Steven


下面(特别是在 fixMapControlLocations我用ActionBarSherlock解决了这个问题。

我遇到的问题是在狭窄的屏幕上,并且分割操作栏具有错误的偏移,具体取决于旋转。该 isNarrow 检查通过sherlock让我知道它是否狭窄。

另一个关键变化是我正在设置myLocation父级父视图的填充。这会获取内部的所有控件,并且基于hierarchyviewer是google maps正在执行的操作。 Google归因徽标位于Surface对象树的下一个父级。看起来不容易移动,所以我可能最终会失去底部动作栏的透明效果以保持合规性。

protected void onCreate(Bundle savedInstanceState) {
    getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.map);
    setUpMapIfNeeded();

    getSupportActionBar().setBackgroundDrawable(d);
    getSupportActionBar().setSplitBackgroundDrawable(d);
}

private void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the
    // map.
    if (map == null) {
        // Try to obtain the map from the SupportMapFragment.
        map = ((SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map)).getExtendedMap();

        // Check if we were successful in obtaining the map.
        if (map != null) {
            setUpMap();
        }
    }
}

private void setUpMap() {
    fixMapControlLocations();
    .....
}

private void fixMapControlLocations() {
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    int actionBarHeight = 0;
    TypedValue tv = new TypedValue();
    if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
    {
        actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
    }

    View myLocationParent = ((View)mapFragment.getView().findViewById(1).getParent());
    View myLocationParentParent = ((View)myLocationParent.getParent());
    myLocationParentParent.setPadding(0, actionBarHeight, 0, isNarrow()?actionBarHeight:0);
}

public boolean isNarrow() {
    return ResourcesCompat.getResources_getBoolean(getApplicationContext(),
            R.bool.abs__split_action_bar_is_narrow);
}

3
2018-06-18 01:25





您可以使用最近添加的内容来完成此操作 GoogleMap.setPadding() 方法:

map.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);

来自API文档:

此方法允许您在地图上定义可见区域,通过在地图的四个边缘中的每一个上设置填充,向地图发信号通知边缘周围的地图部分可能被遮挡。地图功能将适应填充。例如,缩放控件,指南针,版权声明和Google徽标将移动到适合定义区域内,相机移动将相对于可见区域的中心等。

另见 填充在GoogleMap中的工作原理


3
2017-12-05 21:14



不是一个理想的解决方案,因为它搞砸了相机 - Matt


这已经作为增强功能提交(如果您尚未加注,请将其加注) http://code.google.com/p/gmaps-api-issues/issues/detail?id=4670

作为临时解决方法,我在操作栏下方添加了自己的查找位置按钮(我的地图片段位于RelativeLayout中,所以我只做了alignParentRight并设置了适当的上边距)。

然后在我的onClickHandler中我这样做了:

public void onClickHandler(View target) {
   switch (target.getId()) {
      case R.id.my_fml_btn:         
         mMap.setMyLocationEnabled(true);
         View fmlBtn = mMapWrapper.findViewById(2); //mMapWrapper is my RelativeLayout
         if (fmlBtn != null) fmlBtn.setVisibility(View.INVISIBLE);
         break;
   }
}

我使用hierarchyviewer来查找maps api添加的按钮的id。它恰好是添加到地图的第二个视图(并设置为不可见)。

您当然可以通过LayoutParams来调整偏移此按钮而不是隐藏它,但只有在将setMyLocationEnabled设置为true后才会出现此按钮! (在我的用例中,我更喜欢让用户在启动gps之前做出决定)


1
2018-01-17 10:24



谢谢你的链接。出演。 - machtnix
它对我有用!谢谢 - Coderji


确保你使用 ?android:attr/actionBarSize (要么 ?attr/actionBarSize 如果你正在使用ActionBarSherlock)来正确地抵消片段的内容。

根据您尝试完成的效果,将此值应用为边距或填充。我猜测因为半透明的ActionBar,你会想要尝试填充,以便仍然让地图出现在它后面(并保持透视效果)。我只是不确定填充是否会实际移动'找到我'按钮...如果没有,那么可能应用保证金是你唯一的其他选择。

看到 这里 有关此属性的示例和更多详细信息。


0
2018-01-13 00:41



这会正确地重新定位“我的位置”按钮,但实体操作栏会丢失透明的操作栏覆盖。 margin属性适用于片段父级和片段本身,但padding属性仅在父级中设置时才有效。无论哪种方式,这都会产生一个坚实的动作栏。 - qubz