how to change size and position of searchController?.searchBar? - swift

I try to change size and position of searchController.searchBar for exemple
i cahnge y from 0 to 100 but i can see any change in my programme .
here is my code :
placesClient = GMSPlacesClient.sharedClient()
resultsViewController = GMSAutocompleteResultsViewController()
resultsViewController?.delegate = self
searchController = UISearchController(searchResultsController: resultsViewController)
searchController?.searchResultsUpdater = resultsViewController
searchController?.searchBar.sizeThatFits(CGSize(width: 600, height: 44.0 ))
self.definesPresentationContext = true
searchController?.searchBar.frame = (CGRectMake(0, 100,600, 44.0))
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: (searchController?.searchBar)!)
// Keep the navigation bar visible.
searchController?.hidesNavigationBarDuringPresentation = false
searchController?.modalPresentationStyle = UIModalPresentationStyle.Popover
picture
can any body help me please ?

You are able to change the size of a search bar or text field as another example by using the Size Inspector within that item. Also, when you set constraints for the object you can set height or width to anything you wish...within limits of the screen. Therefore, a text field with a set height of 30 can now be set to 50 or whatever you desire to fit your aesthetic. I found this by once searching for myself and finally came across it in a Udemy course for iOS 9 with Mark Price. I would forward the link but it was a paid course. Good luck!

Related

How to use frame to set x position in loop on Swift

I have an array that count is between 1 to 3 varies.
I want to frame them in the middle of the screen with a certain distance
Also the width of the labels is fixed
let array = ["some1", "some2", "some3"]
func setLabel(){
var i = -1
for text in array{
i += 1
let label = UILabel()
label.fram = CGRect(x: screenWidth/2 - (CGFloat(i)*50) + 25, y: 100, width: 50 , height: 20)
label.text = text
addSubview(label)
}
}
You can use stackview as suggested by #matt. If you don't want to use stackview you can calculate the x position by array count and label index like this
let array = ["some1", "some2", "some3"]
func setLabel(){
var i:CGFloat = 0
for text in array{
i += 1
let label = UILabel()
label.backgroundColor = .red
label.frame = CGRect(x: (view.bounds.width/CGFloat(array.count+1))*i-25, y: 100, width: 50 , height: 20)
label.text = text
view.addSubview(label)
}
}
The really easy way to do this is to put the labels (one, two, or three of them) into a centered UIStackView. You would still need to know the desired fixed width of a label and apply a width constraint to each label, but everything else will just take care of itself.
Just as a demonstration, I used an arbitrary width of 100, with the text for all three labels being just "UILabel" as in your image. Here's what it looks like with one label:
Here's what it looks like with three labels:
Here's the code I used (sv is the stack view, which has already been configured in the storyboard; n is how many labels we want):
for _ in 1...n {
let lab = UILabel()
lab.text = "UILabel"
lab.textAlignment = .center
lab.translatesAutoresizingMaskIntoConstraints = false
lab.widthAnchor.constraint(equalToConstant: 100).isActive = true
sv.addArrangedSubview(lab)
}
So all you really need to do is get the right text from your array as we loop, and you're done. The point is that you don't need to think about frames at all! The UIStackView imposes the correct the frames for us.
NOTE Although I said above that the stack view was "configured in the storyboard", that has nothing to do with the answer. You can create and configure the stack view in code just as well, without changing anything about my answer. The point is that the stack view already knows how to receive an arbitrary number of views, space them out evenly, and center them as a whole. That is what it is for. So if, as your question implies, you can't manage the arithmetic to assign the views a frame yourself, why not let the stack view do it for you?

Add right constraint to two labels with variable width

I have two UILabels next to each other in the view where I will show comments to a post, one for the username and one for the timestamp. I convert the timestamp to an easy format like "1h" for one hour ago, "22m" for 22 minutes ago etc.
These are my two labels:
var usernameLabel: UILabel = {
let usernameLabel = UILabel()
usernameLabel.numberOfLines = 1
usernameLabel.lineBreakMode = .byTruncatingTail
usernameLabel.font = UIFont.boldSystemFont(ofSize: 15)
usernameLabel.textColor = UIColor.darkGray
usernameLabel.translatesAutoresizingMaskIntoConstraints = false
usernameLabel.text = "Username"
usernameLabel.isUserInteractionEnabled = true
usernameLabel.isExclusiveTouch = false
usernameLabel.backgroundColor = .green
return usernameLabel
}()
var commentDateLabel: UILabel = {
let commentDateLabel = UILabel()
commentDateLabel.font = UIFont.systemFont(ofSize: 12)
commentDateLabel.textColor = UIColor.lightGray
commentDateLabel.translatesAutoresizingMaskIntoConstraints = false
commentDateLabel.backgroundColor = .red
return commentDateLabel
}()
I add constraints to both of them to make sure they fit inside my view, like this:
commentDateLabel.leftAnchor.constraint(equalTo: usernameLabel.rightAnchor, constant: 8).isActive = true
commentDateLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -16).isActive = true
usernameLabel.leftAnchor.constraint(equalTo: profilePictureImageView.rightAnchor, constant: 16).isActive = true
The problem I'm facing is, the date is aligned on the far right and the username takes up the entire width. I would like it different - where the label of the username is just as wide as needed and the date taking up the entire space that's left.
In other words: I want the green label to shorten to just fit the text and the red label to take up the entire width that's left, so both of them are next to each other but when a username is too long it will truncate and still show the entire date label. How would I go about this?
You need to set
contentHuggingPriority
to usernameLabel to be higher than the other , also set
contentCompressionResistance
to commentDateLabel to be higher

