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

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

码农世界 2024-06-11 后端 112 次浏览 0个评论

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

概览

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

SwiftUI 5.0(iOS 17)进一步定制 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")
        }
    }
    

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

    // 嵌入 Tip
    struct ContentView: View {
        let favTip = FavoriteTip()
        
        var body: some View {
            NavigationStack {
                VStack {
                    
                    TipView(favTip)
                }
                .padding()
                .navigationTitle("TitKit演示")
            }
        }
    }
    // 弹出 Tip
    struct 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 的效果如下图所示:

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

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

    如果大家对于默认 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 外观。

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

    接下来是 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)
    }
    

    运行效果如下所示:

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

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

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

    运行的效果不出意料:

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

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

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

    3. 完全自己打造 Tip 外观

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

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

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

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

    为了能够安闲自在的 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 界面的愉悦之美吧!

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

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


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

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

    • Swift 语言开发精讲

      总结

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

      感谢观赏,再会!😎

转载请注明来自码农世界,本文标题:《SwiftUI 5.0(iOS 17)进一步定制 TipKit 外观让撸码如虎添翼》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,112人围观)参与讨论

还没有评论,来说两句吧...

Top