简体   繁体   English

Google Maps Fragment替换当前片段

[英]Google Maps Fragment replacing current fragment

Background: 背景:
Create an app that will center on the user's location and allow for them to text their location to contacts. 创建一个应用程序,该应用程序将以用户的位置为中心,并允许他们将其位置发送给联系人。 To do this, we need a simple credential check and server address to test on in the preferences. 为此,我们需要一个简单的凭据检查和服务器地址以在首选项中进行测试。

Issue: 问题:
Whenever the user navigates from the original map fragment that shows their location with a marker, the proper map type (hybrid), etc. to another fragment and then wants to return to the map fragment, it defaults to LatLng 0,0 and a generic map (no indication of user location for example). 每当用户从使用标记,正确的地图类型(混合)等显示其位置的原始地图片段导航到另一个片段,然后想要返回到地图片段时,它默认为LatLng 0,0和通用地图(例如,不显示用户位置)。

My initial thought was to try and save the state of the map fragment upon switching to another fragment and reload that when popping the other fragment from the stack. 我最初的想法是尝试在切换到另一个片段时保存映射片段的状态,并在从堆栈中弹出另一个片段时重新加载它。 However I then thought it might be simpler to just replace the current fragment in the MainActivity whenever I need to switch. 但是我当时认为,只要需要切换,只需在MainActivity中替换当前片段可能会更简单。 So on opening the app, MainActivity creates a new MapFragment then replaces it with a Preferences Fragment and when 'saving' creates a new MapFragment to replace the current fragment with. 因此,在打开应用程序时,MainActivity创建一个新的MapFragment,然后将其替换为Preferences Fragment,并在“保存”时创建一个新的MapFragment,以替换当前的Fragment。 Thought this might fix my problem as on initial load the map functions like I want. 以为这可能解决了我的问题,因为在初始加载时,地图功能就像我想要的那样。

The code for MFragment that contains the Map Fragment: MFragment的代码,其中包含Map Fragment:

public class MFragment extends Fragment implements android.location.LocationListener,
                    GooglePlayServicesClient.ConnectionCallbacks, 
                    GooglePlayServicesClient.OnConnectionFailedListener{

private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private static GoogleMap map;
private static LocationClient lClient;
private final static String TAG = "MFragment";
private String provider;
private Location loc;
private LocationManager lManager;
private LatLng currentLatLng;
private final long MIN_TIME = 1000;
private final float MIN_DIST = 10;
private Update updateMarkers = new Update();
private View view;
private MapFragment mFrag;

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    mFrag = MapFragment.newInstance();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState)  {
    super.onCreateView(inflater, container, savedInstanceState);
    //sets the layout for this fragment
    view = inflater.inflate(R.layout.fragment_map, container, false);
    //insert MapFragment into this Fragment 
    getActivity().getFragmentManager().beginTransaction()
            .replace(R.id.mapview, mFrag)
            .commit();
    //get a handle on the map from the MapFragment
//      map = mFrag.getMap();
    //instantiates the location manager
    lManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
    //instantiate the location client
    lClient = new LocationClient(getActivity(), this, this);
    lClient.connect();
    //run through initialization of all objects 
    setUpMapIfNeeded();
    Log.d(TAG, "Successfully created MFragment");
    return view;
}

/**
 * instantiates map from the MapFragment if map is null.  
 */
private void setUpMapIfNeeded() {
    if (getActivity() != null && getActivity().getFragmentManager() != null &&
            map == null)    {
        map = mFrag.getMap();
        Log.d(TAG, "Map generated.");
        setUpMap();
    }   else if (lClient.isConnected()) {
        updateMap();
    }   else    {
        setUpMap();
    }
}

/**
 * sets up the location data for the map.  conditional clause so that the GPS doesn't crash
 * if the app can't get a location straight away.
 */
private void setUpMap() {
    if (map != null) {
        map.setMyLocationEnabled(true);
        map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        Criteria crit = new Criteria();
        provider = lManager.getBestProvider(crit, false);
        if (lManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            loc = lManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        }   else {
            loc = lManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        }
        lManager.requestLocationUpdates(provider, MIN_TIME, MIN_DIST, this);

    }
}


protected void updateMap()  {
    if (servicesConnected())    {
        map.clear();
        currentLatLng = new LatLng(this.loc.getLatitude(), this.loc.getLongitude());
        map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 14));
        map.addMarker(new MarkerOptions()
                    .position(currentLatLng)
                    .title("You"));
        map.setOnMarkerClickListener(new OnMarkerClickListener() {

            @Override
            public boolean onMarkerClick(Marker m) {
                SMSFragment sFrag = new SMSFragment();
                sFrag.setMarker(m);
                getActivity().getFragmentManager().beginTransaction()
                    .replace(android.R.id.content, sFrag)
                    .commit();
                return false;
            }
        });

    }
}

