Как узнать, что карта готова к использованию при использовании SupportMapFragment?
В методе onCreate
я использую SupportMapFragment
для отображения карты.
SupportMapFragment fragment = new SupportMapFragment();
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, fragment).commit();
В связи с этим я хотел бы добавить маркер. Проблема в том, когда вызов getMap
равен нулю, когда я могу попробовать еще раз? Есть ли какое-то событие, которое я могу зарегистрировать, или мой подход сам по себе не прав?
mMap = ((SupportMapFragment)(getSupportFragmentManager().findFragmentById(R.id.map))).getMap();
if(mMap == null)
//what do I do here?
Карта фактически отображается на телефоне, однако мне кажется, что нам не удавалось получить ссылку на добавление маркеров.
UPDATE:
Причина, по которой я создавала SupportMapFragment
через конструктор, связана с тем, что типичный setContentView
был сбой и не работал. Это поставило меня в затруднительное положение, когда я не смог получить свою ссылку в методе onCreate
, так как я фактически создавал SupportMapFragment
в то время. В дальнейших исследованиях, кажется, что мой вопрос setContentView
был побочным продуктом, когда у меня не было как баннера Google-play-services, так и модуль /src, созданный как часть общего проекта. Выполняя ОБА, теперь работает setContentView
, и я могу получить ссылку через getMap()
, как и следовало ожидать.
lots.xml...
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
LotsActivity.java...
public class LotsActivity extends FragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lots);
GoogleMap mMap;
mMap = ((SupportMapFragment)(getSupportFragmentManager().findFragmentById(R.id.map))).getMap();
if(mMap == null)
//this should not occur now
}
Ответы
Ответ 1
EDIT: getMap
теперь устарел
Проблема в том, когда вызов getMap равен null, когда я могу попробовать еще раз?
Это зависит от характера проблемы.
Если вы настроите SupportMapFragment
с помощью элемента <fragment>
в макете, вы можете вызвать getMap()
успешно в onCreate()
. Но, если вы создаете SupportMapFragment
через конструктор, это слишком скоро - GoogleMap
еще не существует. Вы можете расширить SupportMapFragment
и переопределить onActivityCreated()
, так как к нему будет готова getMap()
.
Тем не менее, getMap()
также может возвращать null
для большей проблемы, например, не устанавливать Google Play Services. Вам нужно будет использовать что-то вроде GooglePlayServicesUtil.isGooglePlayServicesAvailable()
, чтобы обнаружить это условие и справиться с ним, как хотите.
Ответ 2
Я закончил расширение класса SupportMapFragment и использовал обратный вызов. Код здесь:
public class MySupportMapFragment extends SupportMapFragment {
public MapViewCreatedListener itsMapViewCreatedListener;
// Callback for results
public abstract static class MapViewCreatedListener {
public abstract void onMapCreated();
}
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
// Notify the view has been created
if( itsMapViewCreatedListener != null ) {
itsMapViewCreatedListener.onMapCreated();
}
return view;
}
}
Я предпочел бы использовать интерфейс и переопределить метод onAttach (activity), но в моем случае я не хотел, чтобы callback возвращался к моей MainActivity. Я хотел, чтобы он вернулся к экземпляру Fragment. (GoogleMap был по существу фрагментом внутри фрагмента). Я настраиваю обратный вызов и программно загружаю карту с этим. Я хотел бы установить itsMapViewCreatedListener внутри конструктора MySupportMapFragment, но использовать что-либо, кроме конструкторов без параметров, не рекомендуется.
itsMySupportMapFragment = new MySupportMapFragment();
MapViewCreatedListener mapViewCreatedListener = new MapViewCreatedListener() {
@Override
public void onMapCreated() {
initPlacesGoogleMapCtrl();
}
};
itsMySupportMapFragment.itsMapViewCreatedListener = mapViewCreatedListener;
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.mapFragmentContainer, itsMySupportMapFragment);
transaction.addToBackStack(null);
transaction.commit();
И затем, когда я вернусь, я могу получить карту; не более null!
public void initPlacesGoogleMapCtrl() {
// Map ready, get it.
GoogleMap googleMap = itsMySupportMapFragment.getMap();
// Do what you want...
}
Ответ 3
Я бы прокомментировал ответ CommonsWare, но у меня недостаточно отзывов. В любом случае, у меня также была эта проблема: getMap() вернет null в onActivityCreated. Моя настройка такова: у меня есть MainActivity, которая содержит фрагмент. В методе onCreateView этого фрагмента я создал SupportMapFragment, а затем добавил его к фрагменту через childFragmentManager. Я продолжал ссылаться на SupportMapFragment и ожидал, что он даст мне карту в onActivityCreated, которой она не была. Решение этой проблемы состояло в том, чтобы переопределить onActivityCreated SupportMapFragment, но не родительский фрагмент. Я сделал это в onCreateView:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_location, container, false);
mMapFragment = new SupportMapFragment() {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mMap = mMapFragment.getMap();
if (mMap != null) {
setupMap();
}
}
};
getChildFragmentManager().beginTransaction().add(R.id.framelayout_location_container, mMapFragment).commit();
return v;
}
Ответ 4
В прошлом месяце (декабрь 2014 года) Google официально разрешил эту проблему. В новейшем (6.5) сервисе Google Play:
Метод getMap() в MapView и MapFragment теперь устарел в пользу нового метода getMapAsync().
С помощью getMapAsync(OnMapReadyCallback callback)
вы можете настроить прослушиватель, когда GoogleMap готов. Он передается в обратном вызове и предоставляется непустым.
Google предоставил пример кода для этого:
public class MainActivity extends FragmentActivity
implements OnMapReadyCallback {
...
}
и при инициализации фрагмента:
MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
когда карта готова, вы получите обратный вызов
@Override
public void onMapReady(GoogleMap map) {
map.addMarker(new MarkerOptions()
.position(new LatLng(0, 0))
.title("Marker"));
}
Ответ 5
Вы также можете использовать MapsInitializer.initialize(context);
, если проблема связана с не инициализированными библиотеками.
Ответ 6
С последними GoogleServices вы можете использовать MapFragment.getMapAsync.
Непосредственно из документов
Устанавливает объект обратного вызова, который будет запущен, когда экземпляр GoogleMap готов к использованию.
Ответ 7
если map == null, тогда найдите карту
if (mGoogleMap == null)
{
SupportMapFragment mapFragment1 = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment1.getMapAsync(this);
}
а затем вызовите функцию onMapReady();