SwiftUI中的Stepper(系统Stepper以及自定义Stepper)

news2024/9/23 15:33:13

本篇文章主要介绍一下Stepper,这个组件在UIKit中也已经有较长的历史了,下面看看在SwiftUI中如何使用,有哪些更加便捷的方法呢?

Stepper减号(-)和加号(+)按钮,可以点击后以指定的数值进行加减。

基础初始化方法

Stepper提供了很多初始化方法,先从最简单的一个入手:
在这里插入图片描述

  @State private var stepperValue: Int = 18
  var body: some View {
    Stepper("Choose your age: \(stepperValue)", value: $stepperValue, in: 16...60, step: 1)
      .foregroundColor(.red)
      .font(.system(size: 22))
//      .fontWeight(.bold) // userd for iOS 16 or later
      .accentColor(.blue)
      .padding()
  }

上面代码中我们设置了几个初始化参数:
titleKeyStepper组件左侧的提示文字。
value:一个被@State包装的属性值,用于记录Stepper的数值。
inStepper可以选择的范围,当达到最低数值时,减号变成disabled,当达到最大值时,加号变成disabled
step:每次加减的步长,即数值。

在这里可以设置提示文字的外观样式,比如foregroundColorfontfontWeight等等,不过有些修饰符是iOS 16之后才能用的,比如fontWeight
上面添加了accentColor修饰符,但是没有起作用,我们只能设置提示文字的样式,而右侧的加减小组建无法设置外观样式。

上面的初始化中提示文字的外观自定义还是比较有限的,下面的方法就自定义一个提示文字:
在这里插入图片描述

    Stepper(value: $stepperValue, in: 18...60, step: 1) {
      Text("My age is: \(value)")
        .font(.system(size: 22))
        .fontWeight(.bold)
        .foregroundColor(.white)
        .padding(.horizontal)
        .padding(.vertical, 5)
        .background(
          Capsule()
            .fill(Color.black.opacity(0.5))
        )
    }

该初始化方法中使用了label参数,这个参数是一个闭包,支持自定义一个提示文字,上面代码中通过Text组件配置了一个提示文字,Text组件的外观设置还是比较丰富的,效果图如上图。

onEditingChanged

Stepper的初始化方法中还提供了一个闭包onEditingChanged,当用户点击的时候调用。

    Stepper("Choose your age: \(stepperValue)", value: $stepperValue, in: 16...60, step: 1, onEditingChanged: { value in
      print("---> value: \(value)")
    })

当用户按下或者长按的时候onEditingChanged返回的value值为true,当用户松手的时候,返回的value值为false.

onIncrement和onDecrement

如果在数值改变的时候,我们想做一些逻辑操作,那么就需要用到下面的初始化方法,该方法提供了onIncrementonDecrement两个闭包,分别在点击加号和减号的时候调用。比如下面这个示例:
在这里插入图片描述
上面示例中在点击Stepper的时候,对图形进行倒角设置。代码如下:

struct StepperDemo: View {
  @State private var stepperValue: Int = 50

  var body: some View {
    VStack(spacing: 40) {
      RoundedRectangle(cornerRadius: CGFloat(stepperValue))
        .frame(width: 200, height: 200)

      Stepper("The cornerRadius is: \(stepperValue)", onIncrement: {
        // Increment
        onSteperChanged(10)
      }, onDecrement: {
        // Decrement
        onSteperChanged(-10)
      })
        .padding()
    }
  }

  func onSteperChanged(_ value: Int) {
    let newValue = stepperValue + value
    if newValue < 0 || newValue > 100 {
      return
    }
    withAnimation(.easeInOut) {
      stepperValue = newValue
    }
  }
}
自定义Stepper

除了系统的Stepper,我们也可以仿照系统的自定义一个Stepper,下面就是自定义的Stepper以及完整代码。
在这里插入图片描述

struct StepperDemo: View {

  @State private var stepperValue: Int = 50

  var body: some View {
    VStack {
        MyStepper(value: $stepperValue, in: 0...100, label: { Text("Value: \(stepperValue)") }, style: DefaultStepperStyle())

        MyStepper(value: $stepperValue, in: 0...100, label: { Text("Value: \(stepperValue)") }, style: DefaultStepperStyle())
            .controlSize(.mini)

        MyStepper(value: $stepperValue, in: 0...100, label: { Text("Value: \(stepperValue)") }, style: CapsuleStepperStyle())
            .controlSize(.large)
            .font(.largeTitle)
    }
    .padding()
  }
}

自定义Stepper组件:

import SwiftUI

struct MyStepper<Label: View, Style: MyStepperStyle>: View {
    @Binding var value: Int
    var `in`: ClosedRange<Int> // todo
    @ViewBuilder var label: Label
    var style: Style

    var body: some View {
        style.makeBody(.init(value: $value, label: .init(underlyingLabel: AnyView(label)), range: `in`))
    }
}

