Ios 将子视图添加到具有遮罩视图的视图会从中移除遮罩
正如标题所述,我将Ios 将子视图添加到具有遮罩视图的视图会从中移除遮罩,ios,swift,uiview,mask,addsubview,Ios,Swift,Uiview,Mask,Addsubview,正如标题所述,我将self.view添加到另一个视图的(link)属性中,但当我使用addSubview向self.view添加更多视图时,遮罩被移除。为什么呢?谢谢 我最初遇到了问题,意识到mask视图正在发布 在我的示例中,我添加了可设置动画的UIImageViews,当我点击addView中的屏幕时,它们会在UIBezierPath上设置动画 代码如下: protocol UICircleMaskDelegate { func circleMaskCompletion() }
self.view
添加到另一个视图的(link)属性中,但当我使用addSubview
向self.view
添加更多视图时,遮罩被移除。为什么呢?谢谢
我最初遇到了问题,意识到mask
视图正在发布
在我的示例中,我添加了可设置动画的UIImageView
s,当我点击addView
中的屏幕时,它们会在UIBezierPath
上设置动画
代码如下:
protocol UICircleMaskDelegate {
func circleMaskCompletion()
}
class UICircleMask: UIView {
var delegate: UICircleMaskDelegate?
var gestureDelegate: UIGestureRecognizerDelegate?
init(gestureDelegate: UIGestureRecognizerDelegate? = nil) {
super.init(frame: .zero)
self.gestureDelegate = gestureDelegate
self.clipsToBounds = true
self.backgroundColor = .yellow
self.isUserInteractionEnabled = false
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var diameterConstraint: NSLayoutConstraint?
var animating = false
func updateSize(_ delta: CGFloat, animated: Bool = false) {
if animating { return }
if animated {
animating = true
diameterConstraint?.constant = UIScreen.main.bounds.height * 2.1
let duration: TimeInterval = Double((UIScreen.main.bounds.height - self.frame.height / 2.1) / 600)// duration = way / speed
let animation = CABasicAnimation(keyPath: "cornerRadius")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
animation.fromValue = self.layer.cornerRadius
animation.toValue = UIScreen.main.bounds.height * 2.1 / 2
animation.duration = duration
self.layer.add(animation, forKey: nil)
UIView.animate(withDuration: duration, delay: 0, options: [.curveEaseOut], animations: {
self.superview?.layoutIfNeeded()
}, completion: { (success) in
if success {
self.animating = false
self.delegate?.circleMaskCompletion()
}
})
} else {
let newSize = diameterConstraint!.constant + (delta * 2.85)
if newSize > 60 && newSize < UIScreen.main.bounds.height * 2.1 {
diameterConstraint?.constant = newSize
}
}
}
var panStarted = false
func handlePan(_ pan: UIPanGestureRecognizer) {
guard let superv = superview else { return }
let delta = pan.translation(in: superv).y
if pan.state == .began {
if delta > 0 {
panStarted = true
updateSize(-delta)
}
} else if pan.state == .changed {
if panStarted {
updateSize(-delta)
}
} else if pan.state == .ended || pan.state == .cancelled {
if panStarted {
updateSize(superv.frame.height * 2.1, animated: true)
panStarted = false
}
}
pan.setTranslation(.zero, in: superv)
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
if let superv = superview {
//
self.makeSquare()
self.centerHorizontallyTo(superv)
let c = NSLayoutConstraint.init(item: self, attribute: .centerY, relatedBy: .equal, toItem: superv, attribute: .bottom, multiplier: 1, constant: -40)
c.isActive = true
diameterConstraint = self.constrainHeight(superv.frame.height * 2.1)
//
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
panGesture.delegate = gestureDelegate
self.superview?.addGestureRecognizer(panGesture)
}
}
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.frame.width / 2
}
}
class ViewController: UIViewController, UIGestureRecognizerDelegate, UICircleMaskDelegate {
override var prefersStatusBarHidden: Bool {
get {
return true
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func circleMaskCompletion() {
// print("nana")
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.init(red: 48/255, green: 242/255, blue: 194/255, alpha: 1)
self.view.clipsToBounds = true
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tap.delegate = self
self.view.addGestureRecognizer(tap)
let circleMask = UICircleMask(gestureDelegate: self)
circleMask.delegate = self
self.view.mask = circleMask
}
func handleTap() {
let num = Int(5 + drand48() * 10)
(1 ... num).forEach { (_) in
addView()
}
}
func addView() {
var image: UIImageView!
let dd = drand48()
if dd < 0.5 {
image = UIImageView(image: #imageLiteral(resourceName: "heart1"))
} else {
image = UIImageView(image: #imageLiteral(resourceName: "heart2"))
}
image.isUserInteractionEnabled = false
image.contentMode = .scaleAspectFit
let dim: CGFloat = 20 + CGFloat(10 * drand48())
image.constrainHeight(dim)
image.constrainWidth(dim)
let animation = CAKeyframeAnimation(keyPath: "position")
let duration = Double(1.5 * self.view.frame.width / CGFloat((60 + drand48() * 40))) // duration = way / speed
animation.path = getPath().cgPath
animation.duration = duration
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
image.layer.add(animation, forKey: nil)
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + duration + 1) {
DispatchQueue.main.async {
image.removeFromSuperview()
}
}
if drand48() < 0.3 {
UIView.animate(withDuration: 0.2 + 0.1 * drand48() , delay: TimeInterval(drand48() * 1), options: [.curveEaseOut, .repeat, .autoreverse], animations: {
image.transform = CGAffineTransform.init(scaleX: 1.5, y: 1.5)
}, completion: nil)
}
self.view.addSubview(image)
self.view.sendSubview(toBack: image)
}
func getPath() -> UIBezierPath {
let path = UIBezierPath()
let startPoint = CGPoint.init(x: -30, y: self.view.frame.height / 2)
path.move(to: startPoint)
let r = CGFloat(400 * drand48())
let cp1 = CGPoint.init(x: self.view.frame.width * 0.33, y: self.view.frame.height * 0.25 - r)
let cp2 = CGPoint.init(x: self.view.frame.width * 0.66, y: self.view.frame.height * 0.75 + r)
let endPoint = CGPoint.init(x: self.view.frame.width + 30, y: self.view.frame.height / 2)
path.addCurve(to: endPoint, controlPoint1: cp1, controlPoint2: cp2)
return path
}
}
extension UIView {
func turnOffMaskResizing() {
self.translatesAutoresizingMaskIntoConstraints = false
}
@discardableResult
func makeSquare() -> NSLayoutConstraint {
self.turnOffMaskResizing()
let constraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.height, multiplier: 1.0, constant: 0)
NSLayoutConstraint.activate([constraint])
return constraint
}
@discardableResult
func centerHorizontallyTo(_ toItem: UIView, padding: CGFloat) -> NSLayoutConstraint {
self.turnOffMaskResizing()
let constraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: toItem, attribute: NSLayoutAttribute.centerX, multiplier: 1.0, constant: padding)
NSLayoutConstraint.activate([constraint])
return constraint
}
@discardableResult
func constrainHeight(_ height: CGFloat, priority: UILayoutPriority = 1000) -> NSLayoutConstraint {
self.turnOffMaskResizing()
let constraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.height, multiplier: 0, constant: height)
constraint.priority = priority
NSLayoutConstraint.activate([constraint])
return constraint
}
}
协议UICircleMaskDelegate{
func circleMaskCompletion()
}
类UICircleTask:UIView{
变量委托:UICircleMaskDelegate?
var gestureDelegate:UIGestureRecognitzerDelegate?
初始化(gestureDelegate:UIGestureRecognitizerDelegate?=nil){
super.init(帧:.0)
self.gestureDelegate=gestureDelegate
self.clipstobunds=true
self.backgroundColor=.yellow
self.isUserInteractionEnabled=false
}
必需的初始化?(编码器aDecoder:NSCoder){
fatalError(“初始化(编码者:)尚未实现”)
}
变量直径约束:NSLayoutConstraint?
var动画设置=false
func updateSize(delta:CGFloat,动画:Bool=false){
如果设置动画{return}
如果动画{
设置动画=真
直径约束?.constant=UIScreen.main.bounds.height*2.1
let duration:TimeInterval=Double((UIScreen.main.bounds.height-self.frame.height/2.1)/600)//duration=way/speed
让动画=CABasicAnimation(关键路径:“拐角半径”)
animation.timingFunction=CAMediaTimingFunction(名称:kCAMediaTimingFunctionEaseOut)
animation.fromValue=self.layer.cornerRadius
animation.toValue=UIScreen.main.bounds.height*2.1/2
animation.duration=持续时间
self.layer.add(动画,forKey:nil)
UIView.animate(持续时间:持续时间,延迟:0,选项:[.curveEaseOut],动画:{
self.superview?.layoutifneed()文件
},完成:{(成功)于
如果成功{
self.animating=false
self.delegate?.circleMaskCompletion()的
}
})
}否则{
让newSize=diameterConstraint!。常数+(增量*2.85)
如果newSize>60&&newSize0{
panStarted=true
updateSize(-delta)
}
}否则,如果pan.state==。已更改{
如果开始{
updateSize(-delta)
}
}否则,如果pan.state==.end | | pan.state==.cancelled{
如果开始{
updateSize(superv.frame.height*2.1,动画:true)
panStarted=false
}
}
平移设置平移(.0,in:superv)
}
重写func didmovetoserview(){
super.didMoveToSuperview()
如果让superv=superview{
//
self.makeSquare()
自中心水平仪(superv)
设c=NSLayoutConstraint.init(项:self,属性:.centerY,relatedBy:.equal,toItem:superv,属性:.bottom,乘数:1,常数:-40)
c、 isActive=true
直径约束=自约束高度(superv.frame.height*2.1)
//
让panGesture=UIPangESTURE识别器(目标:自我,操作:#选择器(handlePan(:))
panGesture.delegate=手势代表
self.superview?.addgesture识别器(panGesture)
}
}
覆盖func布局子视图(){
super.layoutSubviews()
self.layer.cornerRadius=self.frame.width/2
}
}
类ViewController:UIViewController、UIGestureRecognitizerDelegate、UICircleMaskDelegate{
覆盖变量prefersStatusBarHidden:Bool{
得到{
返回真值
}
}
func gestureRecognizer(uGestureRecognizer:UIGestureRecognizer,应与其他gestureRecognizer:UIGestureRecognizer同时识别)->Bool{
返回真值
}
func circleMaskCompletion(){
//印刷品(“娜娜”)
}
重写func viewDidLoad(){
super.viewDidLoad()
self.view.backgroundColor=UIColor.init(红色:48/255,绿色:242/255,蓝色:194/255,alpha:1)
self.view.clipstobunds=true
让tap=uitappesturerecognizer(目标:自我,操作:#选择器(handleTap))
tap.delegate=self
self.view.addgestureRecognitor(点击)
让circleMask=UICircleMask(手势代表:self)
circleMask.delegate=self
self.view.mask=circleMask
}
func handleTap(){
设num=Int(5+drand48()*10)
(1…num).forEach{(u)in
addView()
}
}
func addView(){
var图像:UIImageView!
设dd=drand48()
如果dd<0.5{
image=UIImageView(图像:#imageLiteral(resourceName:“heart1”))
}否则{
image=UIImageView(图像:#imageLiteral(resourceName:“heart2”))
}
image.isUserInteractionEnabled=false
image.contentMode=.scaleSpectFit
设置尺寸:CGFloat=20+CGFloat(10*drand48())
图像高度(dim)
图像宽度(dim)
让动画=关键帧动画(关键路径:“位置”)
让持续时间=Double(1.5*self.view.frame.width/CGFloat((60+drand48()*40))//持续时间=way/speed
animation.path=getPath().cgPath
animation.duration=duration
if pan.state == .began {
if delta > 0 {
panStarted = true
circle.updateSize(-delta)
}