OK, ho finalmente capito questo:
Come suggerito in precedenza, prima ho cambiato la creazione frammento da fare programatically e li aveva aggiunto al gestore frammento bambino, in questo modo:
public override View OnCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstance)
{
var view = inflater.Inflate(Resource.Layout.MyView, viewGroup, false);
// Add fragments to the child fragment manager
// DONT DO THIS, SEE BELOW
var tx = ChildFragmentManager.BeginTransaction();
tx.Add(Resource.Id.lhs_fragment_frame, new LhsFragment());
tx.Add(Resource.Id.rhs_fragment_frame, new RhsFragment());
tx.Commit();
return view;
}
Come previsto, ogni volta che cambio scheda, viene creata un'istanza aggiuntiva di Lhs/RhsFragment, ma ho notato che anche il vecchio Lhs/RhsFragment OnCreateView viene richiamato. Quindi, dopo ogni interruttore di tabulazione, ci sarà un'altra chiamata a OnCreateView. Cambia scheda 10 volte = 11 chiama OnCreateView. Questo è ovviamente sbagliato.
Guardando il codice sorgente per FragmentTabHost, posso vedere che semplicemente scollega e ricollega il frammento del contenuto della scheda quando si passa da una scheda all'altra. Sembra che il ChildFragmentManager di Fragment del genitore stia mantenendo i frammenti del bambino intorno e ricreando automaticamente le loro viste quando il frammento genitore viene riattaccato.
Così, ho spostato la creazione di frammenti di OnCreate, e solo se non ci sta caricando da stato salvato:
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
if (savedInstanceState == null)
{
var tx = ChildFragmentManager.BeginTransaction();
tx.Add(Resource.Id.lhs_fragment_frame, new LhsFragment());
tx.Add(Resource.Id.rhs_fragment_frame, new RhsFragment());
tx.Commit();
}
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstance)
{
// Don't instatiate child fragments here
return inflater.Inflate(Resource.Layout.MyView, viewGroup, false);
}
Questo fissata la creazione delle visualizzazioni aggiuntive e scheda di commutazione è fondamentalmente lavorato oggi.
La domanda successiva era il salvataggio e il ripristino dello stato di visualizzazione. Nei frammenti figli ho bisogno di salvare e ripristinare l'elemento attualmente selezionato. Inizialmente ho avuto qualcosa di simile (questo è OnCreateView del frammento bambino)
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)
{
var view = inflater.Inflate(Resource.Layout.CentresList, container, false);
// ... other code ommitted ...
// DONT DO THIS, SEE BELOW
if (savedInstance != null)
{
// Restore selection
_selection = savedInstance.GetString(KEY_SELECTION);
}
else
{
// Select first item
_selection =_items[0];
}
return view;
}
Il problema di questo è che la scheda host non chiama OnSaveInstanceState quando si passa schede. Piuttosto il frammento del bambino è tenuto in vita e la variabile _selezione può essere lasciata sola.
così ho spostato il codice per il gestore di selezione OnCreate:
public override void OnCreate(Bundle savedInstance)
{
base.OnCreate(savedInstance);
if (savedInstance != null)
{
// Restore Selection
_selection = savedInstance.GetString(BK_SELECTION);
}
else
{
// Select first item
_selection = _items[0];
}
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)
{
// Don't restore/init _selection here
return inflater.Inflate(Resource.Layout.CentresList, container, false);
}
Ora tutto sembra funzionare perfettamente, sia quando si passa linguette e cambiando l'orientamento.
OK, sembra promettente. Come faccio a dire al gonfiatore di usare il gestore del frammento figlio anziché quello genitore? –
Aggiungete il frammento figlio all'interno del vostro frammento genitore facendo in modo che il codice del frammento genitore usi ChildFragmentManager per aggiungere i suoi figli. Quindi l'inflazione che il tuo metodo di callback onCreateView del tuo frammento (figlio) fornisce: https://developer.android.com/reference/android/app/Fragment.html#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle). –
Probabilmente hai bisogno di fare un po 'di googling/stackoverlowing per vedere come gestire i frammenti child in Mono. Non posso aiutarti (io uso Java). –