I am hiding my navigation bar and a UIView under it that acts as a extension bar to it when I scroll my page.
My app is built like:
VC that holds a container view with an embedded table view.
From the table view I have delegates that notify VC1 once a user scrolls up or down.
My problem now is that the animation dont looks that good. What I am trying to do is to animate the extension bar to animate up or down with a fade in or fade out effect as well. When that occurs I also update the top contraint on my container view so that the table view will fill the whole screen. (I am not sure if I use layoutneeded() right or if something else should be used when updating constraints)
My code:
func ContainerTableViewControllerScrolledUp(controller: ContainerTableViewController) {
self.navigationController?.setNavigationBarHidden(false, animated: true)
println("UP")
UIView.animateWithDuration(
1.5,
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.5,
options: nil,
animations: {
self.extensionV.alpha = 1
self.tableVConst.constant = 0
}, completion: { finished in
self.view.layoutIfNeeded()
}
)
}
func ContainerTableViewControllerScrolledDown(controller:ContainerTableViewController) {
self.navigationController?.setNavigationBarHidden(true, animated: true)
println("DOWN")
UIView.animateWithDuration(
1.5,
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.5,
options: nil,
animations: {
self.extensionV.frame.origin.y = CGFloat(-10)
self.tableVConst.constant = -41
self.extensionV.alpha = 0
}, completion: { finished in
self.view.layoutIfNeeded()
}
)
}
extensionV is the extension view
tableVConst is the top constraint for my container view that holds my table view
So how should I edit my code in order to get the extension view to animate up/down with a fade in/fade out effect?
Instead of calling self.view.layoutIfNeeded() in the completion block, try calling it inside the animation block on the last line before it returns.
Related
I have an UIViewController which contains a table view and a simple view. Both of them are at the same level.
At startup my view starts hidden at the bottom and when I press a button I want my view to slide up. When I do this only 1/4 of the view is shown and not the complete view.
This worked okay before adding the table view, but now I don't understand why it doesn't fully show.
Here is the code to show and hide my view:
func showPicker(date: Date?) {
UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseOut], animations: {
self.timePickerView.transform = CGAffineTransform(translationX: 0, y: 0)
}, completion: { _ in
})
}
func hidePicker() {
UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseOut], animations: {
self.timePickerView.transform = CGAffineTransform(translationX: 0, y: self.timePickerView.frame.size.height)
}, completion: { _ in
})
}
And here is a screenshot with the view (below the buttons there should be an UIDatePicker which is not shown):
Someone know what the issue is ? I am trying to do this from the storyboards.
edit:
This is what I have right now, but it still doesn't work. It doesn't animate and it also shows just a part of the view. Apparently if I increase the height the view is shown even more, so somehow it says that the shown part is exactly 220 height, which is strange :/
func hidePicker() {
self.pickerBottomConstraint.constant = -220
UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseOut], animations: {
self.timePickerView.layoutIfNeeded()
}, completion: { _ in
})
}
func showPicker(date: Date?) {
self.pickerBottomConstraint.constant = 0
UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseOut], animations: {
self.timePickerView.layoutIfNeeded()
}, completion: { _ in
})
}
If you're using autolayout, I bet you do and you should, then the easiest way to do what you wanna do is to toggle the constraint of your view, see the gif I added below.
First is to have a reference to your either top or bottom constraint of your view you wanna show and hide. Then modify the constant of the constraint to adjust its position, in that way, you get the illusion that the view is hidden and shown. The demo below uses tableView too.
Hope this helps.
See a demo here showHide that accomplish what you want
Rather then transform, change your views center y position.
ex:
#IBOutlet weak var viewToAnimateOutlet: UIView!
#IBAction func showViewButtonAction(_ sender: Any) {
UIView.animate(withDuration: 1.5) {
self.viewToAnimateOutlet.center.y -= self.viewToAnimateOutlet.frame.height
}
}
#IBAction func hideViewButtonAction(_ sender: Any) {
UIView.animate(withDuration: 1.5) {
self.viewToAnimateOutlet.center.y += self.viewToAnimateOutlet.frame.height
}
}
What i did:
I used autolayout and provided constraint for ViewToAnimate View is
ViewToAnimates.leading = safeArea.leading "constant = 8"
ViewToAnimates.trailing = safeArea.trailing "constant = 8"
This constraint will place ViewToAnimate view outside of the main views bottom. so view will not visible until showViewButtonAction method called.
ViewToAnimates.top = safeArea.bottom "constant = 0"
ViewToAnimates.height = 130
I'm trying to show a UICollectionView in a UITableViewCell. Initially the CollectionView shouldn't be shown, but when the users presses a button the CollectionView should become visible with an animation. I got this working however the first time the CollectionView becomes visible it looks like the cells get zoomed out, if I hide the CollectionView and expand it again, the animation looks correct:
http://g.recordit.co/DBhZCmJKPj.gif
This is the code for animation the change:
func expand() {
tableView?.beginUpdates()
UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveLinear, animations: {
self.imageViewDisclosureIndicator.setImage(UIImage(named: "arrow-up"), for: .normal)
self.collectionViewHeight.constant = self.collectionView.intrinsicContentSize.height
self.layoutIfNeeded()
self.isExpanded = true
}, completion: nil)
tableView?.endUpdates()
}
func collapse() {
tableView?.beginUpdates()
UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveLinear, animations: {
self.imageViewDisclosureIndicator.setImage(UIImage(named: "arrow-down"), for: .normal)
self.collectionViewHeight.constant = CGFloat(0.0)
self.layoutIfNeeded()
self.isExpanded = false
}, completion: nil)
tableView?.endUpdates()
}
Any help would be appreciated!
Try putting self.layoutIfNeeded outside the animation.
Based off your code, I don't see why you need that line of code, but it is probably the cause for your problem. I think that the content would even load fine without that line, because the size of the content view of the collection view is independent of the height of the collection view.
I want to animate a view like using the following code:
UIView.animate(withDuration: 2.7, delay: 0.1, options: .allowAnimatedContent, animations: {
self.AVCenterY.constant = 0.8
}, completion: nil)
But it happens so fast it seems like it is not animated. On the other hand, when I animate the property alpha it is animated (it takes the 2.7 seconds to change). I used 2.7 sec to make sure the problem was that I was using a small duration time.
Constraints cannot be animated at all. It is the act of layout that can be animated:
UIView.animate(withDuration: 2.7, delay: 0.1, options: .allowAnimatedContent, animations: {
self.AVCenterY.constant = 0.8
theView.superview?.layoutIfNeeded() // *
}, completion: nil)
When we animate the act of layout (or when the runtime does so), then any constraint changes are also automatically animated.
Note that what I animate is the layout of the superview of the view that is to move. I called it theView but that is just something I made up. You will need an outlet to that view so that you can get its superview, and use the name of that outlet.
so I'm trying to fade in a custom control and fade out a UIButton. The fading of the custom control is all well, but when I try to fade out the UIButton the whole screen goes black, which is due to the alpha of the root view being set to 0. Here's the code:
func fadeKeypadIn() {
UIView.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.keypad.alpha = 1
self.btnVideo.alpha = 0
}, completion: nil)
UIView.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.btnKeypad.alpha = 0
self.view.alpha = 1
}, completion: {(value: Bool) -> Void in
self.view.alpha = 1
})
}
In the above code if I don't do self.view.alpha = 1 the screen remains totally black.
And here's what the code does in action:
FadeInOutProblem
I'm using Xcode Version 7.2.1 (7C1002)
I don't know how on earth this happened, but the outlets to the buttons I wanted to fade out were referring to the parent view. :|
Recreating the outlets CAREFULLY solved the problem.
I'm trying to build my own slide out menu in swift, but I'm having some troubles.
Now, I coded a function that change the view.frame.origin.x so that I got my view to slide on the right.
Now, I added a subview at index: 0 and I want to make it show when I slide the main view (content) out.
let navView: NavigationViewController = self.storyboard?.instantiateViewControllerWithIdentifier("navView") as NavigationViewController
view.insertSubview(navView.view, atIndex: 0)
addChildViewController(navView)
navView.didMoveToParentViewController(self)
And that's what happen when I click on the menu logo (at the top-left corner):
#IBAction func showMenu(sender: AnyObject) {
println("showMenu")
if !self.menuIsOpen{
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0, options: .CurveEaseInOut, animations: { () -> Void in
self.view.frame.origin.x = 150
}) { (isHappen: Bool) -> Void in
if isHappen {
println("OpenedUp!")
self.menuIsOpen = true
}
}
} else {
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0, options: .CurveEaseInOut, animations: { () -> Void in
self.view.frame.origin.x = 0
}) { (isHappen: Bool) -> Void in
if isHappen {
println("Closed!")
self.menuIsOpen = false
}
}
}
}
So, now, this works but I suppose that the subview slides together with the rest of the main view.
How can I make the navigationView not to hide? Or better, to stay there (I mean with the origin.x: 0)
Could you have a navigation view, associated with a view controller (1), and then have the slide out menu view controller (2) inside that view controller (vc1.addSubview(vc2.view)? Then you could just keep view controller (1)'s navigation bar up and the view controller (2) would be inside it so it does not slide view controller (1)'s navigation bar.
I know I'm a bit late, but in case anyone else has the same problem: I've implemented a similar mechanic on an app I'm currently working on. To achieve it I used custom interactive transitions, which were introduced in iOS7. I would recommend checking out the following links:
See Custom Transitions Using View Controllers https://developer.apple.com/videos/wwdc/2013/
http://www.thinkandbuild.it/ios7-custom-transitions/ In this tutorial, the presented view is rotated to appear on screen; but it's not to much work to adapt the code to silde your menu in from the side and only fill part of the screen.
http://www.appcoda.com/custom-view-controller-transitions-tutorial/ This gives many examples of the kind of effects you can achieve using custom transitions.
Hope that helps.