Create UILabel dynamically and Change the text Also - ios

I am trying to create 7 UILabel programmatically and I am not able to change the text of all UILabel.
let viewsCount = 2
let viewLblcount = 7
var messageForLbl = ["helo", "bhago", "futo", "bhensali" , "bhaaw bhaaw", "haha" ,"alladh"]
let floatValue = CGFloat(viewsCount)
let floatLbl = CGFloat(viewLblcount)
let scrollView: UIScrollView = UIScrollView(frame: CGRectMake(20, 30, 320, 250 * floatValue))
for i in 0 ..< viewsCount {
let views: UIView = UIView(frame: CGRectMake(0, 320 * CGFloat(i) + floatValue, self.view.frame.size.width - 40, 300))
views.backgroundColor = UIColor.grayColor()
views.tag = i + 1
for j in 0 ..< viewLblcount {
let label = UILabel(frame: CGRectMake(20, 40 * CGFloat(j) + floatLbl, self.view.frame.size.width - 100, 20))
let label2 = UILabel(frame: CGRectMake(10, 90 * CGFloat(j) + floatLbl, self.view.frame.size.width - 100, 30))
label.backgroundColor = UIColor.cyanColor()
label.text = "iOS LABEL TRY"
label2.backgroundColor = UIColor.magentaColor()
label2.text = "iOS LABEL TRY2"
label.tag = j + 1
label2.tag = j + 1
views.addSubview(label)
views.addSubview(label2)
scrollView.addSubview(views)
self.view!.addSubview(scrollView)
scrollView.contentSize = CGSizeMake(310, 390 * floatValue)
}
All the label is showing same text.

You have the text of the labels hardcoded on these lines:
label.text = "iOS LABEL TRY"
label2.text = "iOS LABEL TRY2"
I'm not exactly sure what text you want in each label, but I think you want to change it to:
label.text = messageForLbl[j]
Also, you can avoid a future bug by using Swift's enumerators (then you don't have to change viewLblcount when you change messageForLbl):
for value in messageForLbl.enumerate() {
label.text = value
}

Because you have hard coded the text
label.text = "iOS LABEL TRY"

Related

How to set width of UIImageView based on UILabel row width

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)

How to set custom title view to center of navigation bar

I am trying to add custom view (Label) as title view of navigation item.
but it is not appearing in centre
func setupNavigationMultilineTitle(title:String) {
let autoscrollLabel = EFAutoScrollLabel()
autoscrollLabel.text = title
autoscrollLabel.textAlignment = .center
autoscrollLabel.backgroundColor = .red
autoscrollLabel.font = AppTheme.Fonts.font(type: .Medium, size: 15)
autoscrollLabel.textColor = AppTheme.Colors.ColorsOfApp.header_color.color
autoscrollLabel.frame = CGRect(x: 0, y: 0, width:((self.navigationController?.navigationBar.frame.size.width ?? 0) - (self.navigationItem.leftBarButtonItem?.customView?.frame.width ?? 0) * 2) , height: 40)
self.navigationItem.titleView = autoscrollLabel
}
I have tried to use deduct width of custom view to show it in center but unfortunately it is not working.
I have also tried to get self.navigationItem.leftBarButtonItem.width but it returns 0. I confirmed that there is leftBarbutton item with po self.navigationItem.leftBarButtonItem
EDIT
This solves issue
autoscrollLabel.frame = CGRect(x: self.view.center.x - 125, y: 0, width: 250 , height: 40)
But I need dynamic solution
Any help would be appreciated
I debugged your scenario, hope it helps you and other developers,
When we assign tittleView width by calculating the space left after subtracting space of items, margins, padding etc then iOS calculate titleView X from the right side i.e. titleview.x = rightItem.x - width and we are expecting it like titleview.x = navbar.width/2 - width/2.
Please look below sample test cases.
Calculate width
let maxItemOnEitherSide = max(arrLeftItems.count, arrRightItems.count)
let widthOfItem : CGFloat = 30.0
let pading : CGFloat = 40
let aWidth : CGFloat = (self.navigationController?.navigationBar.frame.width)! - CGFloat(maxItemOnEitherSide) * widthOfItem * 2.0 - pading
let lblNavTitle = UILabel(frame: CGRect(x: 0, y: 0,
width: aWidth,
height: 40))
Case 1 : arrLeftItems.count = 1 and arrRightItems.count = 0.
Output :
Case 2 : arrLeftItems.count = 0 and arrRightItems.count = 1.
Hope above cases clear you out what we are expecting and what we are getting and the calculation that I wrote in first para i.e. titleview.x = rightItem.x - width.
Conclusion :
If rightBarItems have more items than leftBarItems then titleview will be in center, so you wont need to do anything but if leftBarItems have more items than rightBarItems then add blank items in right side to make it balance. It is weird for developers but seems like its the only solution.
Check the final output.
View Heirarchy
Output
If your navigation Item is part of a UINavigationController you could try
self.navigationController?.navigationBar.topItem?.leftBarButtonItem?.width ?? 0.0
Add my version code based on #dahiya_boy answers.
In my case, I have a custom button that has a more 30-width size. So, rather than multiply it by 30, I find a max from left and right items to find the max.
Below is the code:
func setCenterTitle(_ title: String) {
let navWidth = (navigationController?.navigationBar.frame.width).orZero
let leftItemsWidth = leftBarButtonItems.orEmptyArray.reduce(0) {
$0 + ($1.customView?.frame.width).orZero
}
let rightItemsWidth = rightBarButtonItems.orEmptyArray.reduce(0) {
$0 + ($1.customView?.frame.width).orZero
}
let maxItemsWidth = max(leftItemsWidth, rightItemsWidth)
let padding: CGFloat = 40
let labelWidth = navWidth - (maxItemsWidth * 2) - padding
let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: labelWidth, height: 40))
titleLabel.text = title
titleLabel.textAlignment = .center
titleLabel.font = UIFont.boldSystemFont(ofSize: 16)
self.titleView = titleLabel
}

