You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:13:36