背景
我有一个包含三个片段的viewpager。所有片段都是使用自定义地图布局或列表视图的相同片段类的新实例,具体取决于应用程序设置。但问题只出在地图模式中。
问题
每次我在地图模式下启动viewpager活动时,只有当前片段显示地图。其他碎片是空的。看起来所有片段都使用了map的唯一实例。当前片段首先获得此地图。其他两个片段中的地图为空。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<include
layout="@layout/loading_component"/>
<FrameLayout
android:id="@+id/mapFragmentHole"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_gravity="center_vertical|center_horizontal" />
<Button
android:id="@+id/cur_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/map_compas"
android:layout_alignParentRight="true"/>
<Button
android:id="@+id/go_back"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:textColor="@color/gray_theatre"
android:textSize="21sp"
android:textStyle="bold"
android:background="@drawable/go_to_list_button_bg"
android:text="@string/return_to_list"
android:layout_alignParentRight="true"
android:visibility="gone"/>
</RelativeLayout>
SectionsPagerAdapter
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public Fragment getItem(int i) {
if (i == 0) {
return CinemaAllFragment.newInstance(modeFavourite);
//return new CinemaFavouriteFragment();
}
if (i == 1) {
return CinemaAllFragment.newInstance(modeOnline);
}
if (i == 2) {
return CinemaAllFragment.newInstance(modeDefault);
}
return null;
}
@Override
public int getCount() {
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getString(R.string.frame_cinema_title1);
case 1:
return getString(R.string.frame_cinema_title2);
case 2:
return getString(R.string.frame_cinema_title4);
}
return null;
}
}
我的片段
public class CinemaAllFragment extends CinemaFragment implements LocationListener {
private LocationManager locationManager;
private String provider;
private GoogleMap map = null;
private Marker myPosition;
private View balloon;
private Button curLocationBtn;
protected ListView listViewCinemas = null;
protected View view;
private String fragmentMode;
private static String MODE = "mode";
private static String modeFavourite = "modeFavourite";
private static String modeOnline = "modeOnline";
private static String modeDefault = "modeDefault";
private Cinema[] cinemas;
private Long updateTime;
private Long lastUpdate;
private CinemaListArrayAdapter adapter = null;
private static String FRAGMENT = "position";
private ArrayList<Marker> Markers;
private long nowTime;
// Handler to update UI timeFr, progress bar etc,.
private Handler mHandler = new Handler();
private Runnable onEveryFiveMinutes;
private SupportMapFragment supportMapFragment = null;
public static CinemaAllFragment newInstance(String someString)
{
CinemaAllFragment myFragment = new CinemaAllFragment();
Bundle args = new Bundle();
args.putString(MODE, someString);
myFragment.setArguments(args);
return myFragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
super.onCreateView(inflater, container, savedInstanceState);
if(getArguments()!=null)
fragmentMode = getArguments().getString(MODE, null);
if (Settings.getCinemaTypeView() == Settings.CinemaTypeView.Map)
{
mLog.d("OnCreate: map "+fragmentMode);
view = inflater.inflate(R.layout.cinema_map, container, false);
GoogleMapOptions gmo = (new GoogleMapOptions()).zoomControlsEnabled(true).rotateGesturesEnabled(false);
if(supportMapFragment == null)
supportMapFragment = SupportMapFragment.newInstance(gmo);
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.mapFragmentHole, supportMapFragment);
fragmentTransaction.commit();
balloon = inflater.inflate(R.layout.cinema_list_item, null);
ImageView delimiter = (ImageView) balloon.findViewById(R.id.delimiter);
delimiter.setVisibility(View.GONE);
}
else if (Settings.getCinemaTypeView() == Settings.CinemaTypeView.Listing)
{
view = inflater.inflate(R.layout.cinema_list, container, false);
}
return view;
}
@Override
public void onResume() {
super.onResume();
if (Settings.getCinemaTypeView() == Settings.CinemaTypeView.Map)
{
setUpMapIfNeeded();
}
onUpdate();
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (Settings.getCinemaTypeView() == Settings.CinemaTypeView.Map)
{
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.remove(supportMapFragment);
ft.commit();
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
}
class CustomInfoAdapter implements GoogleMap.InfoWindowAdapter {
@Override
public View getInfoContents(Marker marker) {
displayView(marker);
if(!marker.getTitle().equals("Я"))
{
return balloon;
}
else return null;
}
@Override
public View getInfoWindow(Marker marker) {
return null;
}
}
public void displayView(Marker marker) {
TextView cinema_title = (TextView) balloon.findViewById(R.id.cinema_title);
Cinema cinema = MoviesDbAdapter.getCinemaById(marker.getTitle());
if (cinema != null)
{
cinema_title.setText(cinema.title);
}
}
public void checkGPSEnabled()
{
// Get the location manager
locationManager = (LocationManager) view.getContext().getApplicationContext().getSystemService(view.getContext().getApplicationContext().LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER/*provider*/, 0, 0, this);
boolean enabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// Check if enabled and if not send user to the GSP settings
// Better solution would be to display a dialog and suggesting to
// go to the settings
if (!enabled) {
new AlertDialog.Builder(view.getContext().getApplicationContext())
.setMessage(view.getContext().getApplicationContext().getResources().getString(R.string.message_gps_off))
.setPositiveButton(view.getContext().getApplicationContext().getResources().getString(R.string.dialog_gps_enable), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, 5);
}
})
.setNegativeButton(view.getContext().getApplicationContext().getResources().getString(R.string.dialog_gps_cancel), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
}
}
/* Request updates at startup */
@Override
public void onLocationChanged(Location location) {
int lat = (int) (location.getLatitude());
int lng = (int) (location.getLongitude());
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {
//getLocation();
}
@Override
public void onProviderDisabled(String provider) {
}
/**
* Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
* installed) and the map has not already been instantiated.. This will ensure that we only ever
* call {@link #setUpMap()} once when {@link #map} is not null.
* <p>
* If it isn't installed {@link SupportMapFragment} (and
* {@link com.google.android.gms.maps.MapView
* MapView}) will show a prompt for the user to install/update the Google Play services APK on
* their device.
* <p>
* A user can return to this Activity after following the prompt and correctly
* installing/updating/enabling the Google Play services. Since the Activity may not have been
* completely destroyed during this process (it is likely that it would only be stopped or
* paused), {@link #onCreate(Bundle)} may not be called again so we should call this method in
* {@link #onResume()} to guarantee that it will be called.
*/
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (map == null) {
//map = (MapView) getActivity().findViewById(R.id.map);
// Try to obtain the map from the SupportMapFragment.
map = supportMapFragment.getMap();
//map.setInfoWindowAdapter(new CustomInfoAdapter());
// Check if we were successful in obtaining the map.
if (map != null) {
setUpMap();
}
}
}
private void getLocation()
{
mLog.d("Touch: ");
checkGPSEnabled();
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER/*provider*/);
// Initialize the location fields
if (location != null) {
System.out.println("Provider " + provider + " has been selected.");
CameraPosition cp = new CameraPosition.Builder()
.target(new LatLng(location.getLatitude(),location.getLongitude()))
.zoom(12)
.build();
map.animateCamera(CameraUpdateFactory.newCameraPosition(cp));
if (myPosition != null)
{
myPosition.remove();
}
myPosition = map.addMarker(new MarkerOptions()
.position(new LatLng(location.getLatitude(),location.getLongitude()))
.title("Я")
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.map_marker_user)));
}
}
/**
* This is where we can add markers or lines, add listeners or move the camera. In this case, we
* just add a marker near Africa.
* <p>
* This should only be called once and when we are sure that {@link #map} is not null.
*/
private void setUpMap() {
map.setMyLocationEnabled(true);
//map.getUiSettings().setMyLocationButtonEnabled(true);
//map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
}
public void onUpdate() {
if(fragmentMode != null)
{
if(fragmentMode.equals(modeDefault)){
cinemas = MoviesDbAdapter.getCinemaAll();
}
else if (fragmentMode.equals(modeFavourite))
{
cinemas = MoviesDbAdapter.getCinemaFavorites();
}
else if (fragmentMode.equals(modeOnline))
{
cinemas = MoviesDbAdapter.getCinemaOnline();
}
mLog.d("OnCreate: "+fragmentMode);
}
else
{
cinemas = MoviesDbAdapter.getCinemaAll();
}
adapter = new CinemaListArrayAdapter(getActivity(), R.layout.movies_list_item, cinemas);
mLog.d("OnCreate: onUpdate "+fragmentMode);
if(cinemas.length == 0)
{
// Load schedules
//Utils.updateLoadingStatus(view, getString(R.string.message_loading_cinemas));
}
if (Settings.getCinemaTypeView() == Settings.CinemaTypeView.Map)
{
try
{
checkGPSEnabled();
} catch (Exception e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
//ApiDownloader downloader = new ApiDownloader(getActivity().getApplicationContext());
//downloader.registerAPI(getActivity().getApplicationContext());
if (Markers != null)
{
for (Marker marker : Markers)
{
marker.remove();
}
Markers.clear();
}
Markers = new ArrayList<Marker>();
if(map != null)
{
//нарисовать маркеры кинотеатров
for (Cinema cinema : cinemas)
{
//mLog.d("Cinema: " + cinema.getLatitude());
Marker cinemaMarker = map.addMarker(new MarkerOptions()
.position(new LatLng(Double.parseDouble(cinema.getLatitude()),Double.parseDouble(cinema.getLongitude())))
.title(cinema.getId().toString())
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.map_marker_mini)));
Markers.add(cinemaMarker);
}
}
}
else
{
//ApiDownloader downloader = new ApiDownloader(getActivity().getApplicationContext());
//downloader.registerAPI(getActivity().getApplicationContext());
listViewCinemas = (ListView) view.findViewById(R.id.cinemas_list_view);
int index = 0;
View v=null;
if(listViewCinemas != null)
{
mLog.d("OnCreate: list not null "+fragmentMode+" "+cinemas.length);
// save index and top position
index = listViewCinemas.getFirstVisiblePosition();
v = listViewCinemas.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
listViewCinemas.setAdapter(adapter);
listViewCinemas.setSelectionFromTop(index, top);
PauseOnScrollListener listener = new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling);
listViewCinemas.setOnScrollListener(listener);
}
}
}
}
答案 0 :(得分:2)
解决问题
只需将片段与地图功能分开,而不是映射到两个新片段中。新的地图片段从SupportMapFragment扩展,并允许他为himlesf创建视图:
public class CinemaMapFragment extends SupportMapFragment implements LocationListener {
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
view = super.onCreateView(inflater, container, savedInstanceState);
balloon = inflater.inflate(R.layout.cinema_list_item, null);
return view;
}
然后我以编程方式添加自定义功能(只需两个按钮):
@Override
public void onResume() {
super.onResume();
LayoutInflater inflater = (LayoutInflater) getActivity().getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View vi = inflater.inflate(R.layout.location_button, null);
View vi2 = inflater.inflate(R.layout.golist_button, null);
curLocationBtn = (Button) vi.findViewById(R.id.cur_location);
goToList = (Button) vi2.findViewById(R.id.go_back);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
((ViewGroup) view).addView(vi, layoutParams);
LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT);
((ViewGroup) view).addView(vi2, layoutParams2);
...
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (map == null) {
//map = (MapView) getActivity().findViewById(R.id.map);
// Try to obtain the map from the SupportMapFragment.
map = getMap();
map.setInfoWindowAdapter(new CustomInfoAdapter());
// Check if we were successful in obtaining the map.
if (map != null) {
setUpMap();
}
}
}