Swift Add UIView with subviews to titleView - ios

I'd like to customize my navigation bar and insert a UIView with two subviews into the title view of the navigation bar.
Unfortunately the subviews aren't displayed.
Do you have any idea why?
let titleContainer = UIView()
titleContainer.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
let searchIcon = UIButton()
searchIcon.setImage(UIImage(named: "search_icon"), for: UIControlState.normal)
searchIcon.layer.frame = CGRect(x: 0, y: (UIScreen.main.bounds.size.height - 28) / 2, width: 28, height: 28)
titleContainer.addSubview(searchIcon)
let titleLabel = UILabel()
titleLabel.frame = CGRect(x: 28, y: UIScreen.main.bounds.size.height, width: UIScreen.main.bounds.size.width-28, height: UIScreen.main.bounds.size.height)
titleLabel.textColor = UIColor(red:255, green:255, blue:255, alpha:1.0)
titleContainer.addSubview(self.titleLabel)
self.navigationItem.titleView = titleContainer
problem and expected solution:

Why did you use height of all the element as UIScreen.main.bounds.size.height? Please try the below code.
P.S. I have changed the color of searchIcon as i didn't have the image and changed the color of text of label and added some text so that it is visible.
let titleContainer = UIView()
titleContainer.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 45)
let searchIcon = UIButton()
//searchIcon.setImage(UIImage(named: "search_icon"), for: UIControlState.normal)
searchIcon.backgroundColor = UIColor.red
searchIcon.layer.frame = CGRect(x: 0, y: 8, width: 28, height: 28)
titleContainer.addSubview(searchIcon)
let titleLabel = UILabel()
titleLabel.frame = CGRect(x: 28, y: 8, width: UIScreen.main.bounds.size.width-28, height: 30)
titleLabel.textColor = UIColor.blue//(red:255, green:255, blue:255, alpha:1.0)
titleContainer.addSubview(titleLabel)
titleLabel.text = "Sample Text"
self.navigationItem.titleView = titleContainer
Here is the screenshot of the above code:
Please change the x,y accordingly as per your requirement.

Have you considered making your let bar = UINavigationBar() programmatically and then add it with: self.view.addSubview(bar)?
So you can push all the "UIBarItems" you want..?

Related

Reduce gap between left-view and curser in textfield

I am using below code for adding left view in textfield:
func setUI()
{
txtUserCode.leftViewMode = .always
let label = UILabel(frame: CGRect(x: 7, y: 0, width: 18, height: txtUserCode.frame.size.height))
label.text = "#"
txtUserCode.leftView?.frame = CGRect(x: 0, y: 0, width: 18, height: txtUserCode.frame.size.height)
txtUserCode.leftView = label
label.backgroundColor = UIColor.green
txtUserCode.leftView?.backgroundColor = UIColor.red
}
But the problem is there is gap between left view and curser you can see in screen shot.
See there is small gap between curser and the left view, you can see between 'premB' and '#'
Any help or suggestion will be helpful.
Update your code to below.
func setUI()
{
txtUserCode.leftViewMode = .always
let label = UILabel(frame: CGRect(x: 7, y: 0, width: 18, height: txtUserCode.frame.size.height))
label.text = "#"
label.sizeToFit()
label.frame = CGRect(x: 7, y: 0, width: label.frame.size.width, height: txtUserCode.frame.size.height)
txtUserCode.leftView?.frame = CGRect(x: 0, y: 0, width: label.frame.size.width, height: txtUserCode.frame.size.height)
txtUserCode.leftView = label
label.backgroundColor = UIColor.green
txtUserCode.leftView?.backgroundColor = UIColor.red
}
To get the exact size, first make sizeToFit for the label & instead of 18, give the width of the label.
Add below line and try again.
txtUserCode.borderStyle = .none

how to set the position of the placeholder of a placeholder in swift programatically ?

I am trying to create the following registration form . I cant set the space between the textfield image and the placeholder text . I've tried the following :
Email_text.placeholderRect(forBounds: CGRect(x: 10, y: 0 , width: 60, height: 50))
any idea how can I fix this ?
Thanks
You can simply do like this, an extension for UITextField
extension UITextField {
func setTextIconAndPlaceholder(icon: UIImage, placeholder: String) {
let imageView = UIImageView()
imageView.image = icon
imageView.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
let view = UIView()
view.frame = CGRect(x: 0, y: 2, width: 25, height: 25)
view.backgroundColor = UIColor.clear
view.addSubview(imageView)
self.leftView = view
self.leftViewMode = UITextFieldViewMode.always
self.placeholder = placeholder
}
}

Set background color for top safe area only in iOS 11

