Search code examples
androidxamarinandroid-appcompatfragmentmanager

Xamarin, Android. Google Maps and AppCompat FragmentManager.FindFragmentById returns null


i'm trying to use the Google Maps ( 27.0.0.0 ) with AppCompat on Xamarin. Everything works fine and the Maps is showed in a Fragment, but when i try to get the fragment references using:

SupportMapFragment  m_mpMapFragment = ( SupportMapFragment ) FragmentManager.FindFragmentById( Resource.Id.Gmap );

I get always m_mpMapFragment as null. I got this error in the past with another app and i fix it just deleting all Xamarin Support V7. But this time i'm using AppCompat and i can't delete the references from V7 support.

My project had two Class: MainActivity and MapAroundMeFragment that show the map in a Fragment after the user clicked on a Tabbar. In MainActivity i have "Main.axml" and in my MapAroundMeFragment i have "MapAroundMeFragmentLayout.xaml".

I found another way to fix this problem by using this "trick":

SetContentView( Resource.Layout.MapAroundMeFragmentLayout );
SetContentView( Resource.Layout.Main );

in my MainActivity, and so, in my MapAroundMeFragment

SupportMapFragment  m_mpMapFragment = ( SupportMapFragment ) FragmentManager.FindFragmentById( Resource.Id.Gmap );

give me back a valid m_mpMapFragment! I can't understand why. Anyone can help me?

This is my MainActivity

using System;

using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Gms.Maps;
using Android.Support.V7.App;

using ActionBar = Android.Support.V7.App.ActionBar;
using Fragment  = Android.Support.V4.App.Fragment;

namespace OscarFinder_AndroidOS {
    [Activity(Label = "OscarFinder_Android", Theme = "@style/Theme.Customab", Icon = "@drawable/ic_launcher", MainLauncher = true)]
    public class MainActivity : ActionBarActivity, ActionBar.ITabListener {    

    private Fragment m_fCurrentFragment;

    protected override void OnCreate( Bundle bundle ) {
        base.OnCreate (bundle);

        var setting = Android.Support.V7.App.ActionBar.NavigationModeTabs;
        SupportActionBar.NavigationMode = setting;

        // Set our view from the "main" layout resource
        /* trick!! */SetContentView( Resource.Layout.MapAroundMeFragmentLayout );
        SetContentView( Resource.Layout.Main );

        CreateAndInitTabs();
    }

    private void CreateAndInitTabs() {
        /* Tab riservata alla Home */
        var homeTab = SupportActionBar.NewTab();
        homeTab.SetText( "Home" );
        homeTab.SetTabListener( this );
        SupportActionBar.AddTab( homeTab );

        /* Tab riservata alla Mappa */
        var mapTab = SupportActionBar.NewTab();
        mapTab.SetText( "Map" );
        mapTab.SetTabListener( this );
        SupportActionBar.AddTab( mapTab );

        /* Tab riservata alla Mappa */
        var optionTab = SupportActionBar.NewTab();
        optionTab.SetText( "Option" );
        optionTab.SetTabListener( this );
        SupportActionBar.AddTab( optionTab );
    }

    public override bool OnOptionsItemSelected( IMenuItem iItem ) {

        return base.OnOptionsItemSelected( iItem );
    }

    public void OnTabReselected( ActionBar.Tab iTab, Android.Support.V4.App.FragmentTransaction iFragment ) {

    }

    public void OnTabSelected( ActionBar.Tab iTab, Android.Support.V4.App.FragmentTransaction iFragment ) {

        if ( iTab.Position == 0 ) {
            m_fCurrentFragment = new HomeOscarFinderFragment();
        }
        else if ( iTab.Position == 1 ) {
            m_fCurrentFragment = new MapAroundMeFragment();
        }

        iFragment.Replace( Android.Resource.Id.Content, m_fCurrentFragment );
    }

    public void OnTabUnselected( ActionBar.Tab iTab, Android.Support.V4.App.FragmentTransaction iFragment ) {
        if ( m_fCurrentFragment != null ) {
            iFragment.Detach( m_fCurrentFragment );
        }
    }
    }
}

Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

MapAroundMeFragment

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;

using Android.Support.V4.App;
using Fragment          = Android.Support.V4.App.Fragment;
using FragmentManager   = Android.Support.V4.App.FragmentManager;

using Android.Gms.Maps;
using Android.Gms.Maps.Model;

namespace OscarFinder_AndroidOS {

    public class MapAroundMeFragment : Fragment, IOnMapReadyCallback {

        private GoogleMap           m_gMap;
        private SupportMapFragment  m_mpMapFragment;
        private float               m_fCurrentZoom      = 15.0f;
        private CustomMapPosition   m_pMapPosition;

        public override void OnCreate( Bundle savedInstanceState ) {
            base.OnCreate( savedInstanceState );
        }

        public override View OnCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {

            var view = inflater.Inflate( Resource.Layout.MapAroundMeFragmentLayout, container, false );

            m_mpMapFragment = ( SupportMapFragment ) FragmentManager.FindFragmentById( Resource.Id.Gmap );

            m_mpMapFragment.GetMapAsync( this );

            UpdateMap();

            return view;
        }

        public void OnMapReady( GoogleMap googleMap ) {
            m_gMap = googleMap;
        }

        private void UpdateMap() {

            m_gMap = m_mpMapFragment.Map;

            if ( m_gMap != null ) {

            }
        }
    }
}

MapAroundMeFragmentLayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/test_fragment"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <fragment
        android:layout_below="@+id/LocationSpecsHeader"
        android:id="@+id/Gmap"
        android:tag="MyMap"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:enabled="true"
        android:clickable="true"
        app:cameraZoom="16"
        class="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>

Thanks a lot!


Solution

  • I solved by using this code.

    In MapAroundMeFragment

    public override View OnCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
    
                var view = inflater.Inflate( Resource.Layout.MapAroundMeFragmentLayout, container, false );
    
                /* Eggià,
                 * creo il fragment della mappa manualmente, perchè, per qualche motivo, non c'è
                 * modo di farlo funzionare prendendolo direttamente dall'inflate. */ 
                MapAroundMeSupportMapFragment mapFragment = new MapAroundMeSupportMapFragment();
                Android.Support.V4.App.FragmentTransaction transaction = FragmentManager.BeginTransaction();
                transaction.Add( Resource.Id.map_container, mapFragment ).Commit();
                mapFragment.GetMapAsync( this );
    
                return view;
            }
    

    In MapAroundMeSupportFragment

    public class MapAroundMeSupportMapFragment : SupportMapFragment {
    
            public void onActivityCreated( Bundle savedInstanceState ) {
                base.OnActivityCreated( savedInstanceState );
            }
        }
    

    Everything works fine now.. I hope!