Move the button using the Constraint Swift Programmatically - swift

#objc func buttonRoundPlayer(){
view?.addSubview(buttonRound)
buttonRound.setTitle("Jump", for: .normal)
buttonRound.addTarget(self, action: #selector(roundhandle), for: .touchUpInside)
buttonRound.backgroundColor = .red
buttonRound.layer.cornerRadius = 5
buttonRound.layer.borderWidth = 1
buttonRound.layer.borderColor = UIColor.white.cgColor
buttonRound.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([buttonRound.bottomAnchor.constraint(equalTo: view!.bottomAnchor),buttonRound.bottomAnchor.constraint(equalTo: view!.bottomAnchor),buttonRound.widthAnchor.constraint(equalToConstant: 100),buttonRound.heightAnchor.constraint(equalToConstant:50)])
}
I recently managed to get help in understanding the layout for the button and make it work but I don't know how to adjust the constraint to move the button away from the edge of the bottom side of the screen.
Thank you in advance for helping.

Not sure what do you mean by edge of bottom side, if you are talking about safe area layout guide, then you can use
NSLayoutConstraint.activate([buttonRound.bottomAnchor.constraint(equalTo:view!.safeAreaLayoutGuide.bottomAnchor),
buttonRound.widthAnchor.constraint(equalToConstant: 100),
buttonRound.heightAnchor.constraint(equalToConstant:50)])
Couple of issues in your code,
You have applied same constraint twice, which makes no logical sense to me
buttonRound.bottomAnchor.constraint(equalTo: view!.bottomAnchor),
buttonRound.bottomAnchor.constraint(equalTo: view!.bottomAnchor)
You force-unwrap view using view! am not really sure if its the ViewController's view or not, if it is ViewController's view, you need not force unwrap it as its a implicit optional in nature, so you should be able to write view.safeAreaLayoutGuide instead.
Through out the code you access view as if its optional, with statements like view?.addSubview(buttonRound), view!.bottomAnchor because am not really sure which view it is and if you are so sure its optional I would suggest using safe unwrap with if let, guard let instead of !
if let view = view {
view.addSubview(buttonRound)
buttonRound.setTitle("Jump", for: .normal)
buttonRound.addTarget(self, action: #selector(roundhandle), for: .touchUpInside)
buttonRound.backgroundColor = .red
buttonRound.layer.cornerRadius = 5
buttonRound.layer.borderWidth = 1
buttonRound.layer.borderColor = UIColor.white.cgColor
buttonRound.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([buttonRound.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor),
buttonRound.widthAnchor.constraint(equalToConstant: 100),
buttonRound.heightAnchor.constraint(equalToConstant:50)])
}
EDIT: As commented by OP below, he is seeing the error
"SafeAreLayoutGude" is only available in iOS 11.0 or newer
OP must be using a deployment target less than iOS 11 and because OP hasn't responded to my question in comment I am updating the answer to support below iOS 11.0
if let view = view {
view.addSubview(buttonRound)
buttonRound.setTitle("Jump", for: .normal)
buttonRound.addTarget(self, action: #selector(roundhandle), for: .touchUpInside)
buttonRound.backgroundColor = .red
buttonRound.layer.cornerRadius = 5
buttonRound.layer.borderWidth = 1
buttonRound.layer.borderColor = UIColor.white.cgColor
buttonRound.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([buttonRound.widthAnchor.constraint(equalToConstant: 100),
buttonRound.heightAnchor.constraint(equalToConstant:50)])
if #available(iOS 11.0, *) {
buttonRound.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
else {
buttonRound.bottomAnchor.constraint(equalTo:view.bottomAnchor).isActive = true
}
}
Not really sure what kind of app your are building/maintaining, iOS 11 seems way old to me, check if you really even need to support such old iOS version or not, change your iOS deployment target value in your project setting to avoid multiple compatibly issues like this.

Related

How to make `attributedReadMoreText` in `ReadMoreTextView` library not selectable - swift

I am a new iOS programming. Now i am creating a sample app which display text using ReadMoreTextView library. My content may contain many lines but by using this library i can maximumNumberOfLines to display how many lines of content should be displayed. I implement those content in cell of UITableView and i have problem is that, when i use label.attributedReadMoreText = NSAttributedString(string: "...") then end of content will display ... and when i click on it and then whole content will be display so, my question is that: How to not letting user click on that ... because i want user to click on cell then i will show another view and display whole content there?
How can i achieve something like this? Thank in advance.
This is how i set UITextView
lazy var categoryShortDetailLabel: ReadMoreTextView = {
let label = ReadMoreTextView()
label.font = UIFont(name: "SFCompactText-Regular", size: 16)
label.textColor = .black
label.isEditable = false
label.isSelectable = false
label.maximumNumberOfLines = 3
label.shouldTrim = true
label.attributedReadMoreText = NSAttributedString(string: "...")
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
Looking at the code here, I found that, the ReadMoreTextView is meant to provide you the feature like, ReadMore and ReadLess for the larger texts in textView.
However your requirement is to stop that functionality. Now, if you take a look at the code here, you will get the idea, that the function shoreMoreText and it's a private function so, can't override it. and this function is expanding the texts and setting the numberOfLines to zero. so, what you can do is, comment the code within and return from function to stop doing the action. Also as the ReadMoreTextView is Licensed as MIT(Read licence here) so, it's okay to modify the code.
private func showMoreText() {
return
/*if let readLessText = readLessText, text.hasSuffix(readLessText) { return }
shouldTrim = false
textContainer.maximumNumberOfLines = 0
if let originalAttributedText = _originalAttributedText?.mutableCopy() as? NSMutableAttributedString {
attributedText = _originalAttributedText
let range = NSRange(location: 0, length: text.count)
if let attributedReadLessText = attributedReadLessText {
originalAttributedText.append(attributedReadLessText)
}
textStorage.replaceCharacters(in: range, with: originalAttributedText)
}
invalidateIntrinsicContentSize()
invokeOnSizeChangeIfNeeded()*/
}
Try and share your results.
Hope it helps!

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

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

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!

UISlider glitch shows two thumbs?

A UISlider in my app sometimes shows a second thumb after it is dragged. This is completely unintentional and unwanted. I've done some searching and can't find any other references to this phenomenon. Can anyone figure out why this is happening? Is this a bug?
Two thumb slider:
This code is executed when a "show options" button is pressed:
readAndApplySettings() //This sets GameSpeed from a file
var SpeedSlider = UISlider()
SpeedSlider.minimumValue = 1
SpeedSlider.maximumValue = 20
SpeedSlider.setValue(Float(21 - GameState.GameSpeed), animated: true)
SpeedSlider.continuous = true
SpeedSlider.addTarget(self, action: "SpeedSliderValueDidChange:", forControlEvents: .ValueChanged)
// Code setting frame and location omitted
OptionsLabelButton.addSubview(SpeedSlider)
This is the ValueDidChange code:
func SpeedSliderValueDidChange(sender:UISlider) {
GameState.GameSpeed = Int(21 - sender.value)
TimerInterval = Double(GameState.GameSpeed) * 0.0167
tempSpeedLabel.text = "Speed: \(21 - GameState.GameSpeed)"
}
Looks like you have created multiple UISliders, double check you are not calling your function twice. As well, if you are using storyboard to create the UISliders. Make sure you do not have two sliders on top of each other.

Programmatically place the Cursor inside a textField of a custom tableView header

How can you programmatically make sure that the cursor of a tableView-HeaderView-TextField gets active (i.e. is the first responder) ??
My table looks like this (i.e with the custom TextField header). So far, the cursor only gets inside the grey header field by clicking inside the textfield. But I would like to be able to get the cursor inside the textfield programmatically....
The code for my custom tableview-header looks like this :
// drawing a custom Header-View with a TextField on top of the tableView
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let container = UIView(frame: CGRectMake(0, 0, self.view.frame.size.width, 50))
let textField = UITextField(frame: CGRectMake(10, 15, self.view.frame.size.width/2 - 40, 45))
textField.delegate = self
self.txtfield = textField
textField.textColor = UIColor.blackColor()
let placeholder = NSAttributedString(string: "..add player", attributes: [NSForegroundColorAttributeName: UIColor.darkGrayColor()])
textField.attributedPlaceholder = placeholder
textField.backgroundColor = UIColor.lightGrayColor()
container.addSubview(textField)
var headPlusBttn:UIButton = UIButton.buttonWithType(UIButtonType.ContactAdd) as! UIButton
headPlusBttn.center.x = self.view.frame.size.width - 20
headPlusBttn.center.y = 38
headPlusBttn.enabled = true
headPlusBttn.addTarget(self, action: "addTeam:", forControlEvents: UIControlEvents.TouchUpInside)
container.addSubview(headPlusBttn)
return container
}
My first approach was to set the first-responder of the headerViewForSection like this (see code):
// reload entries
func reloadEntries() {
self.tableView.reloadData()
// the following does unfortunately not work !!!!!
self.tableView.headerViewForSection(1)?.becomeFirstResponder()
}
Not sure why this does not work. Maybe, the Section-Nr (Int=1) is wrong. But I tried several section-numbers. No curser where it should be.
Any help appreciated !
Usually adding a delay helps in situations like this. It allows the OS to do everything it wants with the view, and then it won't mess up what you're trying to do at the same time.
Maybe something like this:
func reloadEntries() {
self.tableView.reloadData()
let delay = (Int64(NSEC_PER_SEC) * 0.1)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, triggerTime), dispatch_get_main_queue(), { () -> Void in
self.tableView.headerViewForSection(1)?.becomeFirstResponder()
})
}
I haven't tested this to do what you want, so you may need to find a different place to put this.
Also, are you sure you want to affect the view in section 1? From your image it looks like you want to mess with the header in section 0.
Be sure to drop into the debugger and check that the header isn't nil. Your code implies that that's a valid condition. You might try writing it like this (at least for testing):
if let header = self.tableView.headerViewForSection(1) {
header.becomeFirstResponder()
}
else {
print("There is no header.")
}
Try
self.tableView.headerViewForSection(1)?.textfield.becomeFirstResponder()