protected virtual MvxViewPagerFragmentInfo FindFragmentInfoFromAttribute( MvxFragmentPresentationAttribute attribute, MvxCachingFragmentStatePagerAdapter adapter) { MvxViewPagerFragmentInfo fragmentInfo = null; if (attribute.Tag != null) { fragmentInfo = adapter.FragmentsInfo.FirstOrDefault(f => f.Tag == attribute.Tag); } if (fragmentInfo != null) { return(fragmentInfo); } bool IsMatch(MvxViewPagerFragmentInfo info) { if (attribute.ViewType == null) { return(false); } var viewTypeMatches = info.FragmentType == attribute.ViewType; if (attribute.ViewModelType != null) { return(viewTypeMatches && info.ViewModelType == attribute.ViewModelType); } return(viewTypeMatches); } fragmentInfo = adapter.FragmentsInfo.FirstOrDefault(IsMatch); return(fragmentInfo); }
private void RestoreFragmentsInfoState(Bundle bundle) { if (bundle == null) { return; } var fragmentInfoParcelables = bundle.GetParcelableArray(_bundleFragmentsInfoKey); if (fragmentInfoParcelables == null) { return; } // First, we create a list of the ViewPager fragments that were restored by Android. var fragments = GetFragmentsFromBundle(bundle); // Now we get the FragmentInfo data for each fragment from the bundle. int i = 0; foreach (ViewPagerFragmentInfoParcelable parcelable in fragmentInfoParcelables) { MvxViewPagerFragmentInfo fragInfo = null; if (i < fragments.Count) { var f = fragments[i]; if (f is IMvxFragmentView fragment && fragment.ViewModel != null) { // The fragment was already restored by Android with its old ViewModel (cached by MvvmCross). // Add the ViewModel to the FragmentInfo object so the adapter won't instantiate a new one. var viewModelInstanceRequest = new MvxViewModelInstanceRequest(fragment.ViewModel); fragInfo = new MvxViewPagerFragmentInfo(parcelable.Title, parcelable.Tag, parcelable.FragmentType, viewModelInstanceRequest); } } if (fragInfo == null) { // Either the fragment doesn't exist or it doesn't have a ViewModel. // Fall back to a FragmentInfo with the ViewModelType. The adapter will create a ViewModel in GetItem where we will add it to the FragmentInfo. var viewModelRequest = new MvxViewModelRequest(parcelable.ViewModelType); fragInfo = new MvxViewPagerFragmentInfo(parcelable.Title, parcelable.Tag, parcelable.FragmentType, viewModelRequest); } FragmentsInfo.Add(fragInfo); i++; } NotifyDataSetChanged(); }
public override Fragment GetItem(int position, Fragment.SavedState fragmentSavedState = null) { var fragment = base.GetItem(position, fragmentSavedState); // If the MvxViewPagerFragmentInfo for this position doesn't have the ViewModel, overwrite it with a new MvxViewPagerFragmentInfo that has the ViewModel we just created. // Not doing this means the ViewModel gets recreated every time the Fragment gets recreated! if (FragmentsInfo != null && FragmentsInfo.Count > position && fragment is IMvxFragmentView mvxFragment && mvxFragment.ViewModel != null) { var oldFragInfo = FragmentsInfo[position]; if (oldFragInfo != null && oldFragInfo.ViewModel == null) { var newFragInfo = new MvxViewPagerFragmentInfo(oldFragInfo.Title, oldFragInfo.Tag, oldFragInfo.FragmentType, mvxFragment.ViewModel); FragmentsInfo[position] = newFragInfo; } } return(fragment); }
protected virtual Task <bool> ShowViewPagerFragment( Type view, MvxViewPagerFragmentPresentationAttribute attribute, MvxViewModelRequest request) { ValidateArguments(view, attribute, request); // if the attribute doesn't supply any host, assume current activity! if (attribute.FragmentHostViewType == null && attribute.ActivityHostViewModelType == null) { attribute.ActivityHostViewModelType = GetCurrentActivityViewModelType(); } ViewPager? viewPager = null; FragmentManager?fragmentManager = null; // check for a ViewPager inside a Fragment if (attribute.FragmentHostViewType != null) { var fragment = GetFragmentByViewType(attribute.FragmentHostViewType); if (fragment == null) { throw new MvxException("Fragment not found", attribute.FragmentHostViewType.Name); } if (fragment.View == null) { throw new MvxException("Fragment.View is null. Please consider calling Navigate later in your code", attribute !.FragmentHostViewType.Name); } viewPager = fragment.View.FindViewById <ViewPager>(attribute.ViewPagerResourceId); fragmentManager = fragment.ChildFragmentManager; } // check for a ViewPager inside an Activity if (attribute.ActivityHostViewModelType != null) { var currentActivityViewModelType = GetCurrentActivityViewModelType(); // if the host Activity is not the top-most Activity, then show it before proceeding, and return false for now if (attribute.ActivityHostViewModelType != currentActivityViewModelType) { PendingRequest = request; ShowHostActivity(attribute); return(Task.FromResult(false)); } if (CurrentActivity.IsActivityAlive()) { viewPager = CurrentActivity !.FindViewById <ViewPager>(attribute.ViewPagerResourceId); } fragmentManager = CurrentFragmentManager; } // no more cases to check. Just throw if ViewPager wasn't found if (viewPager == null) { throw new MvxException("ViewPager not found"); } var tag = attribute.Tag ?? attribute.ViewType.FragmentJavaName(); var fragmentInfo = new MvxViewPagerFragmentInfo(attribute.Title, tag, attribute.ViewType, request); if (viewPager.Adapter is MvxCachingFragmentStatePagerAdapter adapter) { adapter.FragmentsInfo.Add(fragmentInfo); adapter.NotifyDataSetChanged(); } else { viewPager.Adapter = new MvxCachingFragmentStatePagerAdapter( CurrentActivity, fragmentManager, new List <MvxViewPagerFragmentInfo> { fragmentInfo } ); } return(Task.FromResult(true)); }