Кнопка MyLocation скрыта за прозрачной панелью действий, как переместить?

Я добавил фрагмент карты (API v2) в свое приложение с картой, охватывающей весь экран, и полупрозрачной панелью действий сверху. В активности используется тема с андроидом: windowActionBarOverlay, установленным в true.

Я также включил "MyLocationButton" на карте, но поскольку карта покрывает всю высоту экрана, кнопка закрывается панелью действий.

enter image description here

Как сделать фрагмент карты нарисовать кнопку местоположения ниже панели действий или внизу экрана?

Ответ 1

Вместо того, чтобы создавать свою собственную кнопку, просто переместите кнопку сборки в соответствии с размером панели действий.
Этот код работает для меня, и кнопка находится именно там, где должна быть кнопка (например, на картах Google):

// 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, но он будет работать и для обычной панели действий с несколькими изменениями.

Ответ 2

Ниже (особенно в fixMapControlLocations) я обратился к этому с помощью ActionBarSherlock.

Проблемы, которые у меня были, были на узких экранах, а разделительная панель действия имела неправильное смещение в зависимости от поворота. Проверка isNarrow через sherlock позволяет мне знать, если она узкая.

Другим ключевым изменением является установка прописной части родительского представления myLocation. Это забирает все элементы управления внутри, и на основе hierarchyviewer, как это делают карты Google. Логотип атрибуции 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

Вы можете выполнить это с помощью недавно добавленного метода GoogleMap.setPadding():

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

В документах API:

Этот метод позволяет вам определить видимую область на карте, чтобы сообщить карте, что части карты вокруг краев могут быть затенены, путем установки дополнения на каждом из четырех краев карты. Функции карты будут адаптированы к дополнению. Например, элементы управления масштабированием, компас, уведомления об авторских правах и логотип Google будут перемещены в соответствии с определенной областью, движения камеры будут относиться к центру видимой области и т.д.

Также см. описание того, как работает дополнение в GoogleMap.

Ответ 4

Это уже было добавлено в качестве улучшения (пожалуйста, запустите его, если вы еще этого не сделали) 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;
   }
}

Я использовал иерархический просмотр, чтобы найти идентификатор кнопки, добавленной картами api. Это просто второй вид, добавленный к карте (и установленный на невидимый).

Конечно, вы можете играть с LayoutParams, чтобы смещать эту кнопку, а не скрывать ее, но эта кнопка появляется только после того, как вы установилиMyLocationEnabled в true! (в моем случае я предпочитаю, чтобы пользователь решил до запуска gps)

Ответ 5

Убедитесь, что вы используете ?android:attr/actionBarSize (или ?attr/actionBarSize, если используете ActionBarSherlock), чтобы правильно смещать содержимое фрагмента.

В зависимости от эффекта, который вы пытаетесь выполнить, примените это значение как margin или padding. Я предполагаю, что из-за полупрозрачного ActionBar вы захотите попробовать прописку, чтобы по-прежнему отображалась карта (и сохраняйте прозрачный эффект). Я просто не уверен на 100%, будет ли добавление на самом деле переместить кнопку "Найти меня"... Если нет, то, вероятно, применение поля - это ваш единственный вариант.

См. здесь для примера и более подробную информацию об этом атрибуте.