MvvmCross Xamarin.iOS非全屏模态视图控制器尺寸无法调整问题求助
解决MvvmCross中iOS非全屏模态视图的实现问题
你遇到的这个情况确实是MvvmCross在iOS上处理模态视图的常见小坑——默认情况下FormSheet样式在iPhone上还是会接近全屏显示,官方文档提到的PreferredContentSize也只对iPad生效。下面给你几个2021年亲测可行的解决方案,按推荐程度排序:
方案一:使用MvvmCross官方弹窗插件(最推荐)
MvvmCross有专门的MvxPopup插件,专门用于实现非全屏模态弹窗,比手动调整Frame优雅得多,且在iPhone/iPad上都能稳定生效。
步骤:
- 安装NuGet包:
MvvmCross.Plugin.Popup - 让你的视图控制器继承
MvxPopupViewController而非普通的MvxViewController:
public partial class LogoutPopupViewController : MvxPopupViewController<LogoutViewModel> { public LogoutPopupViewController() : base(UIModalPresentationStyle.FormSheet, UIModalTransitionStyle.CoverVertical) { } public override void ViewDidLoad() { base.ViewDidLoad(); // 自定义弹窗尺寸(比如宽度减边距,高度固定300) PreferredContentSize = new CGSize(UIScreen.MainScreen.Bounds.Width - 40, 300); // 设置背景半透明效果 BackgroundColor = UIColor.Black.ColorWithAlpha(0.5f); } }
- 在ViewModel中通过
IMvxPopupService触发弹窗:
public class LogoutViewModel : MvxViewModel { private readonly IMvxPopupService _popupService; public LogoutViewModel(IMvxPopupService popupService) { _popupService = popupService; } public ICommand ShowLogoutPopupCommand => new MvxCommand(async () => { await _popupService.PresentPopupAsync<LogoutPopupViewModel>(); }); }
方案二:手动调整视图Frame(无需额外插件)
如果不想引入第三方插件,可以在视图控制器中手动调整Frame,配合自定义模态样式解决问题。
实现代码:
[MvxModalPresentation(ModalPresentationStyle = UIModalPresentationStyle.Custom, WrapInNavigationController = true)] public partial class LogoutViewController : BaseViewController<LogoutViewModel> { public override void ViewWillLayoutSubviews() { base.ViewWillLayoutSubviews(); // 自定义视图尺寸:比如高度为屏幕的一半,宽度全屏 var desiredHeight = UIScreen.MainScreen.Bounds.Height / 2; var desiredFrame = new CGRect(0, UIScreen.MainScreen.Bounds.Height - desiredHeight, UIScreen.MainScreen.Bounds.Width, desiredHeight); // 同时调整导航控制器的Frame(如果WrapInNavigationController为true) if (NavigationController != null) { NavigationController.View.Frame = desiredFrame; } else { View.Frame = desiredFrame; } } }
注意:建议在
ViewWillLayoutSubviews中设置,避免首次弹出时的全屏闪烁问题。
方案三:自定义Mvx模态呈现器(全局统一处理)
如果需要全局统一控制所有模态视图的大小,可以自定义Mvx的视图呈现器,重写模态呈现逻辑。
实现代码:
- 创建自定义呈现器:
public class CustomModalViewPresenter : MvxIosModalViewPresenter { public CustomModalViewPresenter(IUIApplicationDelegate applicationDelegate, UIWindow window) : base(applicationDelegate, window) { } protected override void PresentModalViewController(UIViewController viewController, bool animated) { // 针对目标控制器设置自定义尺寸 if (viewController is LogoutViewController logoutVc) { logoutVc.ModalPresentationStyle = UIModalPresentationStyle.FormSheet; // 强制在iPhone上生效PreferredContentSize if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone) { var targetVc = logoutVc.NavigationController ?? logoutVc; targetVc.View.Frame = new CGRect(0, UIScreen.MainScreen.Bounds.Height - 300, UIScreen.MainScreen.Bounds.Width, 300); } } base.PresentModalViewController(viewController, animated); } }
- 在
Setup.cs中替换默认呈现器:
protected override IMvxIosViewPresenter CreatePresenter() { return new CustomModalViewPresenter(ApplicationDelegate, Window); }
内容的提问来源于stack exchange,提问作者Async-
相关产品推荐
相关产品推荐