How to shrink font size to fit in the stackview but remain the same fontsizes in the whole stackview?a

How can I shrink the font size to fit in a stackview of 3 items? It's important to note that the font-sizes should be the same across all views in the Stackview.
Please have a look at the issue below. The My Orders tab has a smaller font than the rest of the Stackview.
What would I like to achieve?
Spread all items evenly in the Stackview with the same fontsizes.
What did I already tried?
Setting the following properties on the labels.
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor=0.75
Setting the following properties on the Stackview.
stackView.axis = .horizontal
stackView.distribution = .equalSpacing
stackView.alignment = .center
stackView.spacing = 16.0
Thanks for any advise.
did you try using fillEqually instead? that should give you equal size for both items.
The way I solved this was to calculate what the percentage of the total width of the stack view each item should take based on the number of characters in the label and using that information to set a width constraint on the labels. Something like this:
let totalCount = labels(into: 0) { $0 += $1.text.count }
labels.forEach { label in
let widthRatio = CGFloat(label.text.count) / CGFloat(totalCount)
label.widthAnchor.constraint(equalTo: label.superview!.widthAnchor, multiplier: widthRatio).isActive = true
}

Programmatically update UITextView height

I am trying to update the height of a UITextView based on the content. I have seen this solution but cannot get it to work with my current code (still learning swift)
I define the UITextView as such:
let eventDetailInfoTextBox : UITextView = {
let textbox = UITextView()
textbox.backgroundColor = UIColor.clear
textbox.layer.borderWidth = 1
textbox.layer.borderColor = ColorPallet.AppTertiaryColor.cgColor
textbox.layer.cornerRadius = 10
textbox.setNeedsDisplay()
let contentSize = textbox.sizeThatFits(textbox.bounds.size)
textbox.isEditable = false
return textbox
}()
The subview is then added in setupViews() along with defining its position in the view using a call to setupEventDetailInfoTextBox()
fileprivate func setupEventDetailInfoTextbox() {
print("Event Detail Info Text Box Height: \(eventDetailInfoTextBox.contentSize.height)")
var frame = eventDetailInfoTextBox.frame
frame.size.height = eventDetailInfoTextBox.contentSize.height
eventDetailInfoTextBox.anchor(eventDetailMapView.bottomAnchor, left: self.leftAnchor, bottom: nil, right: self.rightAnchor, topConstant: 8, leftConstant: 10, bottomConstant: 0, rightConstant: 10, widthConstant: 0, heightConstant: frame.size.height)
}
The call to .anchor is based on the Lets Build That App frameworks found via this link and basically wraps up the local functions from Xcode. I know this works and have reused the same function repeatedly throughout my app.
The output from the print statement is -8 and is represented by a height suitable to show 1 line of text (sometimes).
Can anyone see why my text box refuses to get any bigger if I have more than 1 line of text?
I'm using IOS 10, Xcode 8 and writing in swift 3.
Follow these step
Create height constraint outlet of TextView.
Calculate content height of Textview.
Update TextView height constraint constant value.
Call layoutIfNeeded() function.
I hope it will work.
If you want something static, down and dirty, you can streamline the process (not set and reset properties) as long as you place everything in the right order. If you need to handle device rotations or other runtime changes, that would require something slightly less down and dirty, but not by much--I'm not sure which you need so I opted for the simpler.
// instance property so that other constraints can refer to it
let descriptionTextView = UITextView()
// configure text view
descriptionTextView.text = descriptionModel
descriptionTextView.font = // UIFont
descriptionTextView.textColor = // UIColor
descriptionTextView.isEditable = false
descriptionTextView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(descriptionTextView)
// set constraints
descriptionTextView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16).isActive = true
descriptionTextView.topAnchor.constraint(equalTo: divider.bottomAnchor, constant: 32).isActive = true
descriptionTextView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -32).isActive = true
descriptionTextView.sizeToFit()
descriptionTextView.layoutIfNeeded()
descriptionTextView.heightAnchor.constraint(equalToConstant: descriptionTextView.contentSize.height).isActive = true

Programmatically adding constraints breaks auto layout constraints

