Changing the height of a UIView in response to dragging a finger

I understand that the name is a bit confusing, so I will try to explain it well. I have a UIView with a fixed width of 100 and a variable height starting at 0. What I want to do is drag my finger from the base of the UIView to the top of the screen and the UIView changes its height / extends to the position of my finger. If this is still difficult, just imagine how a strip of paper is pulled out from under it.

If you can help, it will be really great. I donโ€™t think it should be too complicated, but Iโ€™m just a beginner and I can understand if I didnโ€™t explain it well!

+10
source share
3 answers

This should be straightforward with UIPanGestureRecognizer and a little math. To change the view to the correct frame (I use the name _viewToChange , so replace it in my opinion 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 a super view and define a 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 as the user's finger moves. Hope this helps!

+13
source

Swift version using UIPanGestureRecognizer

Using PanGesture is added to the UIView from the storyboard and the delegate is set to self. UIView is attached to the 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 } } } 
+9
source

This is my quick fix, using automatic positioning and height limits for the view you want to resize, while setting upper and lower limits depending on 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. } } 
+3
source

Source: https://habr.com/ru/post/952445/


All Articles