如何阻止Xamarin.Forms DisplayActionSheet点击外部时关闭
嘿,这个问题我之前做项目时也碰到过!Xamarin.Forms自带的DisplayActionSheet确实默认允许点击外部关闭弹窗,要强制用户必须选User或Guest其中一个才能进入登录页,咱们得针对iOS和Android分别做平台特定的处理,下面给你详细的实现步骤:
解决方案思路
因为原生的DisplayActionSheet没有直接提供阻止点击外部关闭的属性,所以我们可以通过**依赖服务(Dependency Service)**创建自定义的ActionSheet,在每个平台上调用原生弹窗组件,并配置禁止点击外部关闭的规则。
1. 在共享项目中定义接口
先创建一个统一的接口,用来封装自定义ActionSheet的调用逻辑:
public interface ICustomActionSheetService { // 参数说明:标题、取消按钮文本(这里我们不需要,设为null即可)、选项按钮数组 Task<string> ShowActionSheetAsync(string title, string cancelButtonText, params string[] buttons); }
2. Android平台实现
在Android项目中实现上面的接口,通过原生AlertDialog来创建弹窗,并设置禁止点击外部关闭:
[assembly: Dependency(typeof(CustomActionSheetService))] namespace YourAppName.Droid { public class CustomActionSheetService : ICustomActionSheetService { public async Task<string> ShowActionSheetAsync(string title, string cancelButtonText, params string[] buttons) { var taskCompletionSource = new TaskCompletionSource<string>(); var currentContext = Android.App.Application.Context; // 创建弹窗构建器 var alertBuilder = new AlertDialog.Builder(currentContext); alertBuilder.SetTitle(title); // 添加选项按钮,点击后返回选中的文本 alertBuilder.SetItems(buttons, (sender, args) => { taskCompletionSource.SetResult(buttons[args.Which]); }); // 核心设置:禁止点击外部关闭弹窗 alertBuilder.SetCancelable(false); // 显示弹窗 var alertDialog = alertBuilder.Create(); alertDialog.Show(); return await taskCompletionSource.Task; } } }
3. iOS平台实现
在iOS项目中同样实现接口,用原生UIAlertController创建ActionSheet,并配置禁止点击外部关闭的规则:
[assembly: Dependency(typeof(CustomActionSheetService))] namespace YourAppName.iOS { public class CustomActionSheetService : ICustomActionSheetService { public async Task<string> ShowActionSheetAsync(string title, string cancelButtonText, params string[] buttons) { var taskCompletionSource = new TaskCompletionSource<string>(); // 创建ActionSheet样式的弹窗 var alertController = UIAlertController.Create(title, null, UIAlertControllerStyle.ActionSheet); // 添加所有选项按钮 foreach (var buttonText in buttons) { alertController.AddAction(UIAlertAction.Create(buttonText, UIAlertActionStyle.Default, action => { taskCompletionSource.SetResult(buttonText); })); } // 核心设置:禁止点击外部关闭 alertController.ModalPresentationStyle = UIModalPresentationStyle.Popover; if (alertController.PopoverPresentationController != null) { // 取消箭头显示,避免弹窗出现不必要的箭头 alertController.PopoverPresentationController.PermittedArrowDirections = 0; // 设置穿透视图为null,点击外部不会触发关闭 alertController.PopoverPresentationController.PassthroughViews = null; // 必须设置弹窗的源视图和位置(这里设为屏幕中心) var rootViewController = UIApplication.SharedApplication.KeyWindow.RootViewController; alertController.PopoverPresentationController.SourceView = rootViewController.View; alertController.PopoverPresentationController.SourceRect = new CGRect( rootViewController.View.Bounds.Width / 2, rootViewController.View.Bounds.Height / 2, 0, 0 ); } // 显示弹窗 var currentViewController = UIApplication.SharedApplication.KeyWindow.RootViewController; await currentViewController.PresentViewControllerAsync(alertController, true); // 获取选中结果后关闭弹窗 var selectedResult = await taskCompletionSource.Task; await alertController.DismissViewControllerAsync(true); return selectedResult; } } }
4. 在共享项目中调用自定义ActionSheet
现在你可以在Xamarin.Forms的页面中调用这个自定义服务,替代原来的DisplayActionSheet:
// 获取服务实例 var actionSheetService = DependencyService.Get<ICustomActionSheetService>(); // 显示自定义ActionSheet var selectedOption = await actionSheetService.ShowActionSheetAsync("选择登录类型", null, "User", "Guest"); // 根据选择结果跳转登录页面 if (selectedOption == "User") { await Navigation.PushAsync(new UserLoginPage()); } else if (selectedOption == "Guest") { await Navigation.PushAsync(new GuestLoginPage()); }
这样设置后,用户就只能通过点击User或Guest选项来关闭弹窗,点击外部或者按返回键(Android)都无法关闭,完全满足你的需求~
内容的提问来源于stack exchange,提问作者Vipin Krishna
相关产品推荐
相关产品推荐