Edit 1
Hello, This is my first time using code to add constraints. I normally just use interface builder. I am trying to add a vertical UISlider, before I thought that mixing visually added constraints was interfering with coded constraints. I have now updated my code and therefore this question to create constrains using ONLY code in this particular view container.
What I have done is I created a view directly underneath another view. I created 3 small views inside that that match the width of the textfields in the view above and then spaced them out the same as how the textfields are spaced out.
For testing purposes only I gave these 3 small views a color to see if it worked, and it does.
When I actually finish the app those red, green, and blue views will be clear. The only reason I wanted them was so when I create the sliders I can constrain each one of them to the center of the view...which is how the labels above the textfields are constrained.
Here is the code for this
which works
// Mark: Hidden View
let leftHiddenView = UIView()
let centerHiddenView = UIView()
let rightHiddenView = UIView()
let hiddenViews = [leftHiddenView, centerHiddenView, rightHiddenView]
for views in hiddenViews {
views.translatesAutoresizingMaskIntoConstraints = false
sliderContainer.addSubview(views)
views.backgroundColor = .white
let widthConstraint = views.widthAnchor.constraint(equalToConstant: 35)
let heightConstraint = views.heightAnchor.constraint(equalToConstant: 5)
NSLayoutConstraint.activate([widthConstraint, heightConstraint])
}
let centerViewHorizontalConstraint = centerHiddenView.centerXAnchor.constraint(equalTo: sliderContainer.centerXAnchor)
let centerViewTopConstraint = centerHiddenView.topAnchor.constraint(equalTo: sliderContainer.topAnchor, constant: 50)
NSLayoutConstraint.activate([centerViewHorizontalConstraint, centerViewTopConstraint])
let leftViewVerticalCenterConstraint = leftHiddenView.centerYAnchor.constraint(equalTo: centerHiddenView.centerYAnchor, constant: 0)
let leftViewTrailingConstraint = leftHiddenView.trailingAnchor.constraint(equalTo: centerHiddenView.leadingAnchor, constant: -60)
NSLayoutConstraint.activate([leftViewVerticalCenterConstraint, leftViewTrailingConstraint])
let rightViewVerticalCenterConstraint = rightHiddenView.centerYAnchor.constraint(equalTo: centerHiddenView.centerYAnchor, constant: 0)
let rightViewTrailingConstraint = rightHiddenView.leadingAnchor.constraint(equalTo: centerHiddenView.trailingAnchor, constant: 60)
NSLayoutConstraint.activate([rightViewVerticalCenterConstraint, rightViewTrailingConstraint])
Now, I started to add a UISlider as vertical. And the exact same thing that happened before happened now.
As you can see everything breaks.
Here is the code thus far on that
// Mark: Slider View
let leftSlider = UISlider()
let centerSlider = UISlider()
let rightSlider = UISlider()
let colorSliders = [leftSlider, centerSlider, rightSlider]
for slider in colorSliders {
slider.translatesAutoresizingMaskIntoConstraints = false
sliderContainer.addSubview(slider)
let w = sliderContainer.bounds.width
slider.bounds.size.width = w
slider.center = CGPoint(x: w/2, y: w/2)
slider.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI_2))
slider.value = 0
slider.minimumValue = 0
slider.maximumValue = 255
let sliderTopConstraint = slider.topAnchor.constraint(equalTo: centerHiddenView.bottomAnchor, constant: 5)
let sliderBottomConstraint = slider.bottomAnchor.constraint(equalTo: sliderContainer.bottomAnchor, constant: 5)
NSLayoutConstraint.activate([sliderTopConstraint, sliderBottomConstraint])
slider.backgroundColor = .purple
}
let centerSliderHorizontalConstraints = centerSlider.centerXAnchor.constraint(equalTo: sliderContainer.centerXAnchor)
NSLayoutConstraint.activate([centerSliderHorizontalConstraints])
Don't ever misc the Design time constraints with adding Runtime constraints. Either add all constraints at design time or all constraints at runtime only. Else you will be in MESS. Make this as a good practice.
In case you need to change the frame, just change the constant property of the constraints and add all the required constraint at design time.
There will be very rare times when you need to add runtime constraints. (I am saying this because I always design in that way only. And that helps me a lot.) Design your screen in such a ways that even if you need to add 2 controls for dynamic UI changes, then keep 2 controls and do show hide with that controls. In can you need some kind of Animation with your controls, you don't need to change design time constraints.
I know this does not answer your question directly, but hope you will get the understanding of how to use constraints.
From your screenshot, I am not able understand exactly what is your UI looks like. Can you give little bit more idea of how your UI looks like? so that I can suggest some idea of how to give constraints...
Well, it turns out that the problem was actually quite easy to solve from the beginning. I only overlooked it because of being intimidated by the vertical UISlider. Since I did not give the above container a fixed height when I added the container below it and ran the app, the containers equally filled the space and the contents inside messed up accordingly. I simply gave the top container with just the labels and textfield a fixed height of 61 and its now much closer to being done. Sorry