UIWebView sizeThatFits only works in delegate method - ios

So I use a UIWebView like a UILabel with a UITextBox that changes its text via
#IBAction func textChanged(_ sender: Any){}
I size the UIWebView to the size of its content with a fixed width and a flexible height using
override func viewDidLoad() {
super.viewDidLoad()
label = WebLabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 1))
label.delegate = self
label.layer.borderColor = UIColor.black.cgColor
label.layer.borderWidth = 1.0
self.view.addSubview(label)
}
Where WebLabel is a class derived from UIWebView which implements following method :
func set(query: String)
{
let htmlString = makeHTMLString(input: (query))
self.loadHTMLString(htmlString, baseURL: nil)
self.sizeToFit()
}
So with this textChanged I get my desired result :
#IBAction func textChanged(_ sender: Any) {
label.set(query: (sender as! UITextField).text!)
label.frame = CGRect(x: label.frame.origin.x, y: label.frame.origin.y, width: label.frame.width, height: 1)
let size = label.sizeThatFits(CGSize.zero)
label.frame = CGRect(x: label.frame.origin.x, y: label.frame.origin.y, width: label.frame.width, height: size.height)
}
But I also want to set a initial html text. I do this using:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
label.set(query: "Hello World !")
label.frame = CGRect(x: label.frame.origin.x, y: label.frame.origin.y, width: label.frame.width, height: 1)
let size = label.sizeThatFits(CGSize.zero)
label.frame = CGRect(x: label.frame.origin.x, y: label.frame.origin.y, width: label.frame.width, height: size.height)
}
But that doesn't work. So the code seems to only work when triggered by user in the delegate method. How do I solve this problem ? Thanks a lot for your help !

Related

Swift changing button position doesn't work

I'm trying to change UIButton but it doesn't work. My code is like this.
#IBAction func addButtonTapped(_ sender: Any) {
print(defaultAddButton.center)
let buttonPos = CGPoint(x: defaultAddButton.frame.midX, y: defaultAddButton.frame.midY)
let width = self.view.bounds.width
let height: CGFloat = 100
let uiView = SubCollecionView(frame: CGRect(x: buttonPos.x - width / 2, y: buttonPos.y - height / 2, width: width, height: height))
self.view.addSubview(uiView)
self.defaultAddButton.center.y += 200
}
SubCollectionView is my custom view. Above code works without self.view.addSubview(uiView) line. I can't understand why it doesn't work. Thank you in advance!
do not fully understand your problem, but can suggest that you have a problem with animation, with this line of code:
self.defaultAddButton.center.y += 200
The above code doesn't work because you need to update the view to update its layout immediately, use this method to update view "layoutIfNeeded()"
Example of code:
class VC: UIViewController {
lazy var buttonAction: UIButton = {
let view = UIButton()
view.translatesAutoresizingMaskIntoConstraints = false
view.setTitle("Action", for: .normal)
view.setTitleColor(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1), for: .normal)
view.backgroundColor = .blue
view.addTarget(self, action: #selector(action(_:)), for: .touchUpInside)
return view
}()
#objc func action(_ sender: UIButton) {
print("action")
print(buttonAction.center)
let buttonPos = CGPoint(x: buttonAction.frame.midX, y: buttonAction.frame.midY)
let width = self.view.bounds.width
let height: CGFloat = 100
let uiView = MediaPlayer(frame: CGRect(x: buttonPos.x - width / 2, y: buttonPos.y - height / 2, width: width, height: height))
self.view.addSubview(uiView)
self.buttonAction.center.y += 200
UIView.animate(withDuration: 1.0) {
self.view.layoutIfNeeded()
}
}
func setupButton() {
self.view.addSubview(buttonAction)
buttonAction.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
buttonAction.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -70).isActive = true
buttonAction.heightAnchor.constraint(equalToConstant: 50).isActive = true
buttonAction.widthAnchor.constraint(equalToConstant: 100).isActive = true
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .gray
setupButton()
}
}
You can try setting changes/frame in view over
viewDidLayoutSubviews
You should call layoutIfNeeded() after this.
#IBAction func addButtonTapped(_ sender: Any) {
print(defaultAddButton.center)
let buttonPos = CGPoint(x: defaultAddButton.frame.midX, y: defaultAddButton.frame.midY)
let width = self.view.bounds.width
let height: CGFloat = 100
let uiView = SubCollecionView(frame: CGRect(x: buttonPos.x - width / 2, y: buttonPos.y - height / 2, width: width, height: height))
self.view.addSubview(uiView)
self.defaultAddButton.center.y += 200
self.view.layoutIfNeeded()
}
If this doesn't work. Please try to call UI modification code inside the main queue.
#IBAction func addButtonTapped(_ sender: Any) {
print(defaultAddButton.center)
DispatchQueue.main.async {
let buttonPos = CGPoint(x: defaultAddButton.frame.midX, y: defaultAddButton.frame.midY)
let width = self.view.bounds.width
let height: CGFloat = 100
let uiView = SubCollecionView(frame: CGRect(x: buttonPos.x - width / 2, y: buttonPos.y - height / 2, width: width, height: height))
self.view.addSubview(uiView)
self.defaultAddButton.center.y += 200
self.view.layoutIfNeeded()
}
}