I'm new to Swift. I have set my top bar programmatically.It works fine for all versions except for iOS version 11.
I want to change the background color of the safe area in iPhone X. Presently I have just added the following code to hide the status bar.
override var prefersStatusBarHidden: Bool {
return true
}
I have created top bar using code:
//Top Bar
let topBar = UIView(frame:CGRect(x: 0,y: 0, width: width, height: 60))
topBar.backgroundColor = UIColor.white
topBar.layer.shadowColor = UIColor.gray.cgColor
topBar.layer.shadowOffset = CGSize(width: 0, height: 3)
topBar.layer.shadowOpacity = 1
topBar.layer.masksToBounds = false
topBar.layer.shadowRadius = 8.0;
//ImageView - Back Button
let backBtn = UIButton(frame:CGRect(x: 25, y: 18, width: 18, height: 34))
let backBtnImage = UIImage(named: "back_button") as UIImage?
backBtn.setImage(backBtnImage, for: .normal)
backBtn.layer.masksToBounds = true
backBtn.addTarget(self,action:#selector(backButtonClicked),
for:.touchUpInside)
//Label - Title
let titleLabel = UILabel(frame:CGRect(x: width * 0.3, y: 13, width: width * 0.55, height: 40))
titleLabel.text = "Favorites"
titleLabel.contentMode = UIViewContentMode.center
//include all in view
topBar.addSubview(titleLabel)
topBar.addSubview(backBtn)
containerView.addSubview(topBar)
Is there a way in which i can do it without using UINavigationBar or setting status bar.
Hi you can also try this one ,
need to add a view with same background which you set in your header view and add to container parent view .
please refer below code
//Top Bar
let safeAreaView = UIView(frame:CGrect(x: 0,y: 0, width: width, height: 40))
safeAreaView.backgroundColor = UIColor.white
self.view.addSubview(safeAreaView)
let topBar = UIView(frame:CGRect(x: 0,y: 0, width: width, height: 60))
topBar.backgroundColor = UIColor.white
topBar.layer.shadowColor = UIColor.gray.cgColor
topBar.layer.shadowOffset = CGSize(width: 0, height: 3)
topBar.layer.shadowOpacity = 1
topBar.layer.masksToBounds = false
topBar.layer.shadowRadius = 8.0;
//ImageView - Back Button
let backBtn = UIButton(frame:CGRect(x: 25, y: 18, width: 18, height: 34))
let backBtnImage = UIImage(named: "back_button") as UIImage?
backBtn.setImage(backBtnImage, for: .normal)
backBtn.layer.masksToBounds = true
backBtn.addTarget(self,action:#selector(backButtonClicked),
for:.touchUpInside)
//Label - Title
let titleLabel = UILabel(frame:CGRect(x: width * 0.3, y: 13, width: width * 0.55, height: 40))
titleLabel.text = "Favorites"
titleLabel.contentMode = UIViewContentMode.center
//include all in view
topBar.addSubview(titleLabel)
topBar.addSubview(backBtn)
containerView.addSubview(topBar)

How to create custom uiview that button can be clicked inside uiview?

