【问题标题】:Google Maps Fragment replacing current fragment谷歌地图片段替换当前片段
【发布时间】:2014-04-24 22:58:35
【问题描述】:

背景:
创建一个以用户位置为中心的应用程序,并允许他们将其位置发送给联系人。为此,我们需要一个简单的凭据检查和服务器地址来在首选项中进行测试。

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

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

包含地图片段的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();
        }
    }
}
}

以及从另一个 Fragment 替换 Fragment 的示例(从 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 对注册按钮使用类似的方法并不能修复地图问题。

感谢任何帮助。

【问题讨论】:

    标签: java android google-maps android-fragments android-nested-fragment


    【解决方案1】:

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

    从 API 级别 17 (Android 4.2) 或使用最新的 Android 支持库开始支持此功能。我建议您始终默认使用支持库。

    【讨论】:

    • 那么我可能会问,在 Activity 中处理 Map 的最佳方法是什么,这样 Activity 就不需要实现大量的方法来处理它,例如 setUpMapIfNeeded(), setUpMap()、updateMap() 等,并且 Map 仍然可以使用一些自定义?这是我第一次在应用程序中使用地图,对于缺乏经验深表歉意。
    • 我建议您创建一个扩展 MapFragment 或 SupportMapFragment 的类,并在其中放置地图逻辑、setUpMapIfNeeded() 方法和其余部分。
    猜你喜欢
    • 1970-01-01
    • 2017-06-12
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多