4

I'm doing my first custom segue animations. What I want is to have a list view that when I select on a row, instead of sliding in from the side, it expands in place from the row selected. Something like:

enter image description here

So the user selects the green row, which causes the new controller to start at the green row size and expand to fill the screen. This part has worked fine so far.

The problem I'm having is with the unwind segue which seeks to do the opposite, shrink the full screen back to the original row and then dismiss. What happens is that it shrinks fine, but the area exposed remains black, and then suddenly flashes into place when the animation is done. What is wanted is something like this:

enter image description here

But what is happening is more like this:

enter image description here

The code I'm using for the unwind's perform looks like:

class FromScheduleFocusSegue: UIStoryboardSegue {
    override func perform() {
        let fromView = self.source.view!
        let toView = self.destination.view!
        let window = UIApplication.shared.keyWindow!
        let schedulesList = self.destination as! SchedulesListController
        let cell = schedulesList.tableView.cellForRow(at: schedulesList.tableView.indexPathForSelectedRow!)!
        var stripe = cell.bounds
        stripe.size.height = 60
        let targetFrame = cell.convert(stripe, to: window).insetBy(dx: 0, dy: 0)
        schedulesList.tableView.selectRow(at: nil, animated: false, scrollPosition: .none)
        UIView.animateWithDuration(4000.milliseconds, delay: 0.seconds, options: .curveEaseInOut, animations: {
            fromView.frame = targetFrame
        }) { (finished) in
            self.source.dismiss(animated: false, completion: nil)
        }
    }
}

So basically, how do I get the view that I'm unwinding to to show up as the animation is taking place?

For completeness sake, here's the forward segue code:

class ToScheduleFocusSegue: UIStoryboardSegue {
    override func perform() {
        let fromView = self.source.view!
        let toView = self.destination.view!
        let window = UIApplication.shared.keyWindow!
        let box = UIScreen.main.bounds
        let schedulesList = self.source as! SchedulesListController
        let cell = schedulesList.tableView.cellForRow(at: schedulesList.tableView.indexPathForSelectedRow!)!
        toView.frame = cell.convert(cell.bounds, to: window).insetBy(dx: 0, dy: 0)
        window.insertSubview(toView, aboveSubview: fromView)
        UIView.animateWithDuration(4000.milliseconds, delay: 0.seconds, options: .curveEaseInOut, animations: {
            toView.frame = box
            }) { (finished) in
                self.source.present(self.destination, animated: false, completion: nil)
        }
    }
}

(This is in XCode8, targeted at iOS10 using Swift3)

Travis Griggs
  • 21,522
  • 19
  • 91
  • 167
  • You should use custom transitions instead. / UIPresentationController and family. – pronebird Oct 14 '16 at 23:02
  • If you can show me an example to get me going in the right direction that makes what I want visually, the bounty's all yours. – Travis Griggs Oct 15 '16 at 02:03
  • I would look more into UICollectionView. For example, see "Collection View Layout Animations for General Transitions" section here https://www.objc.io/issues/12-animations/collectionview-animations/ – Oleksii Nezhyborets Oct 17 '16 at 13:51

1 Answers1

0

Try having the view controller that does the presentation also do the dismiss.

So in your unwind segue:

UIView.animateWithDuration(4000.milliseconds, delay: 0.seconds, options: .curveEaseInOut, animations: {
        fromView.frame = targetFrame
    }) { (finished) in
        self.destination.dismiss(animated: false, completion: nil) // the destination is the one that presented the current view
    }
ray
  • 1,966
  • 4
  • 24
  • 39
  • Didn't make any difference. I'm kind of surprised, I would have expected something to be different, an error, or some other difference, but the visual behavior was the same, and nothing was different in the console output. – Travis Griggs Oct 07 '16 at 15:47