UIPickerView width constraint issue - ios

I need to add UIPickerView to UIAlertController. I use code:
let alertView = UIAlertController()
let pickerView = UIPickerView()
pickerView.translatesAutoresizingMaskIntoConstraints = false
alertView.view.addSubview(pickerView)
pickerView.topAnchor.constraint(equalTo: alertView.view.topAnchor, constant: 50).isActive = true
pickerView.bottomAnchor.constraint(equalTo: alertView.view.bottomAnchor, constant: -50).isActive = true
pickerView.centerXAnchor.constraint(equalTo: alertView.view.centerXAnchor).isActive = true
pickerView.widthAnchor.constraint(equalTo: alertView.view.widthAnchor).isActive = true
present(alertView, animated: true)
Here it is a result:
Why width of the UIPickerView more than UIAlertController?
Also I tried:
pickerView.widthAnchor.constraint(equalTo: alertView.view.widthAnchor, multiplier: 0.5).isActive = true
But got the same result...

when you give a constraint of width which exactly doing right.Issue is from your side look below image when you give a width constant of alertview.view which one UIalertController's main view.For better understand look below image(last view behind blue colour view colour and PickerView color is red.).
Now,we show actual alerview which one subview of main view(in above image Blue colour with Ok button).
change width constraint with subview instead of main view like:-
For better under standing:-
for view in alertView.view.subviews {
print(view)
//just add color which is shown in bellow image.
view.backgroundColor = UIColor.blue
}
So, Solution is like:-
pickerView.widthAnchor.constraint(equalTo: alertView.view.subviews[0].widthAnchor).isActive = true
Result:-
I hope this help you,
Thanks

Related

UILabel position not updating even after changing constraints on button click

I am trying to change the constraints of a UILabel to 30 pixels down so I'm changing it like below:
The initial constraints are:
testLabel.topAnchor.constraint(equalTo: fastestInfoText.bottomAnchor,constant: 5).isActive = true
The button functionality:
#objc func infoIcon3Pressed(sender: UIButton){
fastestInfoText.isHidden = !fastestInfoText.isHidden
testLabel.topAnchor.constraint(equalTo: fastestInfoText.bottomAnchor,constant: 30).isActive = true
}
But still the UILabel is not changing its position to up or down.
I was trying to change constraints after button is clicked.
You're actually creating 2 constraints and activating them both.
Instead make constraint as global variable, and update the constant value when user taps on Button.
lazy var testLabelTopConstraint = testLabel.topAnchor.constraint(equalTo: fastestInfoText.bottomAnchor, constant: 5);
// Activate constraint in view didload.
testLabelTopConstraint.isActive = true
#objc func infoIcon3Pressed(sender: UIButton){
fastestInfoText.isHidden = !fastestInfoText.isHidden
testLabelTopConstraint.constant = 30
}

How to hide a UIView and set new height to UITable view in swift?

I have a UITable view in my View controller and a stackview at the bottom of the table view. I want the UITable view to go full view when stackview isHidden. Here is the code i write to do so :
if response.total != 0.0{
checkoutStackView.layoutIfNeeded()
medDetailTableView.translatesAutoresizingMaskIntoConstraints = false
medDetailTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0).isActive = true
vwPlaceOrder.isHidden = true
viewCheckout.isHidden = true
checkoutStackView.isHidden = true
}else{
checkoutStackView.layoutIfNeeded()
viewCheckout.isHidden = false
checkoutStackView.isHidden = false
self.vwPlaceOrder.isHidden = false
self.lblTotalItemsPrice.text = String(format: "%.1f",response.total)
medDetailTableView.translatesAutoresizingMaskIntoConstraints = false
medDetailTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -70.0).isActive = true
}
But this code is only showing the stackview but when the stackview is hidden UITableview is not going full view.
Here is a image when stackview is showing:
And here is the image when stackview is hidden:
Try to use footer view of UITableView for placing your view. And make UITableView full size of it's superview.
It should solve your problem.
When you hide a view in Swift , it just make it hide but constraints of hiden view is still alive. So you must to set 0 this height constraints.
For this you can create an outlet of Constraints and change it like :
#IBOutlet weak var heightConstt: NSLayoutConstraint!
And when you hide stackView change its constraint
heightConstt.constant = 0

Blurred overlay does not cover entire screen

