protected virtual void ShowViewPagerFragment(
            Type view,
            MvxViewPagerFragmentPresentationAttribute attribute,
            MvxViewModelRequest request)
        {
            if (attribute.ActivityHostViewModelType == null)
            {
                attribute.ActivityHostViewModelType = GetCurrentActivityViewModelType();
            }

            var currentHostViewModelType = GetCurrentActivityViewModelType();

            if (attribute.ActivityHostViewModelType != currentHostViewModelType)
            {
                _pendingRequest = request;
                ShowHostActivity(attribute);
            }
            else
            {
                var viewPager = CurrentActivity.FindViewById <ViewPager>(attribute.ViewPagerResourceId);
                if (viewPager != null)
                {
                    if (viewPager.Adapter is MvxCachingFragmentStatePagerAdapter adapter)
                    {
                        if (adapter.FragmentsInfo.Any(f => f.Tag == attribute.Title))
                        {
                            var index = adapter.FragmentsInfo.FindIndex(f => f.Tag == attribute.Title);
                            viewPager.SetCurrentItem(index > -1 ? index : 0, true);
                        }
                        else
                        {
                            if (request is MvxViewModelInstanceRequest instanceRequest)
                            {
                                adapter.FragmentsInfo.Add(new MvxViewPagerFragmentInfo(attribute.Title, attribute.ViewType, instanceRequest.ViewModelInstance));
                            }
                            else
                            {
                                adapter.FragmentsInfo.Add(new MvxViewPagerFragmentInfo(attribute.Title, attribute.ViewType, attribute.ViewModelType));
                            }
                            adapter.NotifyDataSetChanged();
                        }
                    }
                    else
                    {
                        var fragments = new List <MvxViewPagerFragmentInfo>();
                        if (request is MvxViewModelInstanceRequest instanceRequest)
                        {
                            fragments.Add(new MvxViewPagerFragmentInfo(attribute.Title, attribute.ViewType, instanceRequest.ViewModelInstance));
                        }
                        else
                        {
                            fragments.Add(new MvxViewPagerFragmentInfo(attribute.Title, attribute.ViewType, attribute.ViewModelType));
                        }

                        if (attribute.FragmentHostViewType != null)
                        {
                            var fragment = GetFragmentByViewType(attribute.FragmentHostViewType);
                            if (fragment == null)
                            {
                                throw new MvxException("Fragment not found", attribute.FragmentHostViewType.Name);
                            }

                            viewPager.Adapter = new MvxCachingFragmentStatePagerAdapter(CurrentActivity, fragment.ChildFragmentManager, fragments);
                        }
                        else
                        {
                            viewPager.Adapter = new MvxCachingFragmentStatePagerAdapter(CurrentActivity, CurrentFragmentManager, fragments);
                        }
                    }
                }
                else
                {
                    throw new MvxException("ViewPager not found");
                }
            }
        }
        public override MvxBasePresentationAttribute GetPresentationAttribute(MvxViewModelRequest request)
        {
            var viewType = ViewsContainer.GetViewType(request.ViewModelType);

            var overrideAttribute = GetOverridePresentationAttribute(request, viewType);

            if (overrideAttribute != null)
            {
                return(overrideAttribute);
            }

            IList <MvxBasePresentationAttribute> attributes = viewType.GetCustomAttributes <MvxBasePresentationAttribute>(true).ToList();

            if (attributes != null && attributes.Count > 0)
            {
                MvxBasePresentationAttribute attribute = null;

                if (attributes.Count > 1)
                {
                    var fragmentAttributes = attributes.OfType <MvxFragmentPresentationAttribute>();

                    // check if fragment can be displayed as child fragment first
                    foreach (var item in fragmentAttributes.Where(att => att.FragmentHostViewType != null))
                    {
                        var fragmentHost = GetFragmentByViewType(item.FragmentHostViewType);

                        // if the fragment exists, is on top, and (has the ContentId or the attribute is for ViewPager), then use it as current attribute
                        if (fragmentHost != null &&
                            fragmentHost.IsVisible &&
                            (fragmentHost.View.FindViewById(item.FragmentContentId) != null || item is MvxViewPagerFragmentPresentationAttribute))
                        {
                            attribute = item;
                            break;
                        }
                    }

                    // if attribute is still null, check if fragment can be displayed in current activity
                    if (attribute == null)
                    {
                        var currentActivityHostViewModelType = GetCurrentActivityViewModelType();
                        foreach (var item in fragmentAttributes.Where(att => att.ActivityHostViewModelType != null && att.ActivityHostViewModelType == currentActivityHostViewModelType))
                        {
                            // check for MvxTabLayoutPresentationAttribute
                            if (item is MvxTabLayoutPresentationAttribute tabLayoutAttribute &&
                                CurrentActivity.FindViewById(tabLayoutAttribute.TabLayoutResourceId) != null)
                            {
                                attribute = item;
                                break;
                            }

                            // check for MvxViewPagerFragmentPresentationAttribute
                            if (item is MvxViewPagerFragmentPresentationAttribute viewPagerAttribute &&
                                CurrentActivity.FindViewById(viewPagerAttribute.ViewPagerResourceId) != null)
                            {
                                attribute = item;
                                break;
                            }

                            // check for MvxFragmentPresentationAttribute
                            if (CurrentActivity.FindViewById(item.FragmentContentId) != null)
                            {
                                attribute = item;
                                break;
                            }
                        }
                    }
                }

                if (attribute == null)
                {
                    attribute = attributes.FirstOrDefault();
                }

                attribute.ViewType = viewType;

                return(attribute);
            }

            return(CreatePresentationAttribute(request.ViewModelType, viewType));
        }
        public override MvxBasePresentationAttribute GetPresentationAttribute(Type viewModelType)
        {
            var viewType = ViewsContainer.GetViewType(viewModelType);

            var overrideAttribute = GetOverridePresentationAttribute(viewModelType, viewType);

            if (overrideAttribute != null)
            {
                return(overrideAttribute);
            }

            IList <MvxBasePresentationAttribute> attributes = viewType.GetCustomAttributes <MvxBasePresentationAttribute>(true).ToList();

            if (attributes != null && attributes.Count > 0)
            {
                MvxBasePresentationAttribute attribute = null;

                if (attributes.Count > 1)
                {
                    var fragmentAttributes = attributes.OfType <MvxFragmentPresentationAttribute>();

                    // check if fragment can be displayed as child fragment first
                    foreach (var item in fragmentAttributes.Where(att => att.FragmentHostViewType != null))
                    {
                        var fragment = GetFragmentByViewType(item.FragmentHostViewType);

                        // if the fragment exists, and is on top, then use the current attribute
                        if (fragment != null && fragment.IsVisible && fragment.View.FindViewById(item.FragmentContentId) != null)
                        {
                            attribute = item;
                            break;
                        }
                    }

                    // if attribute is still null, check if fragment can be displayed in current activity
                    if (attribute == null)
                    {
                        var currentActivityHostViewModelType = GetCurrentActivityViewModelType();
                        foreach (var item in fragmentAttributes.Where(att => att.ActivityHostViewModelType != null))
                        {
                            if (CurrentActivity.FindViewById(item.FragmentContentId) != null && item.ActivityHostViewModelType == currentActivityHostViewModelType)
                            {
                                attribute = item;
                                break;
                            }
                        }
                    }
                }

                if (attribute == null)
                {
                    attribute = attributes.FirstOrDefault();
                }

                attribute.ViewType = viewType;

                return(attribute);
            }

            return(CreatePresentationAttribute(viewModelType, viewType));
        }
        protected virtual Task <bool> ShowViewPagerFragment(
            Type view,
            MvxViewPagerFragmentPresentationAttribute attribute,
            MvxViewModelRequest 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));
                }

                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();

            if (viewPager.Adapter is MvxCachingFragmentStatePagerAdapter adapter)
            {
                if (request is MvxViewModelInstanceRequest instanceRequest)
                {
                    adapter.FragmentsInfo.Add(new MvxViewPagerFragmentInfo(
                                                  attribute.Title, tag, attribute.ViewType, instanceRequest.ViewModelInstance));
                }
                else
                {
                    adapter.FragmentsInfo.Add(new MvxViewPagerFragmentInfo(
                                                  attribute.Title, tag, attribute.ViewType, attribute.ViewModelType));
                }

                adapter.NotifyDataSetChanged();
            }
            else
            {
                var fragments = new List <MvxViewPagerFragmentInfo>();
                if (request is MvxViewModelInstanceRequest instanceRequest)
                {
                    fragments.Add(new MvxViewPagerFragmentInfo(
                                      attribute.Title, tag, attribute.ViewType, instanceRequest.ViewModelInstance));
                }
                else
                {
                    fragments.Add(new MvxViewPagerFragmentInfo(
                                      attribute.Title, tag, attribute.ViewType, attribute.ViewModelType));
                }

                viewPager.Adapter = new MvxCachingFragmentStatePagerAdapter(CurrentActivity, fragmentManager, fragments);
            }

            return(Task.FromResult(true));
        }