How to change UINavigationBar height?

Is it possible to change the UINavigationBar height in ios 11?
I've tried this:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let height: CGFloat = 50 //whatever height you want to add to the existing height
let bounds = self.navigationController!.navigationBar.bounds
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height + height)
}
and this:
extension UINavigationBar {
override open func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: UIScreen.main.bounds.width, height: 100)
}
}
and none of them seem to work.

How to implement the NavigationBar effect of AppStore ranking list page

I increase the NavigationBar height with the following code
override func viewDidLayoutSubviews() {
setUpSegmentControll()
let view = UIView(frame: CGRect(x: 0, y: 44, width: ScreenWidth, height: 40))
view.backgroundColor = UIColor.init(colorLiteralRed: 89/255, green: 89/255, blue: 89/255, alpha: 1)
segmentControll.center.x = view.center.x
view.addSubview(segmentControll)
self.navigationController?.navigationBar.addSubview(view)
}
But the segment clicked no effect,what's wrong with the code
You need to increase the size of navigation bar. Try below code it works fine
import UIKit
/*extension UINavigationBar {
open override func sizeThatFits(_ size: CGSize) -> CGSize {
var rect = self.frame;
let screenRect = UIScreen.main.bounds
rect.size.width = screenRect.size.width
rect.size.height = 104
return rect.size
}
}*/
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.navigationController!.navigationBar.clipsToBounds = true
}
override func viewDidAppear(_ animated: Bool) {
self.navigationController!.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 104.0)
}
override func viewWillDisappear(_ animated: Bool) {
self.navigationController!.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 64.0)
}
override func viewDidLayoutSubviews() {
let segmentControll = UISegmentedControl(items: ["1","2"])
segmentControll.frame = CGRect(x: 0, y: 5, width: 300, height: 30)
let view = UIView(frame: CGRect(x: 0, y: 64, width: UIScreen.main.bounds.size.width, height: 40))
view.backgroundColor = UIColor.init(colorLiteralRed: 89/255, green: 89/255, blue: 89/255, alpha: 1)
segmentControll.center.x = view.center.x
view.addSubview(segmentControll)
self.navigationController?.navigationBar.addSubview(view)
}
}
You have to increase the height of the navigation bar. Refer the below link to increase the height of the navigation bar
How to increase the height of UINavigationBar?

iOS navigationItem titleView image and text

