UIScrollView实现原理,简单实现
1 bounds和frames的区别
bounds是相对于自身坐标系来说的位置和尺寸,并且origin一般为(0,0)
frame是相对于父视图坐标系来说自己的位置和尺寸
对于一个UIView实例subview,改变view的bounds并不会改变它在superview中的位置
view.bounds.origin = CGPoint.init(x:0,y:0)
view.bounds.origin = CGPoint.init(x:10,y:0)
在superview中的位置有啥区别?
对于frame来说,其在superview中的位置,计算公式如下:
let subview =UIView.init(frame:CGRect.init(x:20, y:20, width:10, height:10))
其在superview中的位置一定在(20,20)吗?
frame的计算公式:
subview.frame.origin.x = subview.frame.origin.x - superview.bounds.origin.x
subview.frame.origin.y = subview.frame.origin.y - superview.bounds.origin.y
//
2简单实现scrollView
基于上面对bounds和frames的理解,简单实现了scrollView
1创建继承自UIView的view
class CJScrollView:UIView{
}
2模拟滑动手势
let panGesture =UIPanGestureRecognizer.init(target:self, action:#selector(panGestureAction(pan:)))
self.addGestureRecognizer(panGesture)
letpanGesture =UIPanGestureRecognizer.init(target:self, action:#selector(panGestureAction(pan:)))
self.addGestureRecognizer(panGesture)
3:在手势中进行判断(核心代码)
ifpan.state== .began{
startLocation=self.bounds.origin
NSLog("\(startLocation)")
}
ifpan.state== .changed{
letpoint = pan.translation(in:self)
NSLog("\(point)")
varnewOriginX =self.startLocation.x- point.x
varnewOriginY =self.startLocation.y- point.y
//
ifnewOriginX <0{
newOriginX =0
}else{
letmaxMoveWidth =contentSize.width-self.bounds.width
ifnewOriginX > maxMoveWidth{
newOriginX = maxMoveWidth
}
}
ifnewOriginY <0{
newOriginY =0
}else{
letmaxMoveHeight =contentSize.height-self.bounds.height
ifnewOriginY > maxMoveHeight{
newOriginY = maxMoveHeight
}
}
varbounds =self.bounds
bounds.origin=CGPoint.init(x:newOriginX, y:newOriginY)
self.bounds= bounds
}
Demo:https://github.com/caoxijian/ScrollViewTest