• 【SwiftUI模块】0018、SwiftUI搭建一个类似支付宝中的余额宝余额数字动画效果


    SwiftUI模块系列 - 已更新18篇
    SwiftUI项目 - 已更新1个项目
    往期Demo源码下载

    技术:SwiftUI、SwiftUI3.0、支付宝、余额宝、数字动画
    运行环境:
    SwiftUI3.0 + Xcode13.4.1 + MacOS12.5 + iPhone Simulator iPhone 13 Pro Max

    概述

    SwiftUI搭建一个类似支付宝中的余额宝余额数字动画效果

    详细

    一、运行效果

    请添加图片描述

    二、项目结构图

    在这里插入图片描述

    三、程序实现 - 过程

    思路

    1. 先看一下原理图

    在这里插入图片描述
    2. 其实就是在视图里面创建一排数字比如 0~9 垂直排列展示 然后将其他部分进行切割
    3. 拿到当前的数字 和 之前的数字进行每一个位数进行比较
    如果是当前数字位数大于之前位数 就向上滚动。
    如果当前位数小数之前的尾数就向下滚动

    1.创建一个项目命名为 RollingCounter

    在这里插入图片描述
    在这里插入图片描述

    1.1.引入资源文件和颜色

    2. 创建一个虚拟文件New Group 命名为 View

    在这里插入图片描述
    在这里插入图片描述

    2. 创建一个文件New File 选择SwiftUI View类型 命名为RollingText

    主要是:处理数字的动画效果

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    Code

    ContentView - 主窗口

    主要是展示主窗口Home和手动改变随机数

    //
    //  ContentView.swift
    //  Shared
    //
    //  Created by lyh on 2022/8/29.
    //
    
    import SwiftUI
    
    struct ContentView: View {
        @State var value :Int = 0
        var body: some View {
        
            NavigationView{
                VStack(spacing:25){
                    RollingText(font: .system(size: 55), weight: .black, value: $value)
                    
                    Button("change Value"){
                        value = .random(in: 100...2999)
                    }
                }
                .padding()
                .navigationTitle("RollingCounter")
            }
            
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    Home - 主页

    思路

    1. 先看一下原理图

    在这里插入图片描述
    2. 其实就是在视图里面创建一排数字比如 0~9 垂直排列展示 然后将其他部分进行切割
    3. 拿到当前的数字 和 之前的数字进行每一个位数进行比较
    如果是当前数字位数大于之前位数 就向上滚动。
    如果当前位数小数之前的尾数就向下滚动

    //
    //  RollingText.swift
    //  RollingCounter (iOS)
    //
    //  Created by lyh on 2022/8/30.
    //
    
    import SwiftUI
    
    struct RollingText: View {
        // 文本属性
        var font : Font = .largeTitle
        var weight : Font.Weight = .regular
        @Binding var value : Int
        
        // 动画属性
        @State var animationRange: [Int] = []
        var body: some View {
          
            HStack(spacing:0){
                ForEach(0..<animationRange.count,id: \.self){index in
                    //查找给定字体的文本大小
                    Text("8")
                        .font(font)
                        .fontWeight(weight)
                        .opacity(0)
                        .overlay{
                            GeometryReader{ proxy in
                                let size = proxy.size
                                
                                VStack(spacing:0){
                                    // MARK:因为它的个人价值
                                    //我们需要从0到9
                                    ForEach(0...9,id: \.self){number in
                                        Text("\(number)")
                                            .font(font)
                                            .fontWeight(weight)
                                            .frame(width:size.width,height:size.height,alignment: .top)
                                    }
                                }
                                // 设置偏移量
                                .offset(y:-CGFloat(animationRange[index]) * size.height)
                            }
                            .clipped()
                        }
                }
            }
            .onAppear{
                // 加载范围
                animationRange = Array(repeating: 0, count: "\(value)".count)
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.06) {
                    updateText()
                }
            }
            .onChange(of: value) { newValue in
                // 处理额外价值的添加/移除
                let extra = "\(value)".count - animationRange.count
                if extra > 0{
                    // 添加额外的范围
                    for _ in 0..<extra {
                        withAnimation(.easeIn(duration:0.1)){ animationRange.append(0)
                            
                        }
                    }
                }
                else
                {
                    for _ in 0..<(-extra) {
                        withAnimation(.easeIn(duration:0.1)){ animationRange.removeLast()
                        }
                    }
                }
                updateText()
            }
        }
        
        func updateText(){
            let stringValue = "\(value)"
            for(index,value) in zip(0..<stringValue.count, stringValue){
                //如果First Value = 1
                //然后Offset将被应用为-1
                //所以文本将向上移动显示1Value
                // 基于指标值的阻尼分数
                var fraction = Double(index) * 0.15
                // Max = 0.5
                // Total = 1.5
                
                fraction = (fraction > 0.5 ? 0.5 : fraction)
                withAnimation(.interactiveSpring(response: 0.8, dampingFraction: 1, blendDuration: 1 + fraction)){
                    animationRange[index] = (String(value) as NSString).integerValue
                }
            }
        }
    }
    
    struct RollingText_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
  • 相关阅读:
    论文解读(GATv2)《How Attentive are Graph Attention Networks?》
    Android:使用Jetpack Compose画渐变背景
    淘宝API系列,商品详情数据的获取(数据聚全)
    03 【布局之Aspect-Ratio Container Box-Decoration-Break Object-Fit Object-Position】
    最佳实践:Websocket 长连接状态如何保持
    飞桨中国行落地广州 共探企业智能化升级新路径
    尿检设备“智能之眼”:维视智造推出MV-MC 系列医疗专用相机
    OpenGL - Advanced Data & GLSL
    TiDB Cloud
    水稻生物育种突破 国稻种芯-何登骥:功能性农业外源植物导入
  • 原文地址:https://blog.csdn.net/qq_42816425/article/details/126593800