I'm trying to display a blurred background over a ViewController that contains a UITableView and is displayed modally. But I can't seem to get the blur effect to cover the entire screen, specifically the Navigation and Status Bars. Below is a screenshot of the blur effect covering the area below the Navigation Bar but not above it -- this happens when I set the frame of the UIVisualEffectView to view.bounds. (Note: The blur effect is designed to be displayed at the same time as the title screen w/ keyboard, and the title screen has a clear + non-opaque background to accommodate this blur effect.)
Interestingly, when I set the frame of the UIVisualEffectView to view.frame (rather than view.bounds), the blur effect only covers about 2/3rds of the area that view.bound covers. Not sure why it's doing this.
Below is what I have in my code. As you can see, when the 'Done' button is pressed, the app generates the ActionViewController (the title screen) along with the blurred background which is called through a delegate method.
#IBAction func donePressed(_ sender: UIButton) {
let vc = ActionViewController()
self.definesPresentationContext = true
self.providesPresentationContextTransitionStyle = true
vc.modalPresentationStyle = .overFullScreen
vc.modalTransitionStyle = .coverVertical
self.present(vc, animated: true, completion: nil)
self.overlayBlurredBackgroundView()
vc.delegate = self
}
extension PreviewViewController: ActionViewControllerDelegate {
func overlayBlurredBackgroundView() {
let blurredBackgroundView = UIVisualEffectView()
blurredBackgroundView.frame = view.bounds
blurredBackgroundView.effect = UIBlurEffect(style: .systemThinMaterialDark)
view.addSubview(blurredBackgroundView)
}
First off, what Muhammad suggested should work. The reason your code crashes could be you are attempting to add the constraints first before adding the blurView to your view as a subview. The key phrase is:
they have no common ancestor.
Don't do that. Always add your subview before constraining it.
Lastly, one easy way to achieve what you want to achieve is to just toggle your navigationBar's visibility whenever you present your transparent screen (the one with the keyboard) and then put the navigationBar back to visible when you're done. Like so:
func overlayBlurredBackgroundView() {
self.navigationController?.navigationBar.isHidden = true
let blurredBackgroundView = UIVisualEffectView()
//blurredBackgroundView.frame = view.bounds
blurredBackgroundView.effect = UIBlurEffect(style: .systemThinMaterialDark)
view.addSubview(blurredBackgroundView)
blurredBackgroundView.translatesAutoresizingMaskIntoConstraints = false
blurredBackgroundView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0.0).isActive = true
blurredBackgroundView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0.0).isActive = true
blurredBackgroundView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0.0).isActive = true
blurredBackgroundView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0.0).isActive = true
}
and then putting it back when you're removing it:
func removeBlurredBackgroundView() {
self.navigationController?.navigationBar.isHidden = false
for subview in view.subviews {
if subview.isKind(of: UIVisualEffectView.self) {
subview.removeFromSuperview()
}
}
}
You need to put the blur overlay view in the presented view controller instead of presenting view controller i.e. ActionViewController. As far as frame is concern, just add right constraint and it will be layout automatically (no need to set frame) for example if you want your blur view to cover the entire screen you can add these constraints.
In the viewDidLoad function of ActionViewController call this function
func addOverlayBlurredBackgroundView() {
let blurView = UIVisualEffectView()
blurView.effect = UIBlurEffect(style: .systemThinMaterialDark)
self.view.insertSubview(blurView, at: 0)
blurView.translatesAutoresizingMaskIntoConstraints = false
blurView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0.0).isActive = true
blurView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0.0).isActive = true
blurView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0.0).isActive = true
blurView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0.0).isActive = true
}

Customize UINavigationBar with inset image

I have this navigation bar I am trying to implement that looks like this:
I know I can either put the image directly in the nav bar or as a header image below it, but I have no idea how to inset it so that it is contained in both the main container view and breaching the navigation bar as well.
Any ideas would be helpful!
I guess it's achievable using two images:
background: will match the navigation bar frame
icon: let's say an image 50x50 centered to the background in x-axis and y-axis with offset of its height / 2.0
Then you may try to use autolayout constraints doing so:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
guard let navbar = self.navigationController?.navigationBar else {return} // be sure to have defined a navigation controller
navbar.clipsToBounds = false // so the icon will be visible outside the nav bar
let niceBkg = UIImageView(image: UIImage(named: "bkg"))
navbar.addSubview(niceBkg)
niceBkg.translatesAutoresizingMaskIntoConstraints = false
niceBkg.leftAnchor.constraint(equalTo: navbar.leftAnchor).isActive = true
niceBkg.rightAnchor.constraint(equalTo: navbar.rightAnchor).isActive = true
niceBkg.topAnchor.constraint(equalTo: self.navigationController!.view.topAnchor).isActive = true
niceBkg.bottomAnchor.constraint(equalTo: navbar.bottomAnchor).isActive = true
let niceIcon = UIImageView(image: UIImage(named: "icon"))
niceBkg.addSubview(niceIcon)
niceIcon.translatesAutoresizingMaskIntoConstraints = false
niceIcon.widthAnchor.constraint(equalToConstant: 50).isActive = true
niceIcon.heightAnchor.constraint(equalToConstant: 50).isActive = true
niceIcon.centerXAnchor.constraint(lessThanOrEqualTo: niceBkg.centerXAnchor).isActive = true
niceIcon.bottomAnchor.constraint(greaterThanOrEqualTo: niceBkg.bottomAnchor, constant: 25).isActive = true
}
}
on iPhoneX the result is:
About your scenario, you probably need only the icon and a navigationBar with a proper background color. However I added both autolayout configurations because might be useful for someone else, especially if the navigationBar's background is quite complex with border, decorations and so on.

