0

背景:
创建一个应用程序,将中心对用户的位置,并允许他们到文本的位置接触。为此,我们需要一个简单的凭证检查和服务器地址在首选项中进行测试。谷歌地图片段取代当前片段

问题:
每当用户从示出了具有标记,正确的地图类型(混合)等,以另一个片段其位置中的原始地图片段导航,然后想要返回到地图片段它默认为LatLng 0,0和一个通用映射(例如没有用户位置的指示)。

我最初的想法是在切换到另一个片段时尝试保存地图片段的状态,并在从堆栈中弹出另一个片段时重新加载该片段。然而,我认为只要需要切换,只需在MainActivity中替换当前片段可能会更简单。因此,在打开应用程序时,MainActivity会创建一个新的MapFragment,然后用Preferences Fragment替换它,并在'保存'时创建一个新的MapFragment来替换当前片段。认为这可能会解决我的问题,因为初始加载地图功能就像我想要的。

包含地图片段为MFragment的代码:

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(); 
     } 
    } 
} 
} 

而且从另一个片段替换片段(来自PrefsFragment到MFragment)的例子:

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; 
} 

保存按钮调用一个方法在MainActivity中用MapFragment代替当前片段作为尝试的解决方法,但不起作用,就像我希望和使用类似的方法使用FragmentManager的注册按钮不会修复Map问题。

任何帮助表示赞赏。

回答

0

除非确实需要,否则不要在另一个片段中放置片段。如果您选择这样做,您可能不会像使用Activity那样使用FragmentManager。相反,您必须使用容器片段的子片段管理器来创建将通过调用getChildFragmentManager()来插入子片段的片段事务。

从API级别17(Android 4.2)开始或使用最新的Android支持库支持此操作。我建议你默认使用支持库。

+0

我可以问一下,在Activity中处理一个Map的最好方法是什么,这样Activity不需要实现一大堆处理它的方法,比如setUpMapIfNeeded(),setUpMap(),updateMap ()等等,Map仍然可以使用一些定制?这是我第一次在应用中使用地图,对缺乏经验表示歉意。 – fakataha

+0

我建议您创建一个扩展MapFragment或SupportMapFragment的类,并在其中放置地图逻辑,setUpMapIfNeeded()方法和其他类。 – BladeCoder