小工具知识网

当前位置: 首页 > 行业知识 > SwiftUI 5.0(iOS 17)进一步定制 TipKit 外观让撸码如虎添翼

行业知识

SwiftUI 5.0(iOS 17)进一步定制 TipKit 外观让撸码如虎添翼

2026-11-02 16:47:57 来源:互联网转载

概览

在之前 SwiftUI 5.0(iOS 17)TipKit 让用户更懂你的 App 这篇博文里,我们已经初步介绍过了 TipKit 的基本知识。

现在,让我们来看看如何进一步利用 SwiftUI 对 TipKit 提供的细粒度外观定制技巧,让 Tip 更加“明眸皓齿”。

在本篇博文中,您将学到如下内容:

  • 概览
  • 1. TipKit 温故而知新
  • 2. Tip 外观细粒度定制
  • 3. 完全自己打造 Tip 外观
  • 总结

    相信学完本课后,小伙伴们对 TipKit 的内功修为会更加炉火纯青、登峰造极!

    那还等什么呢?Let’s go!!!


    本文对应的视频课在此,欢迎小伙伴们恣意观赏!

    SwiftUI 定制 TipKit 外观进一步让撸码如虎添翼


    1. TipKit 温故而知新

    在前一篇关于 TipKit 的博文中,我们介绍了什么是 TipKit 以及如何在 App 中支持 TipKit 的方法。

    这里再回忆一下:创建一个 Tip 很简单,我们只需让类型遵守 Tip 协议即可。

    struct FavoriteTip: Tip {    var title: Text {        Text("收藏最爱的图片")            .bold()    }        var message: Text? {        Text("将心仪的图片保存到相册中")            .font(.headline)            .foregroundStyle(.gray.gradient)    }var image: Image? {        Image(systemName: "heart")    }}

    然后,我们可以通过嵌入和弹出两种不同方法来显示它:

    // 嵌入 Tipstruct ContentView: View {    let favTip = FavoriteTip()        var body: some View {        NavigationStack {            VStack {                                TipView(favTip)            }            .padding()            .navigationTitle("TitKit演示")        }    }}// 弹出 Tipstruct ContentView: View {    let favTip = FavoriteTip()        var body: some View {        NavigationStack {            VStack {...}            .padding()            .navigationTitle("TitKit演示")            .toolbar {                ToolbarItem {                    Image(systemName: "heart")                        .font(.title.weight(.black))                        .foregroundStyle(.pink.gradient)                        .popoverTip(favTip, arrowEdge: .top)                }            }        }    }}

    嵌入和弹出 Tip 的效果如下图所示:

    如果大家对于默认 Tip 的外观不甚满意怎么办?别急,SwiftUI 还有“妙计”。

    2. Tip 外观细粒度定制

    Apple 在推出 TipKit 框架的同时也提供了若干修改器方法,我们可以利用它们来进一步调整 Tip 视图的外观。

    首先是 tipCornerRadius() 方法,它可以用来调整 Tip 视图边角的弧度:

    struct ContentView: View {    let favTip = FavoriteTip()    @State var addTipRadius = false        var body: some View {        NavigationStack {            VStack {                TipView(favTip)                                Toggle(isOn: $addTipRadius) {                    Text("增加 Tip 边角弧度")                        .font(.title3)                }            }            .padding()                        .navigationTitle("TitKit演示")            .tipCornerRadius(addTipRadius ? 30 : 10)            .frame(maxHeight: .infinity)            .background(.gray.opacity(0.66).gradient)            .animation(.bouncy, value: addTipRadius)        }    }}

    值得注意的是:tipCornerRadius 修改器方法和随后介绍的所有 Tip 外观调整方法都会沿着视图继承树向下传递,这意味着顶层的方法会影响内部所有的 Tip 外观。

    接下来是 tipImageSize() 修改器,我们可以用它来调整 Tip 内部图片的尺寸:

    NavigationStack {    VStack {                TipView(favTip)    }    .tipImageSize(CGSize(width: incImageSize ? 50 : 24, height: incImageSize ? 50 : 24))    .frame(maxHeight: .infinity)    .background(.gray.opacity(0.66).gradient)    .animation(.bouncy, value: incImageSize)}

    运行效果如下所示:

    最后,我们可以用 tipBackground() 修改器方法来调整 Tip 视图背景的显示样式:

    NavigationStack {    VStack {                TipView(favTip)    }    .tipBackground(incBackgroundHue ? Material.ultraThick : .thin)    .frame(maxHeight: .infinity)    .background(.gray.opacity(0.66).gradient)    .animation(.bouncy, value: incImageSize)}

    运行的效果不出意料:

    上面我们介绍了一些从宏观上调整 Tip 外观的方法,如果小伙伴们还是觉得捉襟见肘、鸟入樊笼怎么办?

    别急,我们还可以“欲穷千里目,更上一层楼”:自己动手“丰衣足食”来 100% “恣意”决定 Tip 该如何显示。

    3. 完全自己打造 Tip 外观

    为了最大程度满足秃头码农们随心所欲定制 Tip 外观的需求,苹果决定将 Tip 的外观样式化(Styling)以便让我们可以无拘无束定制它们“主题皮肤”。

    经常撸 SwiftUI 代码的小伙伴们都知道,在 SwiftUI 中大部分原生视图都有对应的样式(Style),比如按钮、Label、Toggle 等等。视图样式为我们充分定制视图的外观带来了极大的便利。

    TipKit 也不例外,我们同样可以利用 tipViewStyle() 修改器来排忧解难:

    为了能够安闲自在的 100% 纯手工打造 Tip 的外观,我们首先需要“由着性子”创建一个遵守 TipViewStyle 协议的类型:

    struct PureCustomTipViewStyle: TipViewStyle {    func makeBody(configuration: Configuration) -> some View {        VStack(alignment: .leading) {            HStack(alignment: .bottom) {                if let image = configuration.image {                    image                        .resizable()                        .aspectRatio(contentMode: .fit)                        .font(.title.weight(.heavy))                        .frame(width: 25, height: 25)                        .foregroundStyle(.teal)                        .padding()                        .overlay {                            RoundedRectangle(cornerRadius: 15.0)                                .stroke(.secondary, lineWidth: 3.0)                        }                }                                Rectangle()                    .frame(width: 3, height: 100)                    .foregroundStyle(.white.gradient)                                VStack(alignment: .leading) {                    if let title = configuration.title {                        title.font(.headline)                    }                                        if let message = configuration.message {                        Group {                            message                                .font(.subheadline)                                .padding()                        }                        .background {                            RoundedRectangle(cornerRadius: 15.0)                                .foregroundStyle(Material.thin)                        }                    }                }            }                        HStack {                Spacer()                ForEach(configuration.actions, id: \.id) { action in                    Button {                        action.handler()                    } label: {                        Image(systemName: "volleyball.fill")                            .foregroundStyle(.yellow.gradient)                        action.label()                    }                    .fontWeight(.bold)                    .buttonStyle(.borderedProminent)                }            }        }        .padding()        .background {            Image("bg")                .resizable()                .opacity(0.77)        }    }}

    接着,为了方便起见我们还可以将上面创建的 Tip 自定义样式融入到 TipViewStyle 自身中去:

    extension TipViewStyle where Self == PureCustomTipViewStyle {    static var pureCustom: Self {        Self.init()    }}

    最后在 Tip 视图本身或其上层容器中,我们即可悠然自得的调用 tipViewStyle() 修改器方法来施展改头换面的“黑魔法”啦:

    struct ContentView: View {    let favTip = FavoriteTip()    @State var addTipRadius = false    @State var incImageSize = false    @State var incBackgroundHue = false        var body: some View {        NavigationStack {            VStack {                                TipView(favTip)                                Toggle(isOn: $addTipRadius) {                    Text("增加 Tip 边角弧度")                        .font(.title3)                }                                Toggle(isOn: $incImageSize) {                    Text("增加 Tip 图片大小")                        .font(.title3)                }                                Toggle(isOn: $incBackgroundHue) {                    Text("增加 Tip 背景色度")                        .font(.title3)                }            }            .padding()                        .navigationTitle("TitKit演示")            .tipCornerRadius(addTipRadius ? 30 : 10)            .tipImageSize(CGSize(width: incImageSize ? 50 : 24, height: incImageSize ? 50 : 24))            .tipBackground(incBackgroundHue ? Material.ultraThick : .thin)            // 应用我们的自定义 Tip 样式            .tipViewStyle(.pureCustom)            .frame(maxHeight: .infinity)            .background(.gray.opacity(0.66).gradient)            .animation(.bouncy, value: addTipRadius)            .animation(.bouncy, value: incImageSize)            .animation(.bouncy, value: incBackgroundHue)        }    }}

    编译运行代码,现在用全身毛孔来感受一下纯手工打造 Tip 界面的愉悦之美吧!

    至此,我们完全掌握了 TipKit 中外观调整与定制的全部技巧,小伙伴们还不赶快发挥天马行空般的想象力打造自己的 Tip 视图吧!棒棒哒!


    想要系统学习 Swift 语言的小伙伴们,千万不要错过我的《Swift 语言开发精讲》专栏哦,欢迎大家恣意观赏:

    • Swift 语言开发精讲

      总结

      在本篇博文中,我们介绍了 SwiftUI 5.0 中从宏观全局调整 Tip 视图显示的几种方式。如果小伙伴们觉得还是不能放开手脚,我们还探讨了如何 100% 纯手工打造自己 Tip 内部布局的方法,包您满意!

      感谢观赏,再会!

上一篇:服务器怎么删数据包?

下一篇:告别余额宝,轻松关闭只需几步操作!