What I am trying to achieve is to have a button click action trigger a uiview popup with a search bar at the top of the view, which then displays a UISearchBar and a UITableView below. I have been successful at implementing these events, but when clicking inside the search bar nothing happens. The search bar just has the word search and a search bar button. I have subclassed the UISearchBarDelegate, UISearchResultsUpdating, and UISearchControllerDelegate for the ViewController. As mentioned, I am doing this programmatically in Swift without a storyboard. There are no outlets or actions. I am calling methods to perform the necessary actions.
private var resultSearchController: UISearchController!
private var locationSearchTable = LocationSearchTable()
func didClickSearchButton() {
locationSearchTable = LocationSearchTable()
locationSearchTable.tableView.delegate = self
resultSearchController = UISearchController(searchResultsController: locationSearchTable)
mapSearchTable.tableHeaderView = resultSearchController?.searchBar
resultSearchController.delegate = self
resultSearchController.searchBar.delegate = self
resultSearchController.searchResultsUpdater = self
}
I am adding the searchBar to the tableView header and it does show up.
override func viewDidLoad() {
super.viewDidLoad()
layout()
}
Calling the 'layout' in the SuperView works.
private func layout() {
popupView.translatesAutoresizingMaskIntoConstraints = false
popupView.addGestureRecognizer(panRecognizer)
didClickSearchButton()
popupView.addSubview(resultSearchController.searchBar) //Tried adding this to the view, but all it did was put it in a different location.
popupView.addSubview(openTitleLabel)
popupView.addSubview(searchButton)
popupView.addSubview(mapSearchTable)
view.addSubview(popupView)
popupView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
popupView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
bottomConstraint = popupView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: popupOffset)
bottomConstraint.isActive = true
popupView.heightAnchor.constraint(equalToConstant: 467).isActive = true
searchButton.translatesAutoresizingMaskIntoConstraints = false
searchButton.leadingAnchor.constraint(equalTo: popupView.leadingAnchor, constant: 50).isActive = true
searchButton.trailingAnchor.constraint(equalTo: popupView.trailingAnchor, constant: -50).isActive = true
searchButton.topAnchor.constraint(equalTo: popupView.topAnchor, constant: 5).isActive = true
openTitleLabel.translatesAutoresizingMaskIntoConstraints = false
openTitleLabel.leadingAnchor.constraint(equalTo: popupView.leadingAnchor, constant: 50).isActive = true
openTitleLabel.trailingAnchor.constraint(equalTo: popupView.trailingAnchor, constant: -50).isActive = true
openTitleLabel.topAnchor.constraint(equalTo: popupView.topAnchor, constant: 5).isActive = true
openTitleLabel.bottomAnchor.constraint(equalTo: popupView.bottomAnchor, constant: 0)
mapSearchTable.translatesAutoresizingMaskIntoConstraints = false
mapSearchTable.topAnchor.constraint(equalTo: popupView.topAnchor, constant: 50).isActive = true
mapSearchTable.bottomAnchor.constraint(equalTo: popupView.bottomAnchor, constant: 10).isActive = true
mapSearchTable.leftAnchor.constraint(equalTo: popupView.leftAnchor).isActive = true
mapSearchTable.rightAnchor.constraint(equalTo: popupView.rightAnchor).isActive = true
mapSearchTable.centerXAnchor.constraint(equalTo: popupView.centerXAnchor).isActive = true
}
I can see all of the elements, but there is no focus inside the text field when clicking on the input box.
It turned out that the issue was with the alpha value that was a stored property in the UISearchBar class I created to handle the rendering of the searchBar. I had the value for the alpha set to '0' and after removing that value I was able to render the UISearchBar normally.
Related
I have a UITableView in my storyboard. I am trying to setup constraints for it in my view controller. After running the application it's not showing up at all. it's only working when i don't run the constraints. here are my constraints.
func tableviewsConstraints(){
homeTableView.translatesAutoresizingMaskIntoConstraints = false
homeTableView.layer.cornerRadius = 10
homeTableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 20).isActive = true
homeTableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -20).isActive = true
homeTableView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true
homeTableView.heightAnchor.constraint(equalToConstant: homeTableView.rowHeight * 3).isActive = true
self.view.addSubview(homeTableView)
}
override func viewDidLoad() {
super.viewDidLoad()
tableviewsConstraints()
Add the homeTableView as the view's subview before adding the constraints to it. And use a constant value when setting the height of tableView, i.e.
func tableviewsConstraints(){
self.view.addSubview(homeTableView) //here....
homeTableView.layer.cornerRadius = 10
homeTableView.translatesAutoresizingMaskIntoConstraints = false
homeTableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 20).isActive = true
homeTableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -20).isActive = true
homeTableView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true
let rowHeight: CGFloat = 100.0 //here....
homeTableView.heightAnchor.constraint(equalToConstant: rowHeight * 3).isActive = true
}
Change the rowHeight value as per your requirement.
Don't you have the outlet of the table view if you have it in the storyboard? Then why you need to subview? If you're creating table view programmatically then follow this.
There is a very weird bug when I push a control to navigation controller and when I return back, look at the gif below.
Before push the detail view controller
After click on back button from detail view controller
My code:
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = Localizations.searching
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.showsScopeBar = true
viewController.navigationItem.searchController = searchController
viewController.navigationItem.hidesSearchBarWhenScrolling = false
viewController.definesPresentationContext = true
For the moment I have found a solution but that looks bad.
After push the viewcontroller I must run this:
let searchedText = searchController.searchBar.text
searchController.isActive = false
searchController.searchBar.text = searchedText
Had the same Problem and found a feasible solution:
After you add the TableView to your ViewController, pinn all directions to the safeAreaLayout(or superview)
self.view.addSubview(tableView)
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
And activate Extend Edges - Unter Opaque Bars
I created a WKWebView in code and added it to my view.
override func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
view = webView
}
When the webpage opens I can see that my navigation bar from the previous view is blocking some of my webpage.
How can I adjust the view in code to make my webpage appear below my navigation bar?
You should add a top constraint to your webview and give it a constant value that works for you (in case you want to add a margin)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.topAnchor.constraint(equalTo: parentView.topAnchor, constant: 40).isActive = true
You should also add the remaining anchor values.
webView.bottomAnchor.constraint(equalTo: parentView.bottomAnchor, constant: 0).isActive = true
webView.trailingAnchor.constraint(equalTo: parentView.trailingAnchor, constant: 0).isActive = true
webView.leadingAnchor.constraint(equalTo: parentView.leadingAnchor, constant: 0).isActive = true
I am trying to setup a couple of views programmatically. On my main view I add two subviews, one anchored to the top and one to the bottom:
//Button View
view.addSubview(buttonsLabel)
buttonsLabel.translatesAutoresizingMaskIntoConstraints = false
buttonsLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
buttonsLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
buttonsLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true
buttonsLabel.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5, constant: -20).isActive = true
//Calculator View
calcLabel.layer.cornerRadius = 25
view.addSubview(calcLabel)
calcLabel.translatesAutoresizingMaskIntoConstraints = false
calcLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
calcLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
calcLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true
//calcLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true
calcLabel.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5, constant: -40).isActive = true
This works fine, both views are 50% of the frame height (minus the constants) and both are shown (one at the top, one at the bottom). But when I try to add a third view, which is 75% of the frames height and which should be placed on top of the other two views, the layout is destroyed and everything is moved almost outside of the frame.
I am trying to anchor the third view to the bottom again:
thirdView.layer.cornerRadius = 25
view.addSubview(thirdView)
thirdView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
thirdView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
thirdView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
thirdView.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.75).isActive = true
This is how everything should look like (left the two views, right the third view on top:
Am I doing the anchors and constraints right (or whats abetter way) and how to add the constraint for the third view, so that it is 75% of the frames height and placed like in the image on top of everything.
Your code looks good the problem is else where, check the view hierarchy in the debugger to see which constraint(s) failed, perhaps you forgot translatesAutoresizingMaskIntoConstraints as beyowulf commented. you should be using constants as well, this makes code much more maintainable.
here is my implementation:
import UIKit
class ViewController: UIViewController {
//MARK: - SubViews
let topHalfView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.gray
return view
}()
let bottomHalfView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.gray
return view
}()
let threeQuarterView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.black
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//add, layout subviews with 9+ constraints
setupViews()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupViews() {
self.view.addSubview(topHalfView)
self.view.addSubview(bottomHalfView)
self.view.addSubview(threeQuarterView)
let guide = self.view.safeAreaLayoutGuide
let spacing:CGFloat = 12
let viewHeight = self.view.frame.height - spacing
topHalfView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
topHalfView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: spacing).isActive = true
topHalfView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -spacing).isActive = true
topHalfView.heightAnchor.constraint(equalToConstant: viewHeight * 0.5).isActive = true
bottomHalfView.topAnchor.constraint(equalTo: topHalfView.bottomAnchor, constant: spacing).isActive = true
bottomHalfView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: spacing).isActive = true
bottomHalfView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -spacing).isActive = true
bottomHalfView.heightAnchor.constraint(equalToConstant: viewHeight * 0.5).isActive = true
threeQuarterView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
threeQuarterView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: spacing).isActive = true
threeQuarterView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -spacing).isActive = true
threeQuarterView.heightAnchor.constraint(equalToConstant: self.view.frame.height * 0.75).isActive = true
}
}
The View hierarchy:
I am trying to programmatically set my constraints to the top of my UIViewController's Nav Bar, but I can't see to get it to work properly. Here is my code:
func setup() {
let containerView = UIView()
containerView.backgroundColor = .red
containerView.translatesAutoresizingMaskIntoConstraints = false
let payeeNameTextField = UITextField()
payeeNameTextField.backgroundColor = .green
payeeNameTextField.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(containerView)
view.addSubview(payeeNameTextField)
//iOS 9 Constraints
//x,y,w,h
// Constraint To Nav Bar
containerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
containerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
containerView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 20).isActive = true
// Constraint to Bottom Anchor
payeeNameTextField.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
payeeNameTextField.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
payeeNameTextField.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
payeeNameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
I know setting it topAnchor is wrong, but I have tried to mess around with this and just cant seem to get the red background to show up.
Thanks in advance for any input!!