protocol MyStepperStyle {
  associatedtype Body: View
  func makeBody(_ configuration: MyStepperStyleConfiguration) -> Body
}

extension MyStepperStyle where Self == DefaultStepperStyle {
    static var `default`: DefaultStepperStyle { return .init() }
}

struct MyStepperStyleConfiguration {
  var value: Binding<Int>
  var label: Label
  var range: ClosedRange<Int>

  struct Label: View {
    var underlyingLabel: AnyView

    var body: some View {
      underlyingLabel
    }
  }
}

struct DefaultStepperStyle: MyStepperStyle {
  func makeBody(_ configuration: MyStepperStyleConfiguration) -> some View {
      Stepper(value: configuration.value, in: configuration.range) {
          configuration.label
      }
  }
}

struct CapsuleStepperStyle: MyStepperStyle {
    func makeBody(_ configuration: MyStepperStyleConfiguration) -> some View {
        CapsuleStepper(configuration: configuration)
    }
}

struct CapsuleStepper: View {
    var configuration: MyStepperStyleConfiguration

    @Environment(\.controlSize)
    var controlSize

    var padding: Double {
        switch controlSize {
        case .mini: return 4
        case .small: return 6
        default: return 8
        }
    }

    var body: some View {
        HStack {
            configuration.label
            Spacer()
            HStack {
                Button("-") { configuration.value.wrappedValue -= 1 }
                Text(configuration.value.wrappedValue.formatted())
                Button("+") { configuration.value.wrappedValue += 1 }
            }
            .transformEnvironment(\.font, transform: { font in
                if font != nil { return }
                switch controlSize {
                case .mini: font = .footnote
                case .small: font = .callout
                default: font = .body
                }

            })
            .padding(.vertical, padding)
            .padding(.horizontal, padding * 2)
            .foregroundColor(.white)
            .background {
                Capsule()
                    .fill(.tint)
            }
        }
        .buttonStyle(.plain)
    }
}

自定义的Stepper组件这里就不做过多的说明了,仅供大家参考,有需要的朋友可以研究研究。

最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1696006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SpringCloud】服务注册与发现

目录 Eureka/注册中心简介模式 使用Eureka实现注册中心1.创建一个名称为demo-eureka-server的Spring Boot项目2.添加项目依赖3. 在启动类添加启动注解4.添加配置信息Eureka的自我保护机制为Eureka Server添加用户认证1.添加依赖2. 添加配置信息3.添加放行代码4.启动服务&#x…

NASA数据集——阿尔法喷气式大气实验甲醛(HCHO)数据

Alpha Jet Atmospheric eXperiment Formaldehyde Data 简介 阿尔法喷气式大气实验甲醛数据 阿尔法喷气式大气实验&#xff08;AJAX&#xff09;是美国国家航空航天局艾姆斯研究中心与 H211, L.L.C. 公司的合作项目&#xff0c;旨在促进对加利福尼亚、内华达和太平洋沿岸地区的…

春秋云境CVE-2018-7422

简介 WordPress Plugin Site Editor LFI 正文 1.进入靶场 2.漏洞利用 /wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path/../../../../../../flag看别人wp做的。不懂怎么弄的&#xff0c;有没有大佬讲一下的

谈谈你对 vue 的理解 ?

1.谈谈你对 vue 的理解 ? 官方: Vue是一套用于构建用户界面的渐进式框架,Vue 的核心库只关注视图层 2. 声明式框架 Vue 的核心特点,用起来简单。那我们就有必要知道命令式和声明式的区别! 早在 JQ 的时代编写的代码都是命令式的,命令式框架重要特点就是关注过程 声明…

【Chrono Engine学习总结】6-创建自定义场景-6.1-3D场景获取

由于Chrono的官方教程在一些细节方面解释的并不清楚&#xff0c;自己做了一些尝试&#xff0c;做学习总结。 Chrono可以导入自定义的三维模型&#xff0c;所以想自己搭建一个3D仿真环境。过程中遇到了一些问题&#xff0c;记录与整理。 1、3D环境的创建方法 Chrono的Irrlich…

如何从头搭建一个自己的java库并上传到maven官方仓库

创建代码 在代码库根目录执行maven命令&#xff0c;用于快速生成一个基础的Maven项目 mvn archetype:generate \-DgroupIdcom.mycompany \-DartifactIdmy-maven-project \-Dversion1.0.0 \-DarchetypeArtifactIdmaven-archetype-quickstart \-DinteractiveModefalse 这个命令…

初学Echart

创建一个html文件 1.引入 点击链接----快速上手网址&#xff1a;快速上手 - 使用手册 - Apache ECharts 复制这一串【这个是引入echart路径】 引入到这里 2.使用 我们在上一步---点击返回--往下翻---找到完整代码--复制黏贴 复制粘贴后--总体长这样 <!DOCTYPE html> &…

