nsomar / OAStackView

Porting UIStackView to iOS 7+
MIT License
2.14k stars 191 forks source link

Add animation to is hidden #11

Open nsomar opened 9 years ago

nsomar commented 9 years ago

The current behaviour for hiding looks like the below: Alt text

The correct version should look similar to the below. Alt text

This issue happens since when hiding the view, the correct implementation is to remove it, an hiding animation should be run on the hidden view before removing it.

WestonHanners commented 9 years ago

As a workaround you can add

myStackView.layoutIfNeeded() in your animation block to animate the change.

(This works on iOS 8)

@IBAction func touched(sender: UIButton) {
  UIView.animateWithDuration(0.2, animations: { () -> Void in
    sender.hidden = true
    sender.superview!.layoutIfNeeded()
  })
}

This will animate the arrangement giving you nice slide animations, the touched view will still disappear instantly, so its only a partial fix.

Thomvis commented 9 years ago

Normally a view that is set to be hidden will hide immediately. So is UIStackView doing some trickery there? Are they perhaps snapshotting the view or something?

WestonHanners commented 9 years ago

in iOS9, it looks like hidden is an animatable property, but I would have to spike it to confirm. My code above simply animates the arrangement, the view still hides instantly.

Thomvis commented 9 years ago

So that will probably not work pre iOS 9. Snapshotting could be an option, but is a bit hacky. Another way to animate a hiding view is to not set the view hidden, but instead remove it from the arranged views and animate its alpha. (This will need https://github.com/oarrabi/OAStackView/pull/17)

WestonHanners commented 9 years ago

are we wanting the scale animation? or simply a fade? I think setting alpha alongside hidden should achieve that in iOS 8 wouldn't it?

FYI, the above gif is from TZStackView, not UIStackView, not sure if the scale is in the real thing.

I'd imagine anything we try to do to implement UIStackView in <iOS 9 is going to be hacky :D

bencallis commented 9 years ago

Snapshotting the view may be a sensible approach as if you try and reduce a views width/height constraint to 0 during the animation it may break the views subviews constraints (if it has any) resulting in strange visual defects.

E.g. if a view added to a stack view has multiple subviews which have constraints which stop the view from going less than 20 points wide. If we animate the views width to 0 it will break the constraints. If we used a snapshot for this it wouldn't be a problem. However, shrinking the image made also look ugly? Maybe a shrink and fade of the snapshot would work best?

Alternatively it may be possible to add each arranged view to a container view where the arranged view it pinned to leading and trailing with a less than required priority. The container height/width would be based on the embedded arranged views height/width. That way if we animate the containers height/width to 0 we would get the same animation as the default UIStackView.

nsomar commented 9 years ago

I just reviewed UIStackView on iOS 9 Beta 4. I dont think it snapshots the view.

Notice the following gif: record

The constraints added to the grey view are no surprise:

constraints

Buttons are aligned top,bottom,center. The label has top/bottom/leading.

From the animation, I think that UIStackView removes the bottom constraint from the label before animating. However, I still dont know what it does to the buttons as they seem to move.

mthole-old commented 9 years ago

@oarrabi Do you have any updated thoughts on the direction here?

nsomar commented 8 years ago

@mthole sorry for the very late answer. No I still don't have a clear solution here. would appreciate any help at the moment.

panupan commented 8 years ago

Another bug I noticed is that if a subview starts out hidden and you try to unhide it with animation, it flies in offscreen.