V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Whatisup
V2EX  ›  iOS

iOS 下怎么就找不到好用的新手引导组件呢?还是得自己动手

  •  
  •   Whatisup · 9 天前 · 739 次点击

    PolarisGuideKit:轻量、低侵入的 iOS 新手引导组件(遮罩挖孔 + Buddy View + 插件化)

    关键词:UIKit · 新手引导 · 低侵入 · 插件扩展

    GitHub:**https://github.com/noodles1024/PolarisGuideKit**

    demo_cn_tiny.webp


    背景:我为什么做这个组件?

    可能是新手引导这个功能太小,随便实现一下也能用,导致没有人愿意来写认真写一个 iOS 下的新手引导组件,搜遍整个 github 也找不到一个在现实项目中能直接拿来用的。如果只考虑某一个具体的新手引导界面,实现起来很容易(特别是现在在 AI 的加持下,UI 仔都不需要了)。但在不同项目、不同场景下,经过和和产品经理&设计师的多次沟通中,我发现了做“新手引导/功能提示”时的一些令人头疼的问题:

    • 需要高亮某个控件,但布局变化、屏幕旋转后挖孔(高亮)位置容易偏
    • 指引说明(箭头/气泡/按钮)形态不固定,可能还伴随着音频播放等附加功能,复用困难
    • 点击高亮区域时,难以做到不侵入原有点击业务逻辑
    • 显示新手引导时难以在不改变原有逻辑的情况下阻止 NavigationController 的滑动返回
    • UITableView/UICollectionView reloadData 后高亮经常失效

    于是我做了 PolarisGuideKit:一个基于 UIKit 的轻量新手引导组件,主打低侵入 + 可扩展 + 动态高亮


    PolarisGuideKit 能解决什么?

    能力 说明 带来的价值
    高亮遮罩 遮罩挖孔高亮 focusView 高亮区域自动跟随,内置高亮效果,可自定义
    Buddy View 说明视图可自由定制 文案、箭头、按钮任意组合
    步骤编排 多步骤引导流程 支持下一步、跳过、完成
    动态 focusView reloadData 后自动修正 TableView/CollectionView 场景稳定
    插件化扩展 Audio/埋点/持久化 可插拔、解耦

    快速上手( 3 分钟接入)

    import UIKit
    import PolarisGuideKit
    
    final class MyViewController: UIViewController {
        private var guide: GuideController?
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
    
            let step = GuideStep()
            step.focusView = myButton
            step.buddyView = MyBuddyView()
            step.forwardsTouchEventsToFocusView = true
            step.completer = ControlEventCompleter(control: myButton, event: .touchUpInside)
    
            let controller = GuideController(hostView: view, steps: [step])
            controller.onDismiss = { _, context in
                print("引导结束,原因 = \(context.reason)")
            }
    
            _ = controller.show()
            guide = controller
        }
    }
    

    核心概念一图速览

    • GuideController:流程编排器,负责 show/hide/切换步骤
    • GuideStep:一步引导配置( focus 、buddy 、style 、completer )
    • FocusStyle:高亮形状(矩形/圆形/圆角/无高亮)
    • GuideBuddyView:说明视图(可继承自定义)
    • GuidePlugin:生命周期扩展(音频/埋点/持久化)

    重点能力拆解

    1) FocusStyle:高亮样式可拔插

    内置样式包含:

    • DefaultFocusStyle(矩形)
    • RoundedRectFocusStyle(圆角矩形)
    • CircleFocusStyle(圆形)
    • NoHighlightFocusStyle(全屏遮罩)
    let step = GuideStep()
    step.focusView = someCard
    step.focusStyle = RoundedRectFocusStyle(
        focusCornerRadius: .followFocusView(delta: 2),
        focusAreaInsets: UIEdgeInsets(top: -6, left: -6, bottom: -6, right: -6)
    )
    

    2) 动态 FocusView:Table/CollectionView 不卡壳

    UITableView / UICollectionView 复用导致高亮错位?
    使用 focusViewProvider 动态获取最新 cell:

    let step = GuideStep()
    step.focusViewProvider = { [weak self] in
        guard let self else { return nil }
        var cell = self.tableView.cellForRow(at: targetIndexPath)
        if cell == nil {
            self.tableView.layoutIfNeeded()
            cell = self.tableView.cellForRow(at: targetIndexPath)
        }
        return cell
    }
    

    3) 触摸转发 + 自动完成

    在不侵入原有业务逻辑的前提下,高亮按钮依然能触发业务逻辑,同时自动关闭引导:

    let step = GuideStep()
    step.focusView = myButton
    step.forwardsTouchEventsToFocusView = true
    step.completer = ControlEventCompleter(control: myButton, event: .touchUpInside)
    

    ✅ 设置 forwardsTouchEventsToFocusView 和 completer 保证了“引导不侵入原有业务逻辑”。


    4) Buddy View:说明视图随便做

    继承 GuideBuddyView,自定义 UI + 布局:

    final class MyBuddyView: GuideBuddyView {
        override func updateLayout(referenceLayoutGuide layoutGuide: UILayoutGuide, focusView: UIView) {
            super.updateLayout(referenceLayoutGuide: layoutGuide, focusView: focusView)
            // 根据 layoutGuide 布局你的文案 / 按钮 / 箭头
        }
    }
    

    5) 插件系统:音频 / 埋点 / 持久化

    内置 AudioGuidePlugin,可在显示引导时播放音频文件,且可在 BuddyView 中配合显示音频播放动画(可选功能):

    let step = GuideStep()
    step.focusView = myCard
    step.addAttachment(GuideAudioAttachment(url: audioURL, volume: 0.8))
    
    let controller = GuideController(
        hostView: view,
        steps: [step],
        plugins: [AudioGuidePlugin()]
    )
    

    如果想要加埋点、标记“引导是否已显示”,可通过自定义 GuidePlugin 实现。


    Demo 示例一览

    • 圆角矩形高亮 + 圆角模式切换
    • 圆形高亮 + 半径缩放
    • 多步骤引导 + 平滑转场
    • 触摸转发 + 自动完成
    • 点击外部关闭( dismissesOnOutsideTap )
    • 音频 + Lottie 同步演示
    • UITableView 动态高亮

    架构 & 视图层级

    flowchart TB
        subgraph Core["核心组件"]
            GuideController["GuideController<br/>(流程编排器)"]
            GuideStep["GuideStep<br/>(步骤配置)"]
        end
    
        subgraph ViewHierarchy["视图层级"]
            GuideContainerView["GuideContainerView<br/>(透明容器)"]
            GuideOverlayView["GuideOverlayView<br/>(遮罩 + 触摸转发)"]
            MaskOverlayView["MaskOverlayView<br/>(遮罩基类)"]
            GuideBuddyView["GuideBuddyView<br/>(说明视图)"]
            GuideShadowView["GuideShadowView<br/>(焦点追踪器)"]
        end
    
        subgraph Extensions["扩展机制"]
            FocusStyle["FocusStyle<br/>(高亮形状)"]
            GuideAutoCompleter["GuideAutoCompleter<br/>(完成触发器)"]
            GuidePlugin["GuidePlugin<br/>(生命周期钩子)"]
            GuideStepAttachment["GuideStepAttachment<br/>(插件数据)"]
        end
    
        GuideController -->|"管理"| GuideStep
        GuideController -->|"创建并承载"| GuideContainerView
        GuideController -->|"派发事件"| GuidePlugin
        
        GuideContainerView -->|"包含"| GuideOverlayView
        GuideContainerView -->|"包含"| GuideBuddyView
        
        GuideOverlayView -.->|"继承"| MaskOverlayView
        GuideOverlayView -->|"创建"| GuideShadowView
        GuideOverlayView -->|"使用"| FocusStyle
        
        GuideStep -->|"配置"| GuideBuddyView
        GuideStep -->|"使用"| FocusStyle
        GuideStep -->|"通过...触发"| GuideAutoCompleter
        GuideStep -->|"携带"| GuideStepAttachment
    

    view_hierarchy.png


    安装

    Swift Package Manager

    1. Xcode → File → Add Packages…
    2. 输入仓库地址:https://github.com/noodles1024/PolarisGuideKit
    3. 选择 PolarisGuideKit

    CocoaPods

    pod 'PolarisGuideKit'
    
    import PolarisGuideKit
    

    注意事项(踩坑清单)

    • focusView 必须是 hostView 的子视图
    • 多 Scene / 多 Window 建议显式传 hostView
    • GuideAutoCompleter 触发后会结束整个引导(建议用于最后一步)
    • 动画转场在复杂形状下可关闭动画:animatesStepTransition = false

    项目地址 & 交流

    目前尚无回复
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   3754 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 00:53 · PVG 08:53 · LAX 16:53 · JFK 19:53
    ♥ Do have faith in what you're doing.