问题
I'm using Google Maps API V2 in an activity wih drop down navigation where the map is on the second position.
I'm adding the map pragmatically like:
mMapFragment = supportMapFragment.newInstance();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.placeHolder, mMapFragment, TAG_MAP)
.commit();
I want to get the GoogleMap ovject, as the documentation https://developers.google.com/maps/documentation/android/map say it should be done with mMapFragment.getMap()
, but it returns null.
according to http://developer.android.com/reference/com/google/android/gms/maps/SupportMapFragment.html it returns null if the Fragment hasn't gone through the onCreateView lifecycle event.
how can I know whenever the fragment is ready ?
EDIT: I found this How do I know the map is ready to get used when using the SupportMapFragment?
Overriding onActivityCreated seems like a solution, but then I'll have to instantiate the fragment through a constructor and not with newInstance(), does it make any difference ?
回答1:
My preferred method is to use a callback to get a signal from a Fragment
. Also, this is the recommended method proposed by Android at Communicating with the Activity
For your example, in your Fragment
, add an interface and register it.
public static interface OnCompleteListener {
public abstract void onComplete();
}
private OnCompleteListener mListener;
public void onAttach(Context context) {
super.onAttach(context);
try {
this.mListener = (OnCompleteListener)context;
}
catch (final ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement OnCompleteListener");
}
}
Now implement this interface in your Activity
public class MyActivity extends FragmentActivity implements MyFragment.OnCompleteListener {
//...
public void onComplete() {
// After the fragment completes, it calls this callback.
// setup the rest of your layout now
mMapFragment.getMap()
}
}
Now, whatever in your Fragment
signifies that it's loaded, notify your Activity
that it's ready.
@Override
protected void onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// create your fragment
//...
// signal that you're done and tell the Actvity to call getMap()
mListener.onComplete();
}
EDIT 2017-12-05 onAttach(Activity activity) is deprecated, use onAttach(Context context) instead. Code above adjusted.
回答2:
In addition to Kirk's answer: since public void onAttach(Activity activity)
is deprecated you can now simply use:
@Override
public void onAttach(Context context) {
super.onAttach(context);
Activity activity;
if (context instanceof Activity){
activity=(Activity) context;
try {
this.mListener = (OnCompleteListener)activity;
} catch (final ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnCompleteListener");
}
}
}
The rest remains the same... One might want to use (Fragment sender)
as a parameter though and always pass this
.
回答3:
I'm not sure I'm completely understanding your issue, but I have a similar setup where I'm using a navigation drop down menu. Here's what works for me:
1.) Load the fragment from an xml file and call setupMapIfNeeded()
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.basicMap);
setUpMapIfNeeded();
Here is the xml file for reference:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/basicMap"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
2.) Then setup the map (for details of isGoogleMapsInstalled(), see this question)
private void setUpMapIfNeeded()
{
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null)
{
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.basicMap)).getMap();
// Check if we were successful in obtaining the map.
if(isGoogleMapsInstalled())
{
if (mMap != null)
{
mMap.setOnCameraChangeListener(getCameraChangeListener());
mMap.setInfoWindowAdapter(new MyCustomInfoWindowAdapter(this));
}
}
else
{
MapConstants.showDialogWithTextAndButton(this, R.string.installGoogleMaps, R.string.install, false, getGoogleMapsListener());
}
}
}
3.) Make sure you also call setUpMapIfNeeded() from onResume():
public void onResume()
{
super.onResume();
setUpMapIfNeeded();
}
回答4:
If you want to do it without any listener:
Add Fragment with a TAG
supportFragmentManager
.beginTransaction()
.add(R.id.pagerContainer, UniversalWebViewFragment.newInstance(UniversalWebViewFragment.YOUTUBE_SERACH_URL+"HD trailers"),
"UniversalWebView")
.disallowAddToBackStack()
.commit()
Create a public method in Hosting Activity class which you want to call after fragment is loaded. Here I am calling back a method of my fragment for example
public fun loadURL() {
val webViewFragment = supportFragmentManager
.findFragmentByTag("UniversalWebView")
as UniversalWebViewFragment
webViewFragment.searchOnYoutube("Crysis Warhead")
}
Now inside onViewCreated
Method of your fragment you can simply call that public method of Host activity like this:
(activity as HomeActivity ).loadURL()
来源:https://stackoverflow.com/questions/14999698/android-how-to-notify-activity-when-fragments-views-are-ready