I tried to create clicked scrollview button like this (at bottom):
this is my code so far:
scView = UIScrollView(frame: CGRect(x: 0, y: view.frame.maxY-110, width: view.bounds.width, height: 110))
self.view.addSubview(scView)
scView.backgroundColor = UIColor.lightGray
scView.translatesAutoresizingMaskIntoConstraints = false
for i in 0 ... 10 {
let myNewView=UIView(frame: CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 200, height: 100))
myNewView.backgroundColor=UIColor.white
myNewView.layer.cornerRadius=10
self.scView.addSubview(myNewView)
let label = UILabel(frame: CGRect(x: xOffset, y: CGFloat(buttonPadding)+5, width: 150, height: 10))
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .left
label.text = "I'am a title label"
label.textColor = .black
myNewView.addSubview(label)
let ditancelabel = UILabel(frame: CGRect(x: xOffset, y: CGFloat(buttonPadding)+5, width: 50, height: 10))
ditancelabel.center = CGPoint(x: 160, y: 285)
ditancelabel.textAlignment = .right
ditancelabel.text = "0.04 km"
ditancelabel.textColor = .red
myNewView.addSubview(ditancelabel)
let textView = UITextView(frame: CGRect(x: xOffset, y: CGFloat(buttonPadding)+15, width: 200.0, height: 40.0))
self.automaticallyAdjustsScrollViewInsets = false
textView.center = self.view.center
textView.textAlignment = NSTextAlignment.justified
textView.textColor = UIColor.lightGray
textView.backgroundColor = UIColor.clear
myNewView.addSubview(textView)
let button = UIButton()
button.tag = i
button.backgroundColor = UIColor.white
button.setTitle("\(i)", for: .normal)
button.setTitleColor(.black, for: .normal)
button.backgroundColor = UIColor.clear
button.addTarget(self, action:#selector(handleRegister(sender:)), for: .touchUpInside)
button.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 200, height: 100)
xOffset = xOffset + CGFloat(buttonPadding) + button.frame.size.width
myNewView.addSubview(button)
}
scView.contentSize = CGSize(width: xOffset, height: scView.frame.height)
but code result like this:
The first button can be clicked, but the other cannot be clicked. And 2 UILabels and 1 UITextView did not appear.
the handleRegister method is to get sender tag and print it as log to know the button can be clicked or not.
How to repair the code so it can be like the custom UIView in the above image?
I need to transfer label and textview text by button click to another viewcontroller which handle by seque in handleRegister.
1) You can't see labels and other control because of your container view size is (200, 100)
let myNewView=UIView(frame: CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 200, height: 100))
and you set center of controls.
label.center = CGPoint(x: 160, y: 285)
ditancelabel.center = CGPoint(x: 160, y: 285)
This center point is not visible within container view. That's why you can't see labels within view. Just comment these line to set center of labels and you can see those perfectly.
2) I need to transfer label and textview text by button click to another viewcontroller which handle by seque in handleRegister.
I hope you have a array in which you stored data to display in your custom view, Just find that object from array based on button tag, and pass that object to another control.
3) The first button can be clicked, but the other cannot be clicked.
Again problem is same like for labels. You had set frame of button like this
button.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 200, height: 100)
and increase xOffset by this line to create another view
xOffset = xOffset + CGFloat(buttonPadding) + button.frame.size.width
xOffset increased each time with the size of button. So if you print xOffset value it actually print like (assuming initial value of xOffset = 10, padding = 0)
for i in 0 ... 10 {
print(xOffset)
..... your other code
}
Output: will be like
10, 210, 410, 610...... Because of this your button is out of bound from container view and because of that you can't click on that.
I have updated your code, check below
scView = UIScrollView(frame: CGRect(x: 0, y: view.frame.maxY-110, width: view.bounds.width, height: 110))
self.view.addSubview(scView)
scView.backgroundColor = UIColor.lightGray
scView.translatesAutoresizingMaskIntoConstraints = false
for i in 0 ... 10 {
let myNewView=UIView(frame: CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 200, height: 100))
myNewView.backgroundColor=UIColor.white
myNewView.layer.cornerRadius=10
self.scView.addSubview(myNewView)
let subVwOffset = 5
let label = UILabel(frame: CGRect(x: subVwOffset, y: CGFloat(buttonPadding)+5, width: 150, height: 10))
label.textAlignment = .left
label.text = "I'am a title label"
label.textColor = .black
myNewView.addSubview(label)
let ditancelabel = UILabel(frame: CGRect(x: subVwOffset, y: CGFloat(buttonPadding)+5, width: 50, height: 10))
ditancelabel.textAlignment = .right
ditancelabel.text = "0.04 km"
ditancelabel.textColor = .red
myNewView.addSubview(ditancelabel)
let textView = UITextView(frame: CGRect(x: subVwOffset, y: CGFloat(buttonPadding)+15, width: 200.0, height: 40.0))
self.automaticallyAdjustsScrollViewInsets = false
textView.center = self.view.center
textView.textAlignment = NSTextAlignment.justified
textView.textColor = UIColor.lightGray
textView.backgroundColor = UIColor.clear
myNewView.addSubview(textView)
let button = UIButton()
button.tag = i
button.backgroundColor = UIColor.white
button.setTitle("\(i)", for: .normal)
button.setTitleColor(.black, for: .normal)
button.backgroundColor = UIColor.clear
button.addTarget(self, action:#selector(handleRegister(sender:)), for: .touchUpInside)
button.frame = CGRect(x: subVwOffset, y: CGFloat(buttonPadding), width: 200, height: 100)
xOffset = xOffset + CGFloat(buttonPadding) + button.frame.size.width
myNewView.addSubview(button)
}
scView.contentSize = CGSize(width: xOffset, height: scView.frame.height)
Let me know if you find any other difficulty.

Add text and image to UITextField right side

How do I add Text and Image on right of the UITextField.
I have a UITextField which will initially have a text/label at right of it and when user click on the button the same textField will now have text + image to the right of UITextField
Image can be added like this but what about the text/label and both ?
txtField.rightViewMode = .always
txtField.rightView = UIImageView(image: UIImage(named: "selectdrop"))
For that you can create on UIView instance and add the UILabel and UIImageView inside it then finally set that view as rightView of textField. Some thing like below.
let rightView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 40))
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 60, height: 40))
label.text = "Text"
label.textColor = UIColor.red
label.textAlignment = .center
let imageView = UIImageView(frame: CGRect(x: 40, y: 0, width: 40, height: 40))
imageView.image = UIImage(named: "selectdrop")
rightView.addSubview(label)
rightView.addSubview(imageView)
txtField.rightView = rightView
txtField.rightViewMode = .always

Resources