【YOLOv10训练教程】如何使用YOLOv10训练自己的数据集并且推理使用

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Oracle Graph 入门 - RDF 知识图谱

Oracle Graph 入门 - RDF 知识图谱 0. 引言1. 查看 RDF Semantic Graph 安装情况2. 创建一个语义网络4. 创建一个模型5. 加载 RDF 文件6. 配置 W3C 标准的 SPARQL 端点 0. 引言 Oracle Graph 的中文资料太少了&#xff0c;只能自己参考英文资料整理一篇吧。 Oracle 数据库包括…

【学习笔记】计算机组成原理(八)

CPU 的结构和功能 文章目录 CPU 的结构和功能8.1 CPU的结构8.1.1 CPU的功能8.1.2 CPU结构框图8.1.3 CPU的寄存器8.1.4 控制单元CU和中断系统 8.2 指令周期8.2.1 指令周期的基本概念8.2.2 指令周期的数据流 8.3 指令流水8.3.1 指令流水原理8.3.2 影响流水线性能的因素8.3.3 流水…

从0开始带你成为Kafka消息中间件高手---第二讲

从0开始带你成为Kafka消息中间件高手—第二讲 那么在消费数据的时候&#xff0c;需要从磁盘文件里读取数据后通过网络发送出去&#xff0c;这个时候怎么提升性能呢&#xff1f; 首先就是利用了page cache技术&#xff0c;之前说过&#xff0c;kafka写入数据到磁盘文件的时候&…

深入探索:中文字符的编码与转移字符的奥秘

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;探索字符编码的世界 二、字符编码基础&#xff1a;理解ASCII与Unicode…

面向未来AI算力中心的电能消耗及优化策略

AI苏妲己&#xff1a;面向未来AI算力中心的电能消耗及优化策略 在人工智能&#xff08;AI&#xff09;和大模型技术加速发展的今天&#xff0c;智算中心对电力需求爆发式递增。如何降低这些中心的能耗成本&#xff0c;关于电能消耗趋势、新能源发电、以及源网荷储一体化解决方…

高级卫生专技资格考试报名流程及照片尺寸审核处理指南

高级卫生专业技术资格考试是卫生专业技术人员职业发展的重要环节&#xff0c;它不仅关系到个人职称的提升&#xff08;副高、正高职称&#xff09;&#xff0c;也是对其专业能力和水平的权威认证。随着考试季的临近&#xff0c;许多考生开始关注报名流程及照片尺寸审核处理等细…

代码随想录算法训练营第36期DAY39

道心破碎的一天&#xff0c;继续加油吧&#xff0c;坚持努力。 DAY39 738单调递增的数字 暴力法&#xff1a; 没有想到用int in;i>0;i--来遍历。 class Solution {private: bool checknum(int num){ if(num<10) return true; while(num/10!0){ …

详细分析Element Plus中的ElMessageBox弹窗用法(附Demo及模版)

目录 前言1. 基本知识2. Demo3. 实战4. 模版 前言 由于需要在登录时&#xff0c;附上一些用户说明书的弹窗 对于ElMessageBox的基本知识详细了解 可通过官网了解基本的语法知识ElMessageBox官网基本知识 1. 基本知识 Element Plus 是一个基于 Vue 3 的组件库&#xff0c;其中…

C++ Primer Plus第十八章复习题

1、使用用大括号括起的初始化列表语法重写下述代码。重写后的代码不应使用数组ar。 class z200 { private:int j;char ch;double z; public:Z200(int jv,char chv&#xff0c;zv) : j(jv), ch (chv), z(zv){} };double x 8.8; std::string s "what a bracing effect ! …

前端---闭包【防抖以及节流】----面试高频!

1.什么闭包 释放闭包 从以上看出&#xff1a;一般函数调用一次会把内部的数据进行清除--但是这种操作却可以一起保留局部作用域的数据 // 优点:1、可以读取函数内部的变量 2、让这些变量始中存在局部作用域当中 2.闭包产生的两种业务场景&#xff1a;防抖、节流 2.1防抖 举…

Mysql教程(0):学习框架

1、Mysql简介 MySQL 是一个开放源代码的、免费的关系型数据库管理系统。在 Web 开发领域&#xff0c;MySQL 是最流行、使用最广泛的关系数据库。MySql 分为社区版和商业版&#xff0c;社区版完全免费&#xff0c;并且几乎能满足全部的使用场景。由于 MySQL 是开源的&#xff0…

【Windows】 IDimager Photo Supreme 2024(图片管理软件)安装教程

软件介绍 IDimager Photo Supreme 2024是一款专业的图片管理软件&#xff0c;旨在帮助用户有效地组织、管理和浏览他们的照片收藏。以下是该软件的一些主要特点和功能&#xff1a; 图片管理&#xff1a;Photo Supreme提供强大的图片管理功能&#xff0c;可以帮助用户轻松地整理…