SwiftUI中如何缩小material-showcase-ios的展示视图尺寸?
解决material-showcase-ios展示视图过大及叠加问题
问题背景
登录后需要首次展示多步骤引导弹窗,使用material-showcase-ios框架(版本~>0.8.0)时遇到两个问题:
- 展示视图整体尺寸过大,不符合设计需求
- 多个引导弹窗同时叠加显示,无法按顺序展示
解决方案
1. 缩小展示视图尺寸
通过配置MaterialShowcase的核心属性,直接控制弹窗的视觉大小:
修改ShowcaseHost中的showcase配置代码
在showShowcase方法里,添加以下属性配置:
// 配置showcase部分 let showcase = MaterialShowcase() showcase.setTargetView(view: targetView) showcase.primaryText = showcaseItem.primaryText showcase.secondaryText = showcaseItem.secondaryText showcase.backgroundPromptColor = showcaseItem.backgroundColor showcase.primaryTextColor = showcaseItem.textColor showcase.secondaryTextColor = showcaseItem.textColor showcase.targetHolderColor = UIColor.white // --- 添加以下控制尺寸的代码 --- // 缩小目标高亮区域的半径(匹配你设置的50x50 targetView,设为25刚好覆盖) showcase.targetHolderRadius = 25 // 缩小提示背景的内边距,减少弹窗整体大小 showcase.backgroundPromptInsets = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12) // 调整文本字体大小,避免长文本撑大弹窗 showcase.primaryTextFont = UIFont.systemFont(ofSize: 16, weight: .semibold) showcase.secondaryTextFont = UIFont.systemFont(ofSize: 13) // 可选:限制提示文本的最大宽度,防止弹窗过宽 showcase.maxWidth = UIScreen.main.bounds.width * 0.75 // --- 结束添加 --- DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { showcase.show(completion: { isPresented = false targetView.removeFromSuperview() }) }
2. 修复多展示叠加问题
当前代码同时渲染两个ShowcaseHost导致叠加,改为顺序触发展示,即第一个弹窗关闭后再显示第二个:
修改HomeNew视图的代码
struct HomeNew: View { // 用单个状态控制当前展示的引导项,避免同时显示多个 @State private var currentShowcaseItem: ShowcaseItem? @State private var isShowcasePresented = false var profileShowcase: ShowcaseItem { ShowcaseItem( primaryText: "Profile", secondaryText: "Click here to check out your profile and Transport Details", animation: .topLeading, backgroundColor: UIColor(red: 0.984, green: 0.906, blue: 0.631, alpha: 1.0), textColor: .white ) } var dashboardShowcase: ShowcaseItem { ShowcaseItem( primaryText: "Dashboard", secondaryText: "Click here to access Dashboards", animation: .center, backgroundColor: UIColor(red: 0.47, green: 0.75, blue: 0.78, alpha: 1.0), textColor: .white ) } var body: some View { ZStack{ Color.Neumorphic.main .ignoresSafeArea() // --- 原有界面代码保持不变 --- VStack{ VStack{ HStack(alignment: .center) { URLImageView(url: userPhoto.percentageEncoding(), placeholder: "NoProfilePic", width: 80, height: 80) .cornerRadius(15) .scaledToFit() .overlay( RoundedRectangle(cornerRadius: 15) .stroke(Color.appGreen, lineWidth: 2) ) .onTapGesture { if isShowcasePresented { isShowcasePresented = false } else { gotoProfile = true } } } Spacer() } .padding(16) } ScrollView { VStack(spacing: 0) { VStack(spacing: 0) { HStack(spacing: 10) { ZStack { HStack { Spacer() Text("View dashboard") .font(.calibriRegular(with: 16)) .foregroundColor(.appGreen) } } } } .frame(height: 40) .onTapGesture { if isShowcasePresented { isShowcasePresented = false } else { gotoDashboard = true } } } } // --- 原有界面代码结束 --- // 只渲染当前需要展示的引导弹窗 if isShowcasePresented, let item = currentShowcaseItem { ShowcaseHost(isPresented: $isShowcasePresented, showcaseItem: item) .onDisappear { // 当前弹窗关闭后,触发下一个引导项 if item == profileShowcase { currentShowcaseItem = dashboardShowcase isShowcasePresented = true } } } } .onAppear { // 首次进入页面,启动第一个引导项 currentShowcaseItem = profileShowcase isShowcasePresented = true } } }
额外优化建议
- 移除
ShowcaseHost中onAppear里的自动关闭代码(DispatchQueue.main.asyncAfter),让用户点击弹窗后再关闭,符合引导弹窗的交互逻辑 - 如果需要精准定位到页面上的实际UI元素(比如头像、Dashboard按钮),可以直接将这些SwiftUI视图转换为UIView作为target,而不是创建额外的targetView,这样引导的位置更准确
内容的提问来源于stack exchange,提问作者Swift
相关产品推荐
相关产品推荐

