大师学SwiftUI第12章 - 手势 Part 2

本文围绕SwiftUI展开,介绍了放大、旋转和拖拽三种手势。放大手势可让用户放大或缩小图片,还能设置缩放比例限制;旋转手势用于旋转图片;拖拽手势可实现应用间或应用内区域间的内容移动,还能自定义预览和处理自定义数据类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

放大手势

放大手势常被称为捏合手势,因为常常在用户张开或捏合两个手指时进行识别。通常这个手势实现用于让用户放大或缩小图片。

发送给​​updating()​​、​​onChanged()​​和​​onEnded()​​方法的值是一个​​CGFloat​​,表示乘上当前比例的倍数,得到图片最终的比例,如下例所示。

示例12-9:定义一个​​MagnificationGesture​​手势

struct ContentView: View {
    @GestureState private var magnification: CGFloat = 1
    @State private var zoom: CGFloat = 1
    
    var body: some View {
        Image(.spot1)
            .resizable()
            .scaledToFit()
            .frame(width: 160, height: 200)
            .scaleEffect(zoom * magnification)
            .gesture(MagnificationGesture()
                .updating($magnification) { value, state, transaction in
                    state = value
                }
                .onEnded { value in
                    zoom = zoom * value
                }
            )
    }
}

示例12-9中的代码定义了两个状态,一个用于记录放大倍数,另一个用于存储最终值。这是为了允许用户多次放大或缩小。执行手势时,倍数值存储在​​magnification​​属性中,但​​zoom​​属性的值直到手势完成时才发生改变,因此在下次用户放大或缩小时,新的比例以上次为基准计算。

为设置图片为用户所选比例,我们对​​Image​​视图应用​​scaleEffect()​​修饰符,并通过将​​zoom​​属性值(用户设置的上一个比例)乘上​​magnification​​属性的值(手势所产生的倍数)计算新的比例。结果就是图片根据手指的移动放大或缩小。

✍️跟我一起做:使用示例12-9中的代码更新​​ContentView.swift​​文件。捏合两个手指来放大或缩小。在模拟器或画面中运行应用时,点击键盘上的Option键激活手势。

示例12-9中的示例允许用户任意放在和缩小图片,但大部分情况下我们需要限制视图的比例为合理值或符合应用的目的。要设置这些限制,我们需要在两处控制比例:对视图应用​​scaleEffect()​​修饰符时,以及手势结束最终的比例设置为​​zoom​​属性时。

示例12-10:确定最小和最大比例

struct ContentView: View {
    @GestureState private var magnification: CGFloat = 1
    @State private var zoom: CGFloat = 1
    
    var body: some View {
        Image(.spot1)
            .resizable()
            .scaledToFit()
            .frame(width: 160, height: 200)
            .scaleEffect(getCurrentZoom(magnification: magnification))
            .gesture(MagnificationGesture()
                .updating($magnification) { value, state, transaction in
                    state = value
                }
                .onEnded { value in
                    zoom = getCurrentZoom(magnification: value)
                }
            )
    }
    func getCurrentZoom(magnification: CGFloat) -> CGFloat {
        let minZoom: CGFloat = 1
        let maxZoom: CGFloat = 2
        
        var current = zoom * magnification
        current = max(min(current, maxZoom), minZoom)
        return current
    }
}

本例中,视图的缩放比例限定在最小为1,最大为2。因我们需要执行一些操作来限定比例为这些值,我们将处理移到一个方法​​getCurrentZoom()​​中,在需要时进行调用。该方法定义了最大最小比例这两个常量,然后通过乘上​​zoom​​属性和放大倍数来计算当前值,最后使用​​min()​​和​​max()​​函数来限定最小为1倍,最大为2倍的结果。​​min()​​函数比较当前比例和最大允许比例,返回两者中的最小值(如果值大于2,返回2),而​​max()​​函数比较结果和最小允许比例,返回两者中的最大值(如值小于1,返回1)。​​getCurrentZoom()​​方法由​​scaleEffect()​​修饰符调用,用于设置视图的比例,​​onEnded()​​方法设置最终比例。因此用户可以放大及缩小图片,但最大为2倍,最小为1倍。

✍️跟我一起做:使用示例12-10中的代码更新​​ContentView​​结构体。则可以按​​minZoom​​和​​maxZoom​​常量所设定的限制来设置视图大小。

旋转手势

旋转手势为用户用两根手势触摸屏幕并做环形移动。常用于旋转图片。就像前面的手势一样,如果希望用户多次执行手势,就需要存储两个状态,一个为当前旋转,另一个是最终旋转。手势所生成的值为​​Angle​​类型的结构体。我们之前使用过这个结构体。它包含两个类型方法,一个用角度创建实例(​​degrees​​(​​Double​​)),另一个通过弧度​​radians​​(​​Double​​)),但在我们示例中将通过手势来旋转图片,因此对当前角度加上手势所产生的变化角度。

示例12-11:定义​​RotationGesture​​识别器

struct ContentView: View {
    @GestureState private var rotationAngle: Angle = Angle.zero
    @State private var rotation: Angle = Angle.zero
    
    var body: some View {
        Image(.spot1)
            .resizable()
            .scaledToFit()
            .frame(width: 160, height: 200)
            .rotationEffect(rotation + rotationAngle)
            .gesture(RotationGesture()
                .updating($rotationAngle) { value, state, transaction in
                    state = value
                }
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值