UIScrollView not scrolling at all when added programmatically in Swift?

So, I have looked through almost all of Stackoverflow's answers to this particular question and even looked through tutorials that supposedly teach you how to use a scroll view but It doesn't seem to apply for my project..
Here is what I know so far, in order for a Scroll View to properly work you first need to give it a content size. This determines the scrollable height etc.
I have provided some code to give you all a better idea of how I am adding said items into my scrollview. If there is something that I am doing wrong or if there is a better way to go about doing this please let me know, I am still fairly new to Swift and iOS development and in my mind it feels like I am doing it correctly.
The steps I am taking
Create items that I want to display (Input fields, Imageviews etc..)
Add said items to the view of the viewcontroller. (view.addsubview(etc..))
Create a scrollView and set its constraints to be same as the screen / view
Add our view with all the items in it into said scroll view
Relax and everything should work out perfect?????
Here is my code, I know it might be lengthy but I think it might be needed so that the scope of my question is understood
class JobRegistrationController: UIViewController {
// ... Omitted for clarity
lazy var scrollView: UIScrollView = {
let view = UIScrollView(frame: UIScreen.main.bounds)
view.backgroundColor = .red
view.contentSize = CGSize(width: self.view.bounds.width, height: self.view.bounds.height * 2)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
//... Omitted for clarity
let scrollContentView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// Need so that view controller is not behind nav controller
self.edgesForExtendedLayout = []
view.addSubview(scrollView)
scrollView.addSubview(scrollContentView)
scrollContentView.addSubview(jobTypeField)
scrollContentView.addSubview(jobTypeDividerLine)
// x, y, width and height constraints
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
// x, y, width and height constraints
scrollContentView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
scrollContentView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollContentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollContentView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
// x, y, width and height constraints
jobTypeField.leftAnchor.constraint(equalTo: scrollContentView.leftAnchor, constant: 20).isActive = true
jobTypeField.topAnchor.constraint(equalTo: scrollContentView.topAnchor).isActive = true
jobTypeField.rightAnchor.constraint(equalTo: scrollContentView.rightAnchor, constant: -8).isActive = true
jobTypeField.heightAnchor.constraint(equalToConstant: 30).isActive = true
// x, y, width and height constraints
jobTypeDividerLine.leftAnchor.constraint(equalTo: scrollContentView.leftAnchor, constant: 20).isActive = true
jobTypeDividerLine.topAnchor.constraint(equalTo: jobTypeField.bottomAnchor).isActive = true
jobTypeDividerLine.rightAnchor.constraint(equalTo: scrollContentView.rightAnchor).isActive = true
jobTypeDividerLine.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
Use this method in your class
override func viewDidLayoutSubviews()
{
scrollView.delegate = self
scrollView.contentSize = CGSize(width:self.view.frame.size.width, height: 1000) // set height according you
}
view.contentSize = CGSize(width: self.view.bounds.width, height: self.view.bounds.height * 2)
You should try to log the contentSize in your console after trying to access it. I am not sure if you are setting the correct contentSize here if the self.view.bounds has been calculated correctly when this gets called at that moment. Since it takes time for self.view frame and bounds to be calculated.
Try setting your contentSize after you have added the actual content to it based on the actual total content size.
EDIT:
Add a single UIView inside the scrollView, with the constraints set to top-bottom-leading-trailing, and add your subviews to it. Also, set the same constraints on the scrollView to the superView top-bottom-leading-trailing.
I believe the line of code below is the problem
scrollContentView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
You are setting your content view to the top of the view, when you should be setting it to the top of the scrollview.
I've just overcome a similar issue were I was setting the topAnchor of my first view to the safeAreaLayoutGuide.topAnchorof the scrollView. Everything laid out correctly but the constraint wouldn't show and therefore the entire content of the scrollView didn't move.
The problem is that you don't tell where the bottom of your content is. In other words you need some bottom constraints.
If you use...
scrollContentView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
...you need also to add a constraint to bind at least one view to the bottom of your UIScrollView like:
scrollContentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
... and also bind the last view in the scrollContentView to its bottomAnchor.
jobTypeDividerLine.bottomAnchor.constraint(equalTo: scrollContentView.bottomAnchor).isActive = true
This will sure fix your issue. Because this way the whole constraint sequence is linked from top to bottom.
Bottom line, the UIScrollView is not that smart that it determines its own bottom in every possible way. It is a kind of lazy. If you don't tell him enough it wouldn't simply scroll, while it is clear that your content disappears behind the bottom of your UIScrollView container.

Resources