I want to set the navigationItem's titleView with image and text like the picture below:
How do I achieve that?
More specifically, I am trying to do this in Swift.
The condition, your controller must have its navigation controller:
Using my code I write below, the result is like this:
In your view controller ,try my code below:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
initUI()
}
// MARK: - init
func initUI() {
let rect:CGRect = CGRect.init(origin: CGPoint.init(x: 0, y: 0), size: CGSize.init(width: 64, height: 64))
let titleView:UIView = UIView.init(frame: rect)
/* image */
let image:UIImage = UIImage.init(named: "01.jpg")!
let image_view:UIImageView = UIImageView.init(image: image)
image_view.frame = CGRect.init(x: 0, y: 0, width: 30, height: 30)
image_view.center = CGPoint.init(x: titleView.center.x, y: titleView.center.y - 10)
image_view.layer.cornerRadius = image_view.bounds.size.width / 2.0
image_view.layer.masksToBounds = true
titleView.addSubview(image_view)
/* label */
let label:UILabel = UILabel.init(frame: CGRect.init(x: 0, y: 30, width: 64, height: 24))
label.text = "Hello"
label.font = UIFont.systemFont(ofSize: 12)
label.textAlignment = .center
titleView.addSubview(label)
self.navigationItem.titleView = titleView
}

set the padding of a text field using swift in xcode

How to create some space at the beginning of a text field using swift?
I looked at the post
padding of text field
I don't understand what the subclass is doing and how do I use that class to padding.
Thank you very much
https://stackoverflow.com/a/27066764/846780
This answer is very clear,
If you subclass UITextField you can override textRectForBounds, editingRectForBounds and placeholderRectForBounds. These methods just allow you to add a rect (frame) to your textfield's label.
newBounds method create the rect (frame) that will be added to textfield's label.
Finally your padding is: let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5);
Now you have a custom UITextField that has a custom padding.
If you create your new subClass like this class MyTextField: UITextField for example, you only need to change the class of the UITextField that you've added into IB file.
Complementing the answer of klevison-matias this is the code I use when I want to add a padding to my TextField in Swift 3
//UITextField : override textRect, editingRect
class LeftPaddedTextField: UITextField {
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + 10, y: bounds.origin.y, width: bounds.width, height: bounds.height)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + 10, y: bounds.origin.y, width: bounds.width, height: bounds.height)
}
}
Then in my TextField I use in this way:
let emailTextField: LeftPaddedTextField = {
let textField = LeftPaddedTextField()
textField.placeholder = "Enter email"
textField.layer.borderColor = UIColor.lightGray.cgColor
textField.layer.borderWidth = 1
textField.keyboardType = .emailAddress
return textField
}()
let passwordTextField: LeftPaddedTextField = {
let textField = LeftPaddedTextField()
textField.placeholder = "Enter password"
textField.layer.borderColor = UIColor.lightGray.cgColor
textField.layer.borderWidth = 1
textField.isSecureTextEntry = true
return textField
}()
Create TextField outlet and use following code. Say "nameTextField" has to add padding.
let paddingView = UIView(frame: CGRectMake(x: 0, y: 0, width: 30, height: 30))
nameTextField.leftView = paddingView
nameTextField.leftViewMode = .always
nameTextField.placeholder = "Enter Name"
You can add Image in paddingView.
Based on #Jorge Casariego's answer I came up with this solution.
You can set PaddedTextField class and the desired padding through the Interface Builder!
class PaddedTextField: UITextField {
#IBInspectable var padding: CGFloat = 0
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + padding, y: bounds.origin.y, width: bounds.width - padding * 2, height: bounds.height)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + padding, y: bounds.origin.y, width: bounds.width - padding * 2, height: bounds.height)
}
}
full code sample:
make sure your TextField points to RoundedTextField via Story board
import UIKit
class RoundedTextField: UITextField {
override func awakeFromNib() {
// add rounded corner
self.layer.cornerRadius = 15.0
self.clipsToBounds = false
super.awakeFromNib()
}
// For the padding from the left
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + 15.0, y: bounds.origin.y, width: bounds.width, height: bounds.height)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + 15.0, y: bounds.origin.y, width: bounds.width, height: bounds.height)
}
}

Resources