I want to click a button and have my View slowly animate into the viewing area from the right side of the screen. Then click a second button and have the view animate off the screen from left to right
I added a Button (OpenButton with IBAction = openView) and a View (DataView) into my main ViewController. I set constraints on DataView to be the safe area for top(20), bottom(20), leading(16) and trailing(16). I also added a Button (CloseButton with IBAction = closeView) into the DataView.
While in Portrait mode, clicking the OpenButton results in the OpenView( ) function being called and the DataView animating properly from right to left into the visible screen as desired. Clicking the CloseButton results in the view animating off the screen from left to right as desired. (Note: There are no calls to viewWillLayoutSubviews( ) which are made by the system at this time). I can click OpenButton and CloseButton multiple times and the animation works great each time while in Portrait mode.
I now switched to Landscape mode. Clicking the OpenButton results in the openView( ) function being called and the DataView animating properly from right to left into the visible screen as desired. Clicking the CloseButton results in weird animation in the wrong places and the DataView does not properly go off the screen. Debugging has shown that when the CloseButton is pressed, then viewWillLayoutSubviews() and viewDidLayoutSubviews( ) are called, then the closeView( ) function is called and then viewWillLayoutSubviews() and viewDidLayoutSubviews( ) are called a second time. When viewDidLayoutSubviews() is called a second time, then the DataView snaps back to it's origin.x constraint value of 16 which results in it moving back to the leading safe area, which affects the animation which is currently going on. It seems like that is what is messes up the animation.
Debug "print" statement output
<Note: OPEN button clicked here>
openScoreWindow -- enter
dataView.frame.origin.x = 16.0
animation complete - openScoreWindow
<Note: CLOSE button clicked here>
viewWillLayoutSubviews
dataView.frame.origin.x = 16.0
viewDidLayoutSubviews
dataView.frame.origin.x = 16.0
closeScoreWindow -- enter
dataView.frame.origin.x = 16.0
viewWillLayoutSubviews
dataView.frame.origin.x = 767.0 <--- this value is set in the UIVIew_Animate( ) in the closeView( ) function, as desired
viewDidLayoutSubviews
dataView.frame.origin.x = 16.0 <--- this is proof the "leading" constraint is reset back to 16 during the active animation
animation complete - closeScoreWindow . <-- this is when animation has completed
** I tried to replicate this scenario by creating a separate brand new swift "test project" which just had the two buttons and dataView, however, in this "test project", the animation in portrait and landscape mode works as desired since viewWillLayoutSubviews() is never called when opening and closing the view. Oh well, for some reason, in my project, viewWillLayoutSubviews() is called twice when I click the Close button.
I have no idea how to get around this issue. Any ideas?
override func viewDidLoad()
{
super.viewDidLoad()
dataView.isHidden = true
print ("viewDidLayoutSubviews")
print(" dataView.frame.origin.x = \(dataView.frame.origin.x)")
print("")
}
@IBAction func openView()
{
print("openScoreWindow -- enter")
print(" dataView.frame.origin.x = \(dataView.frame.origin.x)")
//ensure view is positoned out of the viewing area
dataView.frame.origin.x = getScreenSize().width + 100
//make view visible for eventual animation
dataView.isHidden = false
//animate view moving from right to left onto the screen
UIView.animate(withDuration: 1.0, //1 second
delay: 0,
options: .curveEaseInOut,
animations:
{
self.dataView.frame.origin.x = 16
},
completion: { [weak self] finished in
print(" animation complete - openScoreWindow")
print("")
})
}
}
@IBAction func closeView()
{
print("closeScoreWindow -- enter")
print(" dataView.frame.origin.x = \(dataView.frame.origin.x)")
//animate view moving from left to right off the screen
UIView.animate(withDuration: 3.0, //1 second
delay: 0,
options: .curveEaseInOut,
animations: {
//move view out of the viewing area
self.dataView.frame.origin.x = self.getScreenSize().width + 100
},
completion: { [weak self] finished in
//hide the view
self?.dataView.isHidden = true
print(" animation complete - closeScoreWindow")
print("")
})
}