I am trying to reduce a view to a circle on swipe gesture (in any direction, fast or slow), similar to the experience on WhatsApp videoCall view. See images below, to get an idea of what I am trying to achieve.
I believe I need to use swipe gesture to achieve this, I've added a swipe gesture to my videoView, I am not sure what to do next.
In viewDidLoad I have the below
videoView.addGestureRecognizer(UISwipeGestureRecognizer(target: self, action: #selector(self.minimiseView) ))
I think I need to use gesture location ? and I also need to set the corner radius that increases with the swipe. Could some one please advise how I could achieve this ?
func minimiseView(gesture: UISwipeGestureRecognizer){
let location = gesture.location(in: self.view)
}
You basically want to do the following steps:
cornerRadius = distanceSwiped
Here’s a basic setup for how you might accomplish this:
enum VideoDismissState {
case cornerRadiusChanging, sizeChanging, complete
}
var initialGesturePosition: CGPoint = .zero
var maxCornerRadiusGesturePosition: CGPoint = .zero
var dismissState: VideoDismissState = .complete
func minimiseView(_ gesture: UISwipeGestureRecognizer) {
let location = gesture.location(in: videoView)
switch gesture.state {
case .began:
initialGesturePosition = gesture.location(in: videoView)
dismissState = .cornerRadiusChanging
case .changed:
let currentPosition = gesture.location(in: videoView)
switch dismissState {
case cornerRadiusChanging:
let swipeDistance = distance(between: initialGesturePosition, and: currentPosition)
// play around with this formula to see what feels right
videoView.layer.cornerRadius = swipeDistance / 2
// at a certain point, switch to changing the size
if swipeDistance >= videoView.width / 2 {
maxCornerRadiusGesturePosition = currentPosition
dismissState = .sizeChanging
}
case sizeChanging:
let swipeDistance = distance(between: maxCornerGesturePosition, and: currentPosition)
// again try different things to see what feels right here
let scaleFactor = 50 / swipeDistance
videoView.layer.transform = CGAffineTransform(scaledX: scaleFactor, y: scaleFactor
if scaleFactor <= 0.2 {
dismissState = .complete
}
case complete:
// reset values
initialGesturePosition = .zero
maxCornerRadiusGesturePosition = .zero
// dismiss videoView
// for example: videoView.isHidden = true OR videoView.removeFromSuperview()
}
case .ended:
// if the gesture ends too soon you may want to animate the view back to full screen
}
}
/// Measure distance between two points
func distance(between first: CGPoint, and second: CGPoint) -> CGFloat {
return sqrt((first.x - second.x) ^ 2 + (first.y - second.y) ^ 2)
}
This may not work entirely as I haven’t tested it but the basic idea should be enough to get you started.