Strange shape for colored background in chat app

I am trying to make some small chat app, with a grey background around the message:
The problem is that the grey background is a strange shape (like what I drew in red) rather than a simple rounded rectangle:
messageLbl.frame = CGRect(x: 0, y: 0, width: self.resultsScrollView.frame.size.width-94, height: CGFloat.greatestFiniteMagnitude+32)
messageLbl.backgroundColor = UIColor.groupTableViewBackground
messageLbl.lineBreakMode = NSLineBreakMode.byWordWrapping
messageLbl.textAlignment = NSTextAlignment.left
messageLbl.numberOfLines = 0
messageLbl.font = UIFont(name: "Helvetica Neuse", size: 17)
messageLbl.textColor = UIColor.black
messageLbl.text = self.messageArray[i]
messageLbl.sizeToFit()
messageLbl.layer.zPosition = 20
//messageLbl.frame.origin.x = (self.resultsScrollView.frame.size.width - self.messageX) - messageLbl.frame.size.width //--> value of 449.5 too much right
messageLbl.frame.origin.y = self.messageY
//messageLbl.frame.origin.y = 20
messageLbl.frame.origin.x = 40
self.resultsScrollView.addSubview(messageLbl)
self.messageY += messageLbl.frame.size.height + 30
let frameLbl:UILabel = UILabel()
frameLbl.frame.size = CGSize(width: messageLbl.frame.size.width, height: messageLbl.frame.size.height + 10)
//frameLbl.frame.origin.x = (self.resultsScrollView.frame.size.width - self.frameX) - frameLbl.frame.size.width
frameLbl.frame.origin.x = 20
frameLbl.frame.origin.y = self.frameY
frameLbl.backgroundColor = UIColor.groupTableViewBackground
frameLbl.layer.masksToBounds = true
frameLbl.layer.cornerRadius = 10
self.resultsScrollView.addSubview(frameLbl)
self.frameY += frameLbl.frame.size.height + 20
let img: UIImageView = UIImageView()
img.image = self.myImg
img.frame.size = CGSize(width: 34,height: 34)
//img.frame.origin.x = (self.resultsScrollView.frame.size.width - self.imgX) - img.frame.size.width
frameLbl.frame.origin.x = 70
img.frame.origin.y = self.imgY
img.layer.zPosition = 30
img.layer.cornerRadius = img.frame.size.width/2
img.clipsToBounds = true
self.resultsScrollView.addSubview(img)
self.imgY += frameLbl.frame.height + 20
self.resultsScrollView.contentSize = CGSize(width: theWidth, height: self.messageY)
frameLbl.frame.origin.x = 70
This code is weird. You can move the x to 40 and see the result.

How to add multiple textfields programatically in swift ios

