I am trying to set the time for UIDatePicker from the text of UITextField. But it always gets reset to current time. Text on UITextField is 14:01 and this is how I am trying to set time on UIDatePicker :
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm"
let time = formatter.date(from: textField.text!)
datePickerTime.date = time!
This is is the initialisation of datePickerTime :
datePickerTime = UIDatePicker(frame: CGRect(x: CGFloat(0), y: CGFloat(210), width: CGFloat(320), height: CGFloat(216)))
datePickerTime.datePickerMode = .time
datePickerTime.minimumDate = Date()
I have tried similar case with setting date(not time) and it works fine.
Related
After added below code its display list of UILabel below FSCalendar dates.
But the label overlap dates inside calendar.
How to align weekly / Monthly FSCalendar Label below dates?
func calendar(_ calendar: FSCalendar, willDisplay cell: FSCalendarCell, for date: Date, at monthPosition: FSCalendarMonthPosition) {
let labelMy2 = UILabel(frame: CGRect(x: 10, y: calendar.rowHeight, width: cell.bounds.width - 20, height: 20))
labelMy2.font = UIFont.init(font: Font.interRegular, size: 10)
labelMy2.text = " 00.00 "
labelMy2.textAlignment = .center
labelMy2.backgroundColor = UIColor.init(named: ColorPalette.gray100Color)
labelMy2.textColor = UIColor.init(named: ColorPalette.gray600kColor)
cell.addSubview(labelMy2)
}
Below Added Image
There seems to be some wasted space towards the right of the date picker component:
And it doesn't matter if I increase or decrease the value of width/height of its frame; it stays the standard size.
let datePicker = UIDatePicker(frame: CGRect(x: 20, y: 100, width: 500, height: 200))
datePicker.datePickerMode = .date
view.addSubview(datePicker)
My question is, can it be adjusted?
edit: So I managed to find its short form but thats only addable through the storyboard.
Heres the view:
The top first picker is added programmatically and the second via storyboard. For some reason, I'm unable to make the programmatically created picker smaller...
You can just ask the date picker which size is sufficient ;)
Option A
let datePicker = UIDatePicker()
datePicker.datePickerMode = .date
// Let it size itself to its preferred size
datePicker.sizeToFit()
// Set the frame without changing the size
datePicker.frame = .init(x: 20, y: 100, width: datePicker.bounds.size.width, height: datePicker.bounds.size.height)
view.addSubview(datePicker)
Option B
let datePicker = UIDatePicker()
datePicker.datePickerMode = .date
// Ask the picker for its preferred size
let datePickerPreferredSize = datePicker.systemLayoutSizeFitting(view.bounds.size)
// Set the frame using that size
datePicker.frame = .init(x: 20, y: 100, width: datePickerPreferredSize.width, height: datePickerPreferredSize.height)
view.addSubview(datePicker)
I have recently begun work on an app using Swift in Xcode and am trying to create a text bubble. To do this, I need to get the width of the longest row of text in a multi-row UILabel. For example, if I have this text (I automatically set line breaks after a certain length):
Hello there, this is
an example piece of text
I would like to return the width of the text in the second row. I have already tried using sizeToFit() which would drastically simplify my work, but because of my other code, this is not an option as it causes other problems (my code is below). Is there a purely programmatic way to get this value without using sizeToFit()? Any help would be much appreciated. My code:
bubbleContents.text = textMessage
bubbleContents.numberOfLines = 0
bubbleContents.lineBreakMode = .byWordWrapping
bubbleContents.bounds.size.width = 2000
var widthText = bubbleContents.intrinsicContentSize.width
bubbleContents.bounds.size.width = 266
print(textMessage)
print(widthText)
if widthText > 266 {
let numRows = Int(widthText/266)
print(numRows)
//bubbleContents.frame.origin.y += CGFloat((Double(numRows)*10.25))
var currentHeight = 44.0
currentHeight += Double((Double(numRows)*20.5))
bubbleContents.bounds.size.height = CGFloat(currentHeight)
heightOfCell = Double(currentHeight)
let originalTransform = self.bubbleContents.transform
let scaledTransform = originalTransform
let scaledAndTranslatedTransform = scaledTransform.translatedBy(x: 0, y: CGFloat(Double(numRows)*20.5))
//self.bubbleContents.transform = scaledAndTranslatedTransform
}
else {
heightOfCell = 44.0
}
bubble.frame = CGRect(x: 0, y: 0, width: Double(widthText + 30), height: heightOfCell - 4)
bubbleContents.center.y = bubble.center.y
Here is an image of what my current text bubbles look like:
You can use NSAttributedString,boundingRect(with:options:context:) method, begin by creating NSAttributedString with attributes such as font of your UILabel
let attributes: [NSAttributedString.Key : Any] = [.font: bubbleContents.font]
let atStr = NSAttributedString(string: textMessage, attributes: attributes)
Now use atStr.boundingRect(with:options:context:) method, like so:
let bounds = CGSize(width: 266.0, height: .greatestFiniteMagnitude)
let bubbleSize = atStr.boundingRect(with: bounds, options: [.usesLineFragmentOrigin, .usesFontLeading, .usesDeviceMetrics], context: nil).size
Usage:
bubble.frame.size.width = bubbleSize.width
bubble.frame.size.height = max(bubbleSize.height, 44.0)
I'm having a problem with looping an object in Swift.
I want to declare the UITextfield as an instance variable so I can access it anywhere inside the class.
So if I put it inside the loop it works fine, but I put the variable of UITextField outside the loop, it doesn't show the first textfield in the view and the username textfield would be missing.
Here's my code
var placeHolderArr:[String] = ["Username", "Password"]
let loginField = UITextField() // <----- this one
override func viewDidLoad() {
super.viewDidLoad()
let logoHolder = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height / 2))
logoHolder.backgroundColor = self.utils.hexStringToUIColor(hex: "#ff8f00")
for index in 0...1 {
let height = index * 60
// When I declare the textfield variable in this line, it works fine.
loginField.frame = CGRect(x: 0 , y: Int((logoHolder.frame.maxY + 30) + CGFloat(height)), width: Int(self.view.frame.width - 80), height: 50)
loginField.placeholder = placeHolderArr [index]
loginField.font = UIFont.systemFont(ofSize: 15)
loginField.borderStyle = UITextBorderStyle.roundedRect
loginField.autocorrectionType = UITextAutocorrectionType.no
loginField.keyboardType = UIKeyboardType.default
loginField.returnKeyType = UIReturnKeyType.done
loginField.clearButtonMode = UITextFieldViewMode.whileEditing;
loginField.contentVerticalAlignment = UIControlContentVerticalAlignment.center
loginField.center.x = self.view.center.x
loginField.delegate = self
loginField.tag = index
innerY = Int(loginField.frame.maxY)
print("index\(index)" )
self.view.addSubview(loginField)
}
}
Please see the screenshot below
Textfield when declared inside the loop:
Textfield when declared outside the loop:
Obviously you use the same UITextField. Judt put initialization inside the loop
for index in 0...1 {
let height = index * 60
// When I declare the textfield variable in this line, it works fine.
loginField = UITextField()
loginField.frame = CGRect(x: 0 , y: Int((logoHolder.frame.maxY + 30) + CGFloat(height)), width: Int(self.view.frame.width - 80), height: 50)
loginField
And to use it later use array:
var fieldArr:[UITextField] = []
Then later:
fieldArr.append(loginField)
Summarise:
var placeHolderArr:[String] = ["Username", "Password"]
let loginFields:[UITextField] = []
override func viewDidLoad() {
super.viewDidLoad()
let logoHolder = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height / 2))
logoHolder.backgroundColor = self.utils.hexStringToUIColor(hex: "#ff8f00")
for index in 0...1 {
let loginField = UITextField()
let height = index * 60
// When I declare the textfield variable in this line, it works fine.
loginField.frame = CGRect(x: 0 , y: Int((logoHolder.frame.maxY + 30) + CGFloat(height)), width: Int(self.view.frame.width - 80), height: 50)
loginField.placeholder = placeHolderArr [index]
loginField.font = UIFont.systemFont(ofSize: 15)
loginField.borderStyle = UITextBorderStyle.roundedRect
loginField.autocorrectionType = UITextAutocorrectionType.no
loginField.keyboardType = UIKeyboardType.default
loginField.returnKeyType = UIReturnKeyType.done
loginField.clearButtonMode = UITextFieldViewMode.whileEditing;
loginField.contentVerticalAlignment = UIControlContentVerticalAlignment.center
loginField.center.x = self.view.center.x
loginField.delegate = self
loginField.tag = index
innerY = Int(loginField.frame.maxY)
print("index\(index)" )
self.view.addSubview(loginField)
loginFields.append(loginField)
}
}
When you declare the UITextfield subclass outside your loop, than every time when you set it up, you set up the same UITextfield instance. This means, you are overriding the first set of properties with the next one, every time you iterate on it.
Instead, lets create two instances, and set up both independently:
// declare this outside your loop
let usernameField = UITextField()
let passwordField = UITextField()
for (index, loginField) in [usernameField, passwordField].enumerated() {
// do your setup
}
You can create two properties:
let usernameField = UITextField()
let passwordField = UITextField()
and loop every text field like:
for (index, loginField) in [usernameField, passwordField].enumerated() {
//do what you need
}
I have created a UITextField programatically. Now when I try to get its beginningOfDocument property, it is becoming nil.
Code is as follows:
public func addTextField(title:String?=nil) -> UITextField {
kWindowHeight -= 80.0
let txt: UITextField = UITextField(frame: CGRect(x: 13, y: 67, width: 213.00, height: 35));
txt.addTarget(self, action: "textFieldDidChange", forControlEvents: UIControlEvents.EditingChanged)
txt.borderStyle = UITextBorderStyle.RoundedRect
txt.layer.cornerRadius = 3
txt.layer.borderColor = UIColorFromRGB(0x1E8ADB).CGColor
txt.font = UIFont(name: kDefaultFont, size: 14)
txt.autocapitalizationType = UITextAutocapitalizationType.Words
txt.clearButtonMode = UITextFieldViewMode.WhileEditing
txt.layer.masksToBounds = true
txt.layer.borderWidth = 1.0
if title != nil {
txt.placeholder = title!
}
contentView.addSubview(txt)
return txt
}
In some other class I am calling:
let textField = AlertView().addTextField("Send SMS")
var begining = textField.beginingOfDocument
If you merely create an UITextField then immediately try to access beginningOfDocument property OR even after trying to add it to a superview, you will always get an uninitialized value.
Try to retrieve that property after the UITextField becomes the first responder and see the result :-)
Good luck.