We want to make a "facebook-like" navigation.
We have 3 tabs, with a ViewPager, so here we have 3 categorizedViewModel (see under). Each page is a TabRootFragment
public partial class MainView : MvxActionBarActivity, ActionBar.ITabListener
public class MvxFragmentTabPagerAdapter<TFragment> : FragmentPagerAdapter where TFragment : Fragment
private ViewPager pager;
protected override void OnCreate(Bundle bundle)
{
...
this.SupportActionBar.NavigationMode = (int)ActionBarNavigationMode.Tabs;
...
this.fragmentTabPagerAdapter = new MvxFragmentTabPagerAdapter<TabRootFragment>(this.SupportFragmentManager);
foreach (var categorizedViewModel in this.MainViewModel.CategorizedViewModels)
{
this.AddPage(this.fragmentTabPagerAdapter, categorizedViewModel);
}
this.pager.Adapter = this.fragmentTabPagerAdapter;
this.pager.SetOnPageChangeListener(new ViewPageListenerForActionBar(this.SupportActionBar));
}
private void AddPage(MvxFragmentTabPagerAdapter<TabRootFragment> adapter, CategorizedViewModel categorizedViewModel)
{
Mvx.Trace("MainView => AddPage {0}", Enum.GetName(typeof(Category), categorizedViewModel.Category));
var nestedFragement = new TestView();
nestedFragement.ViewModel = categorizedViewModel;
var fragment = new TabRootFragment(nestedFragement);
adapter.AddFragment(fragment);
ActionBar.Tab tab = this.SupportActionBar.NewTab();
tab.SetIcon(CategoryHelper.GetDrawableId(categorizedViewModel.Category));
tab.SetTabListener(this);
this.SupportActionBar.AddTab(tab);
}
public void OnTabSelected(ActionBar.Tab tab, FragmentTransaction ft)
{
Mvx.Trace("MainView => OnTabSelected()");
this.pager.SetCurrentItem(this.SupportActionBar.SelectedNavigationIndex, false);
}
We have for each tab (each fragment of the viewPager), a TabRootFragment which has a framelayout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="@+id/ChildFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
And therefore, we want to add some TabChildFragments to this TabRootFragment, in order to have 3 separates stacks of fragments ("facebook-like" :)
public class TabRootFragment : Fragment
{
/// <summary>
/// The root children
/// </summary>
public TabChildFragment rootChildren;
/// <summary>
/// Initializes a new instance of the <see cref="TabRootFragment"/> class.
/// </summary>
/// <param name="rootChildren">The root children.</param>
public TabRootFragment(TabChildFragment rootChildren)
{
this.rootChildren = rootChildren;
}
/// <summary>
/// Called when [create view].
/// </summary>
/// <param name="inflater">The inflater.</param>
/// <param name="container">The container.</param>
/// <param name="savedInstanceState">State of the saved instance.</param>
/// <returns>View.</returns>
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Mvx.Trace("TabRootFragment => OnCreateView");
return inflater.Inflate(Resource.Layout.TabRootFragment, container, false);
}
/// <summary>
/// Called when [view created].
/// </summary>
/// <param name="view">The view.</param>
/// <param name="savedInstanceState">State of the saved instance.</param>
public override void OnViewCreated(View view, Bundle savedInstanceState)
{
Mvx.Trace(
"TabRootFragment => OnViewCreated {0}",
Enum.GetName(typeof(Category), this.rootChildren.ViewModel.Category));
base.OnViewCreated(view, savedInstanceState);
this.ChildFragmentManager.BeginTransaction()
.Add(Resource.Id.ChildFragment, this.rootChildren)
.Commit();
}
All seems to go well until we reach the OnViewCreated of the TabRootFragment . When we hit the fragment manager transaction, we receive a nice Exception:
Java.Lang.IllegalStateException: Activity has been destroyed
It would seem that the TabRootFragment is not attached to the Activity. But it is set to the pager by the SetCurrentItem in the OnTabSelected method...
How can I check if this fragment is well attached to the activity through ViewPager ?
Donn was right, this is related to this: https://stackoverflow.com/a/15656428/5210 :)
Excepted that my fragment was never detached, and the fix needed to be applied right from the OnAttach method of the TabRootFragment .
Bonus: the Xamarin code to do so:
public class TabRootFragment : MvxFragment
{
public override void OnAttach(Activity activity)
{
Mvx.Trace("TabRootFragment => OnAttach");
base.OnAttach(activity);
this.InitChildFragmentManagerState();
}
/// <summary>
/// Initializes the state of the child fragment manager.
/// </summary>
private void InitChildFragmentManagerState()
{
var classRefProp = typeof(Fragment).GetProperty(
"class_ref",
BindingFlags.NonPublic | BindingFlags.Static);
IntPtr classRef = (IntPtr)classRefProp.GetValue(this);
var field = JNIEnv.GetFieldID(
classRef,
"mChildFragmentManager",
"Landroid/support/v4/app/FragmentManagerImpl;");
JNIEnv.SetField(this.Handle, field, IntPtr.Zero);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.