/**
 * checks for connection to google play services
 * @return
 */
private boolean servicesConnected() {
    int resultCode = GooglePlayServicesUtil
            .isGooglePlayServicesAvailable(getActivity().getApplicationContext());
    if (ConnectionResult.SUCCESS == resultCode) {
        Log.d(TAG, getString(R.string.play_available));
        return true;
    } else {
        if (GooglePlayServicesUtil.isUserRecoverableError(resultCode))  {
            GooglePlayServicesUtil
                .getErrorDialog(resultCode, getActivity(), 
                    CONNECTION_FAILURE_RESOLUTION_REQUEST).show();
        }   else    {
            Log.i(TAG, "This device is not supported");
        }
        return false;
    }
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    if (connectionResult.hasResolution())   {
        try {
            connectionResult
                .startResolutionForResult(getActivity(), CONNECTION_FAILURE_RESOLUTION_REQUEST);
        }   catch (IntentSender.SendIntentException e)  {
            e.printStackTrace();
        }
    }   else    {
        Toast.makeText(getActivity(), R.string.connect_failed, Toast.LENGTH_SHORT).show();
    }
}

/**
 * Called after location client connects
 */
@Override
public void onConnected(Bundle arg0) {
    updateMap();
}

/**
 * simple display message after disconnecting.
 */
@Override
public void onDisconnected() {
    Toast.makeText(getActivity(), R.string.disconnected, Toast.LENGTH_SHORT).show();
}


public void onStart()   {
    super.onStart();
    lClient.connect();
    setUpMapIfNeeded();
}

public void onResume()  {
    super.onResume();
    lClient.connect();
    setUpMapIfNeeded();
}

public void onPause()   {
    lClient.disconnect();
    super.onPause();
}

public void onStop()    {
    lClient.disconnect();
    super.onStop();
}

public void onDestroy() {
    lClient.disconnect();
    super.onDestroy();
}

@Override
public void onLocationChanged(Location location) {
    this.loc = location;
    updateMap();
}

@Override
public void onProviderDisabled(String provider) {
    // TODO Auto-generated method stub

}

@Override
public void onProviderEnabled(String provider) {
    // TODO Auto-generated method stub

}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
    // TODO Auto-generated method stub

}


public void updateMarkers(List<Record> records){
    //update map with markers corresponding to each latitude, longitude passed back from records
    for (Record r : records){
        map.addMarker( new MarkerOptions()
                .position(new LatLng(r.getValueOfLatitude(), r.getValueOfLongitude())));
    }
}

private class Update extends AsyncTask<Void, Void, Boolean> {

    private List<Record> records;

    protected Update()  {
        super();
        records = new ArrayList<Record>();
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        Connect conn = new Connect(getActivity());
        try {
            records = conn.getAll();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    protected void onPostExecute(Boolean result)    {
        if (result) {
            updateMarkers(records);
        }   else    {
            Toast.makeText(getActivity(), R.string.rec_fail, Toast.LENGTH_SHORT).show();
        }
    }
}
}

And an example of replacing the Fragment from another Fragment (From PrefsFragment to MFragment): 以及从另一个片段(从PrefsFragment到MFragment)替换Fragment的示例:

    register = (Button) v.findViewById(R.id.register);

    save.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            saveToPreferences(v);
            ((MainActivity)getActivity()).replaceFragment();
        }
    });

    register.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            getActivity().getFragmentManager().beginTransaction()
                .replace(android.R.id.content, new RegFragment())
                .commit();
        }
    });

    return v;
}

the save button calls a method in MainActivity to replace the current fragment with a MapFragment as an attempted work-around but doesn't function like I was hoping and using the similar method for the register button using FragmentManager doesn't fix the Map issue either. 保存按钮会调用MainActivity中的方法来尝试用MapFragment替换当前片段,但无法正常运行,就像我希望的那样,并且使用FragmentManager对注册按钮使用类似方法也无法解决Map问题。

Any help is appreciated. 任何帮助表示赞赏。

Don't put a fragment inside another fragment unless you really need to. 除非确实需要,否则请勿将一个片段放在另一个片段中。 If you choose to do so, you may not use the FragmentManager of the Activity like you do. 如果您选择这样做,则可能不会像以前那样使用ActivityFragmentManager Instead you must use the child fragment manager of the container fragment to create the fragment transaction that will insert the child fragment by calling getChildFragmentManager() . 相反,您必须使用容器片段的子片段管理器来创建片段事务,该事务将通过调用getChildFragmentManager()来插入子片段。

This is supported since API level 17 (Android 4.2) or using the most recent Android Support Library. 自API级别17(Android 4.2)或使用最新的Android支持库以来,就支持此功能。 I suggest you to always use the support library by default. 我建议您默认情况下始终使用支持库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM