Jordan
Jordan

Reputation: 2523

Changing UIView shadow size on view size change producing weird effect

I have a view that has a pan gesture recognizer on it to grow the overall height of the view as you swipe it up or down. This works well enough for now but I also wanted to add a drop shadow that I had designed and make sure that it kept with the height of the changing draggable view. However, this is producing some strange effects and I want to see if there is a way to fix this

The relevant code to handle changing the view height and the shadow height is as follows

// SET SHADOW FOR DRAGABLE VIEW PATH IN VIEW DID LOAD
draggableView.layer.shadowColor = UIColor.black.cgColor
draggableView.layer.shadowOffset = CGSize(width: 0, height: 12)
draggableView.layer.shadowOpacity = 0.33
draggableView.layer.shadowRadius = 8
draggableView.layer.shadowPath = UIBezierPath(roundedRect: 
draggableView.bounds, cornerRadius: 12).cgPath

// INSIDE THE RECOGNIZER HANDLER

if recognizer.state == .began || recognizer.state == .changed {
    translation = recognizer.translation(in: self.view)
    recognizer.setTranslation(CGPoint(x: 0.0, y: 0.0), in: self.view)
    let endPosition = recognizer.location(in: draggableView) // the posiion at which PanGesture Ended
    difference = endPosition.y - startPosition.y
    var newFrame = draggableView.frame
    newFrame.origin.x = draggableView.frame.origin.x
    newFrame.origin.y = draggableView.frame.origin.y + difference
    // HERE WE SET THE HEIGHT OF THE VIEW THAT IS BEING "DRAGGED"
    newFrame.size.height = draggableView.frame.size.height - difference
    // HERE WE UPDATE THE SHADOW PATH WITH THE NEW DRAGGABLE VIEW BOUNDS
    draggableView.layer.shadowPath = UIBezierPath(roundedRect: draggableView.bounds, cornerRadius: 12).cgPath
    draggableView.frame = newFrame
}

The effect I'm getting is the shadow not quite updating in time with the current pan gesture, here is a gif of what that looks like

enter image description here

I'm hoping there is a way I can get this to work without this weird behavior, I'm fairly new to swift though I understand the concepts it's more about not really knowing all the best ways to go about doing things

Upvotes: 1

Views: 769

Answers (1)

Fangming
Fangming

Reputation: 25261

You need to invert the order of the following two lines of code

draggableView.layer.shadowPath = UIBezierPath(roundedRect: draggableView.bounds, cornerRadius: 12).cgPath
draggableView.frame = newFrame

The reason is that you are updating the potision (Frame) of your draggableView in the PanGesture delegate method. However, you are updating the shadow frame (line 1) BEFORE updating the position (frame) of the draggable view (line 2). So, inverting the two lines will work for you

Suggestions:

In your case, you are updating frames of two views (draggable and shadow). We can see that the CPU is struggling trying to updating both of them since it's lagging (especially in the shadow part since you are re-drawing it.)

My suggestions is that you can create a parent transparent view and put your current draggable view inside and draw the shadow. This will happen only once in your viewDidLoad. Then inside gesture deletege, you will only update frame of the parent view. In this case, you do not need to update the shadow every time and the dragging will be more smooth

Upvotes: 1

Related Questions