I am trying to show multiple textFields by running a loop, that whether the number of textfields noTextField is greater than zero (which is an input value), it should display the multiple textFields on ViewController.
Here is what I have one textfield and prints multiple hello but could not display multiple textfields.
What I have
enter image description here
What I want
enter image description here
if self.noTextFields! > 0 {
for _ in 0..<self.noTextFields! {
// self.createForm()
print ("hello")
let sampleTextField = UITextField(frame: CGRect(x: 20, y: 100, width: 300, height: 40))
sampleTextField.placeholder = "Enter text here"
sampleTextField.font = UIFont.systemFont(ofSize: 15)
sampleTextField.borderStyle = UITextBorderStyle.roundedRect
sampleTextField.autocorrectionType = UITextAutocorrectionType.no
sampleTextField.keyboardType = UIKeyboardType.default
sampleTextField.returnKeyType = UIReturnKeyType.done
sampleTextField.clearButtonMode = UITextFieldViewMode.whileEditing;
sampleTextField.contentVerticalAlignment = UIControlContentVerticalAlignment.center
sampleTextField.delegate = self as? UITextFieldDelegate
self.view.addSubview(sampleTextField)
}
}
Mistakes and Corrections:
Check the SubView items contents for the self.view by self.view.items values printing in logs.
You have not assigned the X / Y position for the +1 counter text fields you are allocating to any incremental position so even if the new object will get created it will be overlapped on the same previous item.
I would always recommend to put the textfield object in array at same time when you do addSubview call, immediately after this self.view.addSubview(sampleTextField) call. This will help me to save the reference for each text field item when required to modify / access / deallocate.
You also set the tag for each textfield object so its better to get the object with that tag from the subviews with [self.view viewWithTag:tagNo] call if you dont want an array to be used.
Your snippet will look like
var xValue = 0,yValue =0
var tagNo = 0
var textObjects = allocate new array.
if self.noTextFields! > 0 {
for _ in 0..<self.noTextFields! {
// self.createForm()
print ("hello")
let sampleTextField = UITextField(frame: CGRect(x: xValue, y: yValue, width: 300, height: 40)) //Note that I have set xValue and yValue
sampleTextField.placeholder = "Enter text here"
sampleTextField.font = UIFont.systemFont(ofSize: 15)
sampleTextField.borderStyle = UITextBorderStyle.roundedRect
sampleTextField.autocorrectionType = UITextAutocorrectionType.no
sampleTextField.keyboardType = UIKeyboardType.default
sampleTextField.returnKeyType = UIReturnKeyType.done
sampleTextField.clearButtonMode = UITextFieldViewMode.whileEditing;
sampleTextField.contentVerticalAlignment = UIControlContentVerticalAlignment.center
sampleTextField.delegate = self as? UITextFieldDelegate
sampleTextField.tag = tagNo //Note this line for tagNo
self.view.addSubview(sampleTextField)
textObjects.addObject:sampleTextField //Note this line for adding textfield to array for reference to get total items added
yValue = yValue + sampleTextField.frame.size.height + 20; //Added yValue to place another text view at bottom of initial one and 20px buffer for gap.
}
}
print "Total Textobjects in array:textObjects.count
If required to get object from view its self.view.viewwithTag(tagNo) will return exact text field.
You just add dynamic value of y(add x if required).
var counter = 30
var yValue = 0
in for loop you just need to add below code
let sampleTextField = UITextField(frame: CGRect(x: 20, y: yValue, width: 300, height: 40))
yValue = Counter
//(space each textfield if 30 because height of textfield is 40)
counter = counter + 70

How to use variables in CGRectMake function - attempting to output data in table-like structure

I am attempting to output a list of an account's 'friends' by pragmatically creating and stacking labels. I have fetched the accounts' friends from a MySQL database (accessible via NSURL interacting with a PHP script) and loaded them into an array. The goal is to loop through the array and create a label that is positioned slightly below the previous one each iteration. The problem I have run into is when I pass a variable into the CGRectMake function to create the label, it will not accept the int because it is not of type "CGFloat". I feel like I have tried just about everything, but I can never cast the data type correctly.Here is my code:
import UIKit
class viewFriendsViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let friendsArray = ["billy", "joe", "bob", "jim"]
var inc = 0
for index in friendsArray {
let label: UILabel = UILabel()
let yPos: CGFloat = Float(inc * 10)
label.frame = CGRectMake(50, 50, 200, yPos)
label.backgroundColor = UIColor.blackColor()
label.textColor = UIColor.whiteColor()
label.textAlignment = NSTextAlignment.Center
label.text = "\(index)"
self.view.addSubview(label)
inc = inc + 1 // I have not been able to play with the label yet to determine how to move it's vertical position because I cannot run the program due to the casting error.
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
try this
var inc = 0
for index in friendsArray {
let label: UILabel = UILabel()
//type conversion is
let yPos = CGFloat(inc * 10)
label.frame = CGRectMake(50,yPos,200,50) // if you want to change the Y-Coodinates use in Y frame not in height
label.backgroundColor = UIColor.blackColor()
label.textColor = UIColor.whiteColor()
label.textAlignment = NSTextAlignment.Center
label.text = "\(index)"
self.view.addSubview(label)
inc = inc + 1
}
the above choice is not work try this
var inc : CGFloat = 0
for index in friendsArray {
let label: UILabel = UILabel()
label.frame = CGRectMake(50,inc,200,50) // if you want to change the Y-Coodinates use in Y frame not in height
label.backgroundColor = UIColor.blackColor()
label.textColor = UIColor.whiteColor()
label.textAlignment = NSTextAlignment.Center
label.text = "\(index)"
self.view.addSubview(label)
inc = inc * 10 // inc + 10
}
You should take advantage of the new notation for CGRect in swift instead of using legacy c macros, these allow for usage with Int, Double and Float:
CGRect(x: 50, y: 200, width: 20, height: 40)
Note that these frames are now created using standard swift init functions for structs.
I've tested it with CGFloat() instead of Float() and it works:
var inc = 0
var ypos: CGFloat = CGFloat(inc * 10)
var rect: CGRect = CGRectMake(50, ypos, 200, 200)
Also note you are currently using your ypos at the position of the height. Remember it is
CGRectMake(<xPos>, <yPos>, <width>, <height>)

Resources