4

I am working on animating my view which contains an ImageView and a Label. Please see figure 1. I am trying to animate upperView when scrolling on below tableView is done. And the final result should look like Figure 2. where the imageView's height and width is reduced and is at the left corner with minimum height and label in front of the imageView. Animation is working fine, the imageView goes from Original position to final position smoothly and so does the Label. But the upperView doesn't works as per the animation.

I tried it with upperViews Height Constraint and by its frame.

  1. If I change it with its height Constraint it goes to its final position very quickly.

  2. And if I give height using upperView.frame.size.height then the view goes up but the table view remains on their places.

Here is what I have tried

func scrollViewDidScroll(scrollView: UIScrollView) {
  if scrollView.contentOffset.y > 0
        {
         UIView.animateWithDuration(1.5, delay: 0.0, options: .CurveEaseOut, animations:
                    {
                        self.imageView.frame = CGRect(x: 5.0, y: 0.0, width: 30, height: 40)

                    }, completion: { finished in
                        UIView.animateWithDuration(1.5, delay: 1.0, options: UIViewAnimationOptions.AllowUserInteraction,animations: {

                            self.selectedProgramNameLabel.center = CGPoint(x: self.selectedProgramNameLabel.center.x, y: self.imageView.center.y)

                            }, completion: { finished in
                                UIView.animateWithDuration(1.5, delay: 2.0, options: UIViewAnimationOptions.AllowUserInteraction, animations: {

                              self.upperViewHeightConstraint.constant = 50

                                    }, completion: { finished in

                                })
                        })
                })
        }
        else if scrollView.contentOffset.y == 0
        {
          UIView.animateWithDuration(1.5, delay: 0.0, options: .CurveEaseOut, animations:
                {
                    self.selectedProgramNameLabel.center = CGPoint(x: self.selectedProgramNameLabel.center.x, y: self.imageView.center.y + self.imageView.frame.height - 45)


                }, completion: { finished in
                    UIView.animateWithDuration(1.5, delay: 0.0, options: UIViewAnimationOptions.AllowUserInteraction,animations: {

                        self.imageView.frame = CGRect(x: self.upperView.frame.origin.x, y: self.upperView.frame.origin.y, width: 100.0, height: 134)


                        }, completion: { finished in
                            UIView.animateWithDuration(1.5, delay: 1.0, options: UIViewAnimationOptions.AllowUserInteraction, animations: {


                                }, completion: { finished in


                            })
                    })
            })

       }

TIA.

Figure 1. enter image description here Figure 2. enter image description here

iDeveloper
  • 940
  • 1
  • 10
  • 45

2 Answers2

1

While animating any layout constraints, it is must to use layoutIfNeeded in animation block if you want desired animation effect. So just add this one in animation block.

self.view.layoutIfNeeded()
self.upperViewHeightConstraint.constant = 50

Also use any flag to check whether views have been animated, otherwise your animation block will executed number of times.

ankit
  • 3,537
  • 1
  • 16
  • 32
0

Try to use: UIViewAnimationOptions.beginFromCurrentState, CABasicAnimation. How to animate the frame of an layer with CABasicAnimation?

It's not what are you looking for but I hope that can help you.

enter image description here

var cntTopViewT: NSLayoutConstraint!
var cntTopViewH: NSLayoutConstraint!

override func viewDidLoad() {
    super.viewDidLoad()

    navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
    navigationController?.navigationBar.shadowImage = UIImage()
    navigationController?.navigationBar.isTranslucent = true

    let scrollView = UIScrollView()
    scrollView.delegate = self
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(scrollView)

    let topView = UIView()
    topView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(topView)

    let topViewBackgroundImageView = UIImageView()
    topViewBackgroundImageView.translatesAutoresizingMaskIntoConstraints = false
    topView.addSubview(topViewBackgroundImageView)

    let bottomView = UIView()
    bottomView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.insertSubview(bottomView, at: 0)

    let v = UIView()
    v.translatesAutoresizingMaskIntoConstraints = false
    bottomView.addSubview(v)


    let views: [String: Any] = ["view": view,
                                "scrollView": scrollView,
                                "topView": topView,
                                "topViewBackgroundImageView": topViewBackgroundImageView,
                                "bottomView": bottomView,
                                "v": v]
    var cnts: [NSLayoutConstraint] = []

    cnts += NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: [], metrics: nil, views: views)
    cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView]|", options: [], metrics: nil, views: views)

    cnts += NSLayoutConstraint.constraints(withVisualFormat: "H:[topView(scrollView)]", options: [], metrics: nil, views: views)
    cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:[scrollView]-0@1-[topView]", options: [.alignAllCenterX], metrics: nil, views: views)
    cntTopViewT = NSLayoutConstraint(item: topView, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .top, multiplier: 1, constant: 0)
    cntTopViewH = NSLayoutConstraint(item: topView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 0)
    cnts += [cntTopViewT, cntTopViewH]

    cnts += NSLayoutConstraint.constraints(withVisualFormat: "H:|[topViewBackgroundImageView]|", options: [], metrics: nil, views: views)
    cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:|[topViewBackgroundImageView]|", options: [], metrics: nil, views: views)

    cnts += [NSLayoutConstraint(item: bottomView, attribute: .width, relatedBy: .equal, toItem: scrollView, attribute: .width, multiplier: 0.9, constant: 0)]
    cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:[scrollView]-0@1-[bottomView]|", options: [.alignAllCenterX], metrics: nil, views: views)
    cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:|[bottomView(999)]|", options: [], metrics: nil, views: views)

    cnts += NSLayoutConstraint.constraints(withVisualFormat: "H:|[v(50)]", options: [], metrics: nil, views: views)
    cnts += NSLayoutConstraint.constraints(withVisualFormat: "V:|[v(50)]", options: [], metrics: nil, views: views)

    NSLayoutConstraint.activate(cnts)

    topView.backgroundColor = .red
    bottomView.backgroundColor = .green
    v.backgroundColor = .blue
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let minH = (navigationController?.navigationBar.frame.height ?? 0) + UIApplication.shared.statusBarFrame.height
    let maxH = view.frame.height * 0.35

    cntTopViewT.constant = scrollView.contentOffset.y
    cntTopViewH.constant = max(-scrollView.contentOffset.y, minH)
    scrollView.contentInset.top = maxH
    scrollView.scrollIndicatorInsets.top = (cntTopViewH.constant - minH) + (minH * ((cntTopViewH.constant - minH) / (maxH - minH))) + 5

    //let kTransform = min(max(cntTopViewH.constant / maxH + 0.1, 0.5), 1)
    //topViewFioLabel.transform = CGAffineTransform(a: kTransform, b: 0, c: 0, d: kTransform, tx: 0, ty: 0)
}
Community
  • 1
  • 1
Dmytro Shvetsov
  • 946
  • 10
  • 13
  • Thanx for the answer but I have tried this before. And this works only if there is enough data on table view to scroll, else my imageView and label are stuck in between which looks very ugly. So had to use UIAnimation so that it moves to its destination even if data on table is less. But the upperView Height constraint is not moving when I animate, it moves like a bullet which is not acceptable. – iDeveloper Apr 25 '17 at 07:05