バックグラウンド
3つのフラグメントを持つビューページャーがあります。すべてのフラグメントは、アプリの設定に応じてカスタムマップレイアウトまたはリストビューを使用する同じフラグメントクラスの新しいインスタンスです。しかし、問題はマップモードでのみ発生します。
問題
マップモードでviewpagerアクティビティを開始するたびに、現在のフラグメントのみがマップを表示します。他のフラグメントは空です。すべてのフラグメントがマップの唯一のインスタンスを使用しているように見えます。そして、現在のフラグメントは最初にこのマップを取得します。他の2つのフラグメントのマップはnullです。
<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);
}
}
}
}