4

I'm trying to get GoogleMap object from a Fragment, which is on the second page of ViewPager, whose contents are given with FragmentPagerAdapter.

My ViewPager consist of two pages: an ordinary layout, and a Google map.

I can access to the first layout doing this:

View tempView = LayoutInflater.from(getApplication())
                .inflate(R.layout.start_activity, null);
tempTextView = (TextView) tempView.findViewById(R.id.timer);

Everything is OK here. But I also want to access Google maps.
When the map was in a separate activity, I could get GoogleMap object doing this:

map=((SupportMapFragment)getSupportFragmentManager()
    .findFragmentById(R.id.map)).getMap();

But now the above line returns null

The question is how to get GoogleMap object from fragment now?

They suggest doing this (some people say this works), but it doesn't take effect for me:

map = ((SupportMapFragment) getSupportFragmentManager()
      .findFragmentByTag("android:switcher:" + R.id.pager + ":1")).getMap();

I'm providing the code here.

azizbekian
  • 60,783
  • 13
  • 169
  • 249

2 Answers2

7

I've found the solution here, but will post here too for other users to see the code and not get stuck for weeks like I did.

MyPagerAdapter.java

public class MyPagerAdapter extends FragmentPagerAdapter
{
    private Context context;
    final LatLng    YEREVAN = new LatLng(40.181, 44.513);

    public MyPagerAdapter(FragmentManager fm, Context context)
    {
        super(fm);
        this.context = context;
    }

    @Override
    public Fragment getItem(int position)
    {
        switch (position)
        {
            case 0:
                return new MyFragment();
            case 1:
                return MyMapFragment.newInstance(YEREVAN);
        }
        return null;
    }

    @Override
    public int getCount()
    {
        return 2;
    }

    @Override
    public CharSequence getPageTitle(int position)
    {
        Locale l = Locale.getDefault();
        switch (position)
        {
            case 0:
                return context.getString(R.string.start).toUpperCase(l);
            case 1:
                return context.getString(R.string.map).toUpperCase(l);
        }
        return null;
    }
}

MyMapFragment.java

public class MyMapFragment extends SupportMapFragment
{
    private LatLng  latLon;

    public MyMapFragment()
    {
        super();
    }

    public static MyMapFragment newInstance(LatLng position)
    {
        MyMapFragment frag = new MyMapFragment();
        frag.latLon = position;
        return frag;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View v = super.onCreateView(inflater, container, savedInstanceState);
        initMap();
        return v;
    }

    private void initMap()
    {
        UiSettings settings = getMap().getUiSettings();
        settings.setAllGesturesEnabled(false);
        settings.setMyLocationButtonEnabled(false);

        getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(latLon, 16));
        getMap().addMarker(new MarkerOptions().position(latLon).icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));
    }
}
Community
  • 1
  • 1
azizbekian
  • 60,783
  • 13
  • 169
  • 249
1

The problem is that your MyFragmentPagerAdapter doesn't use SupportMapFragments, but only adds MyFragments. You should change its getItem function to something like this:

public Fragment getItem(int position) {
    Fragment fragment;
    switch (position) {
    case 0:
        fragment = new MyFragment();
        break;
    case 1:
        fragment = new MySupportMapFragment();
        break;
    }
    Bundle args = new Bundle();
    args.putInt(MyFragment.ARG_SECTION_NUMBER, position);
    fragment.setArguments(args);
    return fragment;
}

For that you have to implement your own type MySupportMapFragment where you load your layout, similar with what you did with MyFragment.

Then you can call your SupportMapFragment directly from the FragmentPagerAdapter. Like:

SupportMapFragment supportMapFragment = 
    (SupportMapFragment) mMyFragmentPagerAdapter.getItem(1);
map = supportMapFragment.getMap();

Once added to the adapter, you should get the SupportMapFragment you are expecting.

Terry
  • 14,529
  • 13
  • 63
  • 88
  • I get `ClassCastException`: MyFragment cannot be cast to SupportMapFragment. Are you sure the `getItem()` method is working properly? I've left it untouched, it was created automatically by android. – azizbekian Mar 17 '13 at 17:07
  • I see. Well, `getItem()` returns a `Fragment`, and I just wanted to downcast it to `SupportMapFragment`. But with a look at your code, it seems you never create a SupportMapFragment, but only a normal Fragment with a view with a map. You should change your method `getItem(int position)` in `MyFragmentPagerAdapter`, so that it returns a Fragment at position 0, and a SupportMapFragment at position 1. I will edit my answer and show you in a minute... – Terry Mar 17 '13 at 17:34
  • "For that you have to implement your own type MySupportMapFragment where you load your layout, similar with what you did with MyFragment" -> should the `MySupportMapFragment` extend `Fragment` or `MapFragment`? If `Fragment`, then it's useless, because I inflate my view checking the fragment attributes. If `MapFragment`, then adapter's `getItem()` complains, because it returns `Fragment` instead of `MapFragment`. What should I do? – azizbekian Mar 19 '13 at 16:24
  • `MySupportMapFragment` should implement `SupportMapFragment`. So, for case (1) your MyFragmentPagerAdapter returns a SupportMapFragment. Since SupportMapFragment extends Fragment, it shouldn't complain. Then, if you say `(SupportMapFragment) mMyFragmentPagerAdapter.getItem(1);` you should be able to cast to a SupportMapFragment. – Terry Mar 19 '13 at 20:12
  • I've changed my code. So now the `ViewPager` has only 1 page (the map). Look at the code above, please, I've edited the post. Still the `gMap` is `null`. What is incorrect here? – azizbekian Mar 20 '13 at 09:28