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

本篇文章主要介绍一下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组件这里就不做过多的说明了,仅供大家参考,有需要的朋友可以研究研究。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NDIS驱动开发-NET_BUFFER体系

网络数据由通过网络发送或接收的数据包组成。 NDIS 提供数据结构来描述和组织此类数据。 NDIS 6.0 及更高版本的主要网络数据结构包括&#xff1a; NET_BUFFERNET_BUFFER LISTNET_BUFFER_LIST_CONTEXT 它们之间的关系如下: 在 NDIS 6.0 及更高版本中&#xff0c; NET_BUFFER …

基于python数据挖掘在淘宝评价方面的应用与分析,技术包括kmeans聚类及情感分析、LDA主题分析

随着电子商务的蓬勃发展&#xff0c;淘宝作为中国最大的在线购物平台之一&#xff0c;吸引了大量的消费者进行购物并留下了大量的客户评价。这些客户评价中包含了丰富的消费者意见和情感信息&#xff0c;对于商家改进产品、提升服务质量以及消费者决策都具有重要的参考价值。 …

一个机器学习问题的重新定义

任何事物都有两面性。 一些机器学习问题也是如此。并非每个回归问题&#xff08;你认为的&#xff09;都需要回归。仔细考虑和审视问题的业务不仅可以帮助开发更好的模型&#xff0c;还可以找到有效的解决方案。 重构或重新定义&#xff08;reframing&#xff09;是一种改变机…

数据结构-思考完全二叉树

我们知道在完全二叉树中 &#xff1a; &#xff08;孩子下标-1&#xff09;/ 2 父节点下标 父节点下标*21 左孩子节点 父节点下标*22 右孩子节点 那我们该怎样理解以便之后不容易忘记呢&#xff1f; 以下是我的思考过程&#xff1a;观察下边的完全二叉树的下标规律…

Docker HTTPS api V2 Manifest V 2, Schema 2 下的免装docker下载镜像的方法

目录 前言 下载镜像代码 使用方法 原代码中无法适配 Schema 2 的原因浅析 如何解决 相对原代码改动的东西 前言 本文提供代码主要是基于 https://github.com/NotGlop/docker-drag 提供的代码修改的。链接中提供的代码应该是是基于HTTPS api V2 Manifest V 2, Schema 1实…

如何使用pycrypt加密工具测试反病毒产品的检测性能

关于pycrypt pycrypt是一款基于Python 3语言开发的加密工具&#xff0c;广大研究人员可以使用该工具来尝试绕过任意类型的反病毒产品&#xff0c;以检测目标反病毒产品的安全性能。 功能介绍 1、目前已知反病毒产品检测率为0/40&#xff1b; 2、支持绕过任意EDR解决方案&#…

Nodejs+Socket.io+Web端完成聊天

前言 源码获取:nodeexpresssocket.ioweb: 聊天demo (gitee.com) 目录结构 后端依赖 启动方式 前端是html正常启动 后端是node app.js 后端app.js核心代码 const express require(express) const app express() var http require(http).Server(app) var io require(so…

AI网络爬虫-自动获取百度实时热搜榜

工作任务和目标&#xff1a;自动获取百度实时热搜榜的标题和热搜指数 标题&#xff1a;<div class"c-single-text-ellipsis"> 东部战区台岛战巡演练模拟动画 <!--48--></div> <div class"hot-index_1Bl1a"> 4946724 </div> …

uniapp+vue3+ts开发小程序或者app架构时候的UI框架选型

使用vue3tsviteuniapp开发小程序或者跨平台app的趋势越来越高&#xff0c;有一个顺手的UI的框架还是非常重要的&#xff0c;官方维护的 uni-ui&#xff0c;支持全端&#xff0c;而且有类型提示&#xff0c;目前已经内置到 GitHub - Sjj1024/uniapp-vue3: 使用uniapp和vue3 ts …

01-05.Vue自定义过滤器

目录 前言过滤器的概念过滤器的基本使用给过滤器添加多个参数 前言 我们接着上一篇文章01-04.Vue的使用示例&#xff1a;列表功能 来讲。 下一篇文章 02-Vue实例的生命周期函数 过滤器的概念 概念&#xff1a;Vue.js 允许我们自定义过滤器&#xff0c;可被用作一些常见的文本…

Photoshop插件(UXP)编写过程中,如何更新sp-checkbox的选中状态

✨问题说明 sp-checkbox是uxpSpectrum UXP Widgets下的一个小组件&#xff0c;内置样式大概是这样&#xff1a; 那么&#xff0c;如果用js动态的改变选中的状态&#xff0c;应该如何做呢&#xff1f; 如果直接是html来写&#xff1a; <sp-checkbox checked>Checked<…

部门来了个测试开发,听说是00后,上来一顿操作给我看蒙了...

公司新来了个同事&#xff0c;听说大学是学的广告专业&#xff0c;因为喜欢IT行业就找了个培训班&#xff0c;后来在一家小公司实习半年&#xff0c;现在跳槽来我们公司。来了之后把现有项目的性能优化了一遍&#xff0c;服务器缩减一半&#xff0c;性能反而提升4倍&#xff01…

Java——图书管理系统万字详解(附代码)

框架搭建 book包 将书相关的放到book包中&#xff0c;创建一个Book类用来设置书的属性&#xff0c;包括书名、作者、价格、类型、是否被借出等。 以上属性均被private所修饰 利用编译器生成构造方法&#xff08;不需要构造isBorrowed&#xff0c;因为其初始值为false&#…

代码审计--一道简单的文件包含题目的多种利用方式

NO.1 传统方法 首先来看下代码 <?php error_reporting(0); if(isset($_GET["file"])){include($_GET["file"]); }else{highlight_file(__FILE__);phpinfo(); } ?>看完代码后再来学习学习函数吧&#xff0c;毕竟菜啊&#xff01;&#xff01;&…

【图书推荐】《Vue.js 3.x+Element Plus从入门到精通(视频教学版)》

配套示例源码与PPT课件下载 百度网盘链接: https://pan.baidu.com/s/1nBQLd9UugetofFKE57BE5g?pwdqm9f 自学能力强的&#xff0c;估计不要书就能看代码学会吧。 内容简介 本书通过对Vue.js&#xff08;简称Vue&#xff09;的示例和综合案例的介绍与演练&#xff0c;使读者…

【独家揭秘!玩转ChatGPT?一文带你解锁秘籍!】

&#x1f680;【独家揭秘&#xff01;玩转ChatGPT&#xff1f;一文带你解锁秘籍&#xff01;】&#x1f680; &#x1f449; 【直达ChatGPT体验站】 ChatGPT&#xff0c;全称“Chat Generative Pre-trained Transformer”&#xff0c;是人工智能研究实验室OpenAI于2022年底推出…

夏日炎炎,手机如何避免变成热源?这些降温技巧分享给你

夏日炎炎&#xff0c;手机也容易“中暑”。 高温不仅会让手机性能大打折扣&#xff0c;还可能引发安全隐患。因此&#xff0c;如何让手机在高温下“冷静”下来&#xff0c;成为了许多手机用户关心的问题。 本文将为你提供一些实用的降温技巧&#xff0c;帮助你的手机安全度过…

Python数据可视化(四)

实现图形的动画效果 在 matplotlib 中&#xff0c;不仅可以绘制静态图形&#xff0c;也可以绘制动态图形。对于动态图形来说&#xff0c;我们称 之为动画或许会让读者更容易明白。绘制动画的方法主要有两种&#xff1a;一种是使用模块 animation 绘制动 画&#xff1b;另一种是…

【C++题解】1699 - 输出是2的倍数,但非3的倍数的数

问题&#xff1a;1699 - 输出是2的倍数&#xff0c;但非3的倍数的数 类型&#xff1a;循环 题目描述&#xff1a; 请从键盘读入一个整数 n&#xff0c;输出 1∼n 中所有是 2 的倍数&#xff0c;但非 3 的倍数的数&#xff0c;每行 1个。 比如&#xff0c;读入一个整数10 &…

[Algorithm][动态规划][简单多状态DP问题][按摩师][打家劫舍Ⅱ][删除并获得点数][粉刷房子]详细讲解

目录 1.按摩师1.题目链接2.算法思路详解3.代码实现 2.打家劫舍 II1.题目链接2.算法思路详解3.代码实现 3.删除并获得点数1.题目链接2.算法思路详解3.代码实现 4.粉刷房子1.题目链接2.算法思路详解3.代码实现 1.按摩师 1.题目链接 按摩师 2.算法思路详解 思路&#xff1a; 确…