IOS中手势UIGestureRecognizer

通常在对视图进行缩放移动等操作的时候我们可以用UIScrollView,因为它里边自带了这些功能,我们要做的就是告诉UIScrollView的几个相关参数就可以了

但是没有实现旋转的手势即UIRotationGestureRecognizer 

IOS中手势有很多:

UIRotationGestureRecognizer旋转

UITapGestureRecognizer手指点击

UIPinchGestureRecognizer缩放

UISwipeGestureRecognizer手指快速扫过

UIPanGestureRecognizer手指拖拽移动

UILongPressGestureRecognizer长按

怎么去实现自己的UIScrollView呢,还可以旋转其Content呢?

需要UIRotationGestureRecognizer、UIPinchGestureRecognizer、UIPanGestureRecognizer的组合操作,先实现单个的操作

UIPanGestureRecognizer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    func panOnView(panGesture:UIPanGestureRecognizer){
         
        println("PanClick!")
        switch(panGesture.state){
        case .Ended:
            println("end")
        case .Began:
//
            println("began")
//            velocity = CGPoint(x: panGesture.velocityInView(view).x * fps, y: panGesture.velocityInView(view).y * fps)//初始速度
        case .Changed:
            var trans = panGesture.translationInView(view)
             
            imageCenter!.transform = CGAffineTransformTranslate(imageCenter!.transform, trans.x / currentScale, trans.y / currentScale)
            panGesture.setTranslation(CGPointZero, inView: view)//translate的时候,center和position都不变
        default:
            println("default")
        }
//          adjustAnchorPointForGestureRecognizer(panGesture)
    }

UIPinchGestureRecognizer: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//缩放
func pintchOnView(pintchGesture:UIPinchGestureRecognizer){
     
    currentScale = getViewScale(pintchGesture)
    switch pintchGesture.state{
    case .Began:
    case .Ended:
        println("end")
    case .Changed:
        var scale = pintchGesture.scale
        pintchGesture.view!.transform = CGAffineTransformScale(pintchGesture.view!.transform,scale, scale)
        pintchGesture.scale = 1
    default:
        println("default")
    }
     
}

 UIPanGestureRecognizer:

1
2
3
4
5
6
7
8
9
10
11
12
13
func rotateOnView(rotateGesture:UIRotationGestureRecognizer){
    switch rotateGesture.state{
    case .Began:
    case .Ended:
        println("end")
    case .Changed:
        imageCenter?.transform = CGAffineTransformRotate(imageCenter!.transform, rotateGesture.rotation)
        rotateGesture.rotation = 0
        println("changed")
    default:
        println("default")
    }
}

 组合操作:

1
2
3
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

 一定要实现上面的函数才能组合操作,值得注意的是,因为缩放和旋转都有个中心点的问题,也是常说的瞄点,瞄点不一样,缩放和旋转产生的效果完全不一样

在视图的Layer中有一个属性anchorPoint这个点一般的默认值是(0.5,0.5)值大小是从0~1变化。如何理解瞄点,其实很简单,比如说瞄点是P点,在P处的视图上有一个很小的小花儿(假设有这个参照物),旋转之后无论图形变成什么样子,那个参照物小花儿还是在屏幕的原来的位置。比如P(0.5,0.5)那就是在视图的正中心缩放旋转,(0,0)就是左上角旋转缩放,(1,1)就是右下角缩放旋转。

如果在组合操作的时候不设置瞄点,每次手指操作的位置不同,瞄店都会变化,你不重现设置,很有可能你一旋转,视图都不知道跑哪里去了,所以在所有手势的Begin枚举的时候,应该手动再设置当前手指操作的点作为瞄点

1
2
3
4
5
6
7
8
9
10
11
func adjustAnchorPointForGestureRecognizer(gestureRecognizer:UIGestureRecognizer){
    stopTimer()
    var piece = gestureRecognizer.view
    var locationInView = gestureRecognizer.locationInView(piece)
    var locationInSuperview = gestureRecognizer.locationInView(piece?.superview)
    piece?.layer.anchorPoint = CGPoint(x: locationInView.x / piece!.bounds.size.width, y: locationInView.y / piece!.bounds.size.height)
    piece?.center = locationInSuperview
    var trans = imageCenter!.transform
    imageCenter!.transform = CGAffineTransformTranslate(trans, -trans.tx / currentScale, -trans.ty / currentScale)
    panGestureRecognizer.setTranslation(CGPointZero, inView: view)
}

 惯性:

在很多操作中我们都会看见视图缓动的动画效果,感觉好像视图在受到阻力。很多动画库里边都有这样的效果。但是动画一般都是密封的过程,也就是说假如一个移动动画持续5秒,那么在这五秒结束之前,你不能对其坐标手动赋值,除非你用一个全新的移动动画来代替它。所以常用计时器来自己写一个缓动的动画

 var fps:CGFloat = 1 / 60.0//假设在每次fps时间间隔就对对象位置赋值

 var factor:CGFloat = 0.95//摩擦系数

 var velocity = ?//手指脱离屏幕的瞬间,视图朝某个方向运动的速度,例如移动动画的缓动,将手指抬起的坐标减去抬起之前的上一个坐标,这个距离向量作为初识的速度

定义一个计时器,时间间隔为fps,每隔fps,将velocity累乘一个factor系数。视图的坐标每次就加上velocity,直到velocity=0,终止计时器。不光移动动画可以,任意的动画都可以采用这个方法,简单的实现缓动效果,好处在于,这种动画缓动摩擦系数可以自己控制,而且可以在任意缓动的过程中对对象重新定位动画的属性,只要在之前关闭计时器即可

 

 

 

 

 

 

 

 

posted @   流火行者  阅读(838)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示