Changing height of UIView in response to finger drag
This should be straight-forward with a UIPanGestureRecognizer
and a little math. To change the view to the correct frame (I'm using the name _viewToChange
, so replace that with your view later), simply add:
UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
pan.maximumNumberOfTouches = pan.minimumNumberOfTouches = 1;
[self addGestureRecognizer:pan];
to your init
method for the super view, and define the method:
- (void)pan:(UIPanGestureRecognizer *)aPan; {
CGPoint currentPoint = [aPan locationInView:self];
[UIView animateWithDuration:0.01f
animations:^{
CGRect oldFrame = _viewToChange.frame;
_viewToChange.frame = CGRectMake(oldFrame.origin.x, currentPoint.y, oldFrame.size.width, ([UIScreen mainScreen].bounds.size.height - currentPoint.y));
}];
}
This should animate the view up as the users finger moves. Hope that Helps!
This is my swift solution in doing it using autolayout and a height constraint on the view you want to resize, while setting a top and bottom limit based on the safe areas
private var startPosition: CGPoint!
private var originalHeight: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(viewDidDrag(_:)))
resizableView.addGestureRecognizer(panGesture)
}
@objc private func viewDidDrag(_ sender: UIPanGestureRecognizer) {
if sender.state == .began {
startPosition = sender.location(in: self.view)
originalHeight = detailsContainerViewHeight.constant
}
if sender.state == .changed {
let endPosition = sender.location(in: self.view)
let difference = endPosition.y - startPosition.y
var newHeight = originalHeight - difference
if view.bounds.height - newHeight < topSafeArea + backButtonSafeArea {
newHeight = view.bounds.height - topSafeArea - backButtonSafeArea
} else if newHeight < routeDetailsHeaderView.bounds.height + bottomSafeArea {
newHeight = routeDetailsHeaderView.bounds.height
}
resizableView.constant = newHeight
}
if sender.state == .ended || sender.state == .cancelled {
//Do Something if interested when dragging ended.
}
}
Swift version using UIPanGestureRecognizer
Using PanGesture added to UIView from Storyboard and delegate set to self. UIView is attached to bottom of the screen.
class ViewController: UIViewController {
var translation: CGPoint!
var startPosition: CGPoint! //Start position for the gesture transition
var originalHeight: CGFloat = 0 // Initial Height for the UIView
var difference: CGFloat!
override func viewDidLoad() {
super.viewDidLoad()
originalHeight = dragView.frame.height
}
@IBOutlet weak var dragView: UIView! // UIView with UIPanGestureRecognizer
@IBOutlet var gestureRecognizer: UIPanGestureRecognizer!
@IBAction func viewDidDragged(_ sender: UIPanGestureRecognizer) {
if sender.state == .began {
startPosition = gestureRecognizer.location(in: dragView) // the postion at which PanGestue Started
}
if sender.state == .began || sender.state == .changed {
translation = sender.translation(in: self.view)
sender.setTranslation(CGPoint(x: 0.0, y: 0.0), in: self.view)
let endPosition = sender.location(in: dragView) // the posiion at which PanGesture Ended
difference = endPosition.y - startPosition.y
var newFrame = dragView.frame
newFrame.origin.x = dragView.frame.origin.x
newFrame.origin.y = dragView.frame.origin.y + difference //Gesture Moving Upward will produce a negative value for difference
newFrame.size.width = dragView.frame.size.width
newFrame.size.height = dragView.frame.size.height - difference //Gesture Moving Upward will produce a negative value for difference
dragView.frame = newFrame
}
if sender.state == .ended || sender.state == .cancelled {
//Do Something
}
}
}