iOS Animation Works Unexpectedly in Swift - ios

I'm developing app which contains horizontal tab bar and I made it myself.
What happens is that when I press 2nd tab bar the bottom view's width is wrong.
Here's a screenshot.
Here's a code for this.
let bottomView = UIView(frame: CGRect(x: 0, y: scrollViewSize.height-3, width: tabBarViewWidth, height: 3))
bottomView.backgroundColor = UIColorFromRGB(rgbValue: 0x92D2CD)
self.tabBarView.addSubview(bottomView)
...
//tab button click event
...
UIView.animate(withDuration: 0.3, animations: {
self.bottomView.frame.origin.x = _sender.superview?.frame.origin.x ?? 0
})
Colud any one please help me resolve this issue?

Related

iOS SearchController Searchbar does not work after adding constraint programmatically

I have an iOS project whereby the SearchController's SearchBar is added to the view as a subview:
let subView = UIView(frame: CGRect(x: 0, y: 65.0, width: 350.0, height: 45.0))
subView.addSubview((self.searchController.searchBar))
self.view.addSubview(subView)
As shown in the screenshot below, the searchbar is partially obscured by the navigation bar:
As such, I added the following constraint:
subView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([subView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor)])
The searchbar is now positioned correctly below the navigation bar as shown:
However, I'm now not able to click onto the searchbar to input any text. How can I resolve this?
How I resolved this at the end.
I still made use of a subView for the searchbar. But this time, instead of giving a fixed value for y, I used the heights of the safeArea and the navigation bar as shown:
let window = UIApplication.shared.windows.first
let safeheight = window?.safeAreaInsets.top
let navHeight = self.navigationController?.navigationBar.frame.height
let subView = UIView(frame: CGRect(x: 0, y: safeheight! + navHeight!, width: 350.0, height: 45.0))
subView.addSubview((self.searchController.searchBar))
self.view.addSubview(subView)
This time, the searchbar was positioned correctly and worked perfectly.

UIView Frame View and CGRect Not Working on First Call

So I am trying to slide a tableview in over top of a lower view, which happens to also to be a uitableview. I have a sandwich icon to slide it in and a close icon to slide it out.
The button switching works great. However, when clicking the close button, the first time, the tableview will not slide out, it will basically slid out and right back to where it is.
However subsequent times, after the close icon switches back to sandwich, and then I click again to bring back close, it will slide it out just fine. Why it not work on the first try.
Below is my code. As you can see my CGRect is supposed to animate and slide the view to the displaywidth X.
#objc func showNewsList(_ sender: UIButton) -> Void {
let displayWidth: CGFloat = self.view.frame.width
let displayHeight: CGFloat = self.view.frame.height
newsIconClose.isHidden = true
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
newsSourceTable.frame = CGRect(x: displayWidth, y: 0, width:
displayWidth, height: displayHeight + 100)
self.addNewsIcon()
})
}
Bingo, figured it out. For whatever reason, CGRect wasn't liked, but this is.
self.newsSourceTable?.frame.origin.x = 0

How to hide custom view above tableview

I have a tableView with a UIView inside it and I want with the tap of a button to disappear the view.
Because the UIView is inside the tableView (not as a cell, but above the tableView) I can't set a height constraint and make it after 0.
This is the code I use:
UIView.animate(withDuration: 2.0, animations: { () -> Void in
self.infoView.frame = CGRect(x: 0 ,y: 0, width: self.view.frame.width, height: 0)
self.view.layoutIfNeeded()
})
I also tried to set infoView equal to nil (but nothing happened)
Please leave a comment if you don't understand something I said.
Thanks in advance.
Simplest way is hide it, each view has property hidden. https://developer.apple.com/documentation/uikit/uiview/1622585-hidden
change your code
UIView.animate(withDuration: 2.0, animations: { () -> Void in
self.infoView.frame = CGRect(x: 0 ,y: 0, width: 0, height: 0)
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.automatic
self.tableView.reloadData()
})

UIView block based animation weird behavior

I have got this very simple animation (case):
class ViewController: UIViewController {
var v: UIView!
var b = false
override func viewDidLoad() {
super.viewDidLoad()
self.v = UIView(frame: CGRect(x: 120, y: 250, width: 30, height: 30))
self.v.backgroundColor = .red
self.view.addSubview(self.v)
}
#IBAction func didTapButton(_ sender: UIButton) {
UIView.animate(withDuration: 3,
delay: 0,
options: [.beginFromCurrentState, .curveLinear],
animations: {
if self.b {
self.v.frame = CGRect(x: 120, y: 250, width: 30, height: 30)
} else {
self.v.frame = CGRect(x: 240, y: 250, width: 30, height: 30)
}
self.b = !self.b
},
completion: nil)
}
}
On each tap of the button the red view moves to left or right depending on current direction. The animation should start from the current position and to be linear.
However if I tap the button when the previous animation is already in progress then the red view does not start immediately to move in the opposite direction. It just freezes in the current position while the previous animation finishes and then starts moving. If I change the animation curve option from linear to easeOut and it works properly.
I am using iOS 10, Xcode 8.2.1
Any ideas why this happens?
When the animation is on, the UI components will not react to new changes. It will buffer the input and react once the animation is complete.
This is not related to the iOS or Xcode versions, but a normal behaviour.
I've found the answer.
I tis because of the additive animations in iOS 8 and above. Here is a very useful link which explains what actually happens and why the animation freezes.
http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/

Frame on ViewController

I have this class:
extension UIViewController {
func waiting() -> UIView{
let strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 200, height: 50))
strLabel.text = "Aguarde..."
strLabel.textColor = UIColor.whiteColor()
let messageFrame = UIView(frame: CGRect(x: view.frame.midX - 90, y: view.frame.midY - 25 , width: 180, height: 50))
messageFrame.layer.cornerRadius = 15
messageFrame.backgroundColor = UIColor(white: 0, alpha: 0.40)
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
activityIndicator.startAnimating()
messageFrame.addSubview(activityIndicator)
messageFrame.addSubview(strLabel)
view.addSubview(messageFrame)
return messageFrame
}
}
When I need use this class I use:
class MyController: UIViewController{
....
func x(){
let messageFrame = waiting()
//my code
messageFrame.removeFromSuperview()
}
}
The problem is when the frame is showed if I touch anywhere on my app this frame is hidden. I need that when this frame is showed other options staying disabled, when I finish the frame, the options of app is enabled again. How can I do it?
Change the view that you are returning a bit:
Make a "container" view that has the same frame as the view controller's view. Give this view a "clear" background.
Make a "background" view, same size as the "container" view and add it to the container. Give this view a black background and an alpha of, say, 0.4.
Now put the view that you are currently building in your "waiting" method, and add it to the "container" view (NOT to the background view, this should be a sibling of the background view, otherwise your alert will also be transparent).
Make sure all user interaction is disabled on your views (might only need it disabled on the "container" view).
This gives you a container view that covers the entire screen, and it has 2 children: a transparent background of the same size, and your current "waiting" alert thing.
Now if you add the "container" view to your view controller's view, the user can only touch on the container view which does nothing.
(Keep in mind that this doesn't handle screen rotation...you will have to do that yourself if needed.)

Resources