Анимация просмотра переходит в конечную позицию вместо медленного движения

Я работаю над анимацией своего представления, которое содержит ImageView и Label. См. Рисунок 1. Я пытаюсь оживить upperView, когда прокрутка ниже tableView завершена. И окончательный результат должен выглядеть как на рисунке 2. где высота и ширина imageView уменьшены и находится в левом углу с минимальной высотой и меткой перед imageView. Анимация работает нормально, imageView плавно переходит из исходного положения в конечное, как и Label. Но upperView не работает в соответствии с анимацией.

Я пробовал это с ограничением высоты upperViews и его фреймом.

  1. Если я изменю его с помощью ограничения по высоте, он очень быстро вернется в свое окончательное положение.

  2. И если я задаю высоту с помощью upperView.frame.size.height, тогда представление поднимается, но представление таблицы остается на своих местах.

Вот что я пробовал

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.

Рисунок 1.  введите описание изображения здесь Рисунок 2. введите описание изображения здесь


person iDeveloper    schedule 21.04.2017    source источник


Ответы (2)


При анимации любых ограничений макета необходимо использовать layoutIfNeeded в блоке анимации, если вы хотите получить желаемый эффект анимации. Так что просто добавьте это в блок анимации.

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

Также используйте любой флаг, чтобы проверить, были ли виды анимированы, иначе ваш блок анимации будет выполняться несколько раз.

person ankit    schedule 21.04.2017
comment
Я пробовал self.view.layoutIfNeeded () раньше, но все равно он действует так же. Прыгает в конечную позицию. - person iDeveloper; 21.04.2017
comment
ваши блоки анимации выполняются несколько раз, сделайте их анимированными один раз. - person ankit; 21.04.2017
comment
Да, я заставил его выполнить один раз, но все равно он не анимируется. Он прыгает :( - person iDeveloper; 21.04.2017
comment
вы говорите, что вид сверху не анимируется, верно? - person ankit; 21.04.2017
comment
Да, дружище. Он сразу прыгает на высоту 50. - person iDeveloper; 21.04.2017
comment
попробуйте, self.upperViewHeightConstraint.constant = 50; self.upperView.layoutIfNeeded () означает метод компоновки после постоянного изменения - person ankit; 21.04.2017
comment
Если я добавлю self.upperView.layoutIfNeeded (), изображение и метка исчезнут - person iDeveloper; 21.04.2017

Попробуйте использовать: UIViewAnimationOptions.beginFromCurrentState, CABasicAnimation. Как анимировать кадр слоя с помощью CABasicAnimation? < / а>

Это не то, что вы ищете, но я надеюсь, что это может вам помочь.

введите описание изображения здесь

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)
}
person Dmytro Shvetsov    schedule 21.04.2017
comment
Спасибо за ответ, но я пробовал это раньше. И это работает, только если в представлении таблицы достаточно данных для прокрутки, иначе мой imageView и метка застревают между ними, что выглядит очень некрасиво. Поэтому пришлось использовать UIAnimation, чтобы он перемещался к месту назначения, даже если данных в таблице меньше. Но ограничение высоты upperView не перемещается при анимации, оно движется как пуля, что неприемлемо. - person iDeveloper; 25.04.2017