Swift ios how to set nav bar image not stretch - ios

I have made it possible to add a background image to a nav bar using the ff code but the image is stretched. Is there any way that it will not be stretched?
self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: "BG.jpg"), for: .default)

You could try this,
UINavigationBar.appearance().setBackgroundImage(UIImage(named: "BG.jpg")!.resizableImage(withCapInsets: UIEdgeInsets.zero, resizingMode: .stretch), for: .default)
Try out other options in the code as well.
UPDATE
You can even try below category for UINavigationBar
extension UINavigationController {
func setBackgroundImage(_ image: UIImage) {
navigationBar.isTranslucent = true
navigationBar.barStyle = .blackTranslucent
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
view.insertSubview(imageView, belowSubview: navigationBar)
NSLayoutConstraint.activate([
imageView.leftAnchor.constraint(equalTo: view.leftAnchor),
imageView.rightAnchor.constraint(equalTo: view.rightAnchor),
imageView.topAnchor.constraint(equalTo: view.topAnchor),
imageView.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor)
])
}
}
Above code may be vary depending on your final requirements.

class TutorialViewController: UIViewController {
// This property will set the Image to Navigation Bar
public var navigationBarImage: UIImage? {
get {
return (navigationItem.titleView as? UIImageView)?.image
} set {
if newValue != nil {
let imageView = UIImageView(image: newValue)
imageView.contentMode = .scaleAspectFill
navigationItem.titleView = imageView
} else {
navigationItem.titleView = nil
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
navigationBarImage = #imageLiteral(resourceName: "my_nav_image")
}

for all images you can set the content mode =
.scaleToFill (UIViewContentModeScaleToFill)
.scaleAspectFit (UIViewContentModeScaleAspectFit)
.scaleAspectFill (UIViewContentModeScaleAspectFill)
If you do not want to see the contents that are outside the bounds you need to remember to set clipsToBounds to true on the containing superview
View.clipsToBounds = true

Related

In xcode 11.4.1 I get this error "Use of unresolved identifier" for an image which is in assets folder, why is that?

import UIKit
class ViewController: UIViewController {
let canoaimageview: UIImageView = {
let imageview = UIImageView(image: canoa) //ERROR Use of unresolved identifier 'canoa'
imageview.translatesAutoresizingMaskIntoConstraints = false
return imageview
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(canoaimageview)
setupLayout()
}
private func setupLayout() {
canoaimageview.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
canoaimageview.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
canoaimageview.widthAnchor.constraint(equalToConstant: 150).isActive = true
canoaimageview.heightAnchor.constraint(equalToConstant: 150).isActive = true
}
}
//an attached image is included showing the error and assets folder
You need to make an UIImage first to assign it to imageView like this
let canoaimageview: UIImageView = {
let imageview = UIImageView(image: UIImage(named: "canoa")) //ERROR Use of unresolved identifier 'canoa'
imageview.contentMode = .scaleAspectFit
imageview.translatesAutoresizingMaskIntoConstraints = false
return imageview
}()

Why does UIView fill the superView?

I am creating a subview programmatically that I would like to be positioned over a superView, but I do not want it to fill the enter superView.
I have been checking around to see if this question has been asked before but for some reason, I can only find answers to how to fill the entire view.
I would really appreciate it if someone could help critique my code and explain how to position a subView instead of filling the entire superview.
class JobViewController: UIViewController {
var subView : SubView { return self.view as! SubView }
var requested = false
let imageView: UIImageView = {
let iv = UIImageView(image: #imageLiteral(resourceName: "yo"))
iv.contentMode = .scaleAspectFill
iv.isUserInteractionEnabled = true
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(imageView)
imageView.fillSuperview()
subView.requestAction = { [ weak self ] in
guard let strongSelf = self else { return }
strongSelf.requested = !strongSelf.requested
if strongSelf.requested {
UIView.animate(withDuration: 0.5, animations: {
strongSelf.subView.Request.setTitle("Requested", for: .normal)
strongSelf.subView.contentView.backgroundColor = UIColor.red.withAlphaComponent(0.5)
})
} else {
UIView.animate(withDuration: 0.5, animations: {
strongSelf.subView.Request.setTitle("Requested", for: .normal)
strongSelf.subView.contentView.backgroundColor = UIColor.blue
})
}
}
}
override func loadView() {
// I know the issue lies here, but how would I go about setting the frame of the subview to just be positioned on top of the mainView?
self.view = SubView(frame: UIScreen.main.bounds)
}
}
I have my subView built in a separate file, I am not sure whether or not I would need its information since It is just what is inside of the subview.
You should add your subView as a subview of self.view and not set it equal your main view. And then set the constraints accordingly.
override func viewDidLoad() {
self.view.addSubview(subView)
subview.translatesAutoresizingMaskIntoConstraint = false
addSubview.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true
addSubview.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = true
addSubview.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true
addSubview.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
}
Regarding your initialisation problem try:
var subView = SubView()
I hope I understood your question correct.

Peculiar top margin in the ImageView added from ChildViewController

I have created a child view controller as below. It has a UIImageView. I added the UIImageView to the view as below.
class SampleChildViewController : UIViewController {
let imageView : UIImageView = {
let imageview = UIImageView()
imageview.translatesAutoresizingMaskIntoConstraints = false
imageview.clipsToBounds = true
imageview.contentMode = .scaleAspectFit
imageview.image = UIImage(named: "cat")
return imageview
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(imageView)
NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: view.topAnchor),
imageView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 10),
imageView.widthAnchor.constraint(equalToConstant: 150),
imageView.heightAnchor.constraint(equalToConstant: 150)
])
}
}
This is how the parent view controller looks like.
class ViewController: UIViewController {
let child : SampleChildViewController = SampleChildViewController()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.red
child.view.translatesAutoresizingMaskIntoConstraints = false
addChild(child)
child.didMove(toParent: self)
view.addSubview(child.view)
NSLayoutConstraint.activate([
child.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 8),
child.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 8),
child.view.leftAnchor.constraint(equalTo: view.leftAnchor),
child.view.rightAnchor.constraint(equalTo: view.rightAnchor),
])
}
}
Now the problem is I have a strange top margin to the imageview as shown below. How to fix it?
problem is with imageview.contentMode = .scaleAspectFit. The boundary you see for the image is not the real boundary. Set the content mode as imageview.contentMode = .scaleAspectFill as it'll fill the whole view.
It should look something below
let imageView : UIImageView = {
let imageview = UIImageView()
imageview.translatesAutoresizingMaskIntoConstraints = false
imageview.clipsToBounds = true
imageview.contentMode = .scaleAspectFill
imageview.image = UIImage(named: "cat")
return imageview
}()

iOS autolayout locating images at the same line with same ration for each views

I am working on studying iOS autolayout
However, which constraints and functions should I use for making those views have the same location.
I mean, I want to locate those two UIImageView at center like the first picture. But, whenever I change the UIView, they go down and down... what should I do?
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
let firstView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "angry").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let secondView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "crying").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let thirdView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "heartEmpty").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let fourthView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "joy").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
func setupViews() {
view.addSubview(firstView)
// setup first view
firstView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
firstView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
firstView.widthAnchor.constraint(equalToConstant: 80).isActive = true
firstView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(secondView)
// setup second view
secondView.leftAnchor.constraint(equalTo: firstView.rightAnchor, constant: 20).isActive = true
secondView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
secondView.widthAnchor.constraint(equalToConstant: 80).isActive = true
secondView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(thirdView)
thirdView.leftAnchor.constraint(equalTo: secondView.rightAnchor, constant: 20).isActive = true
thirdView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
thirdView.widthAnchor.constraint(equalToConstant: 80).isActive = true
thirdView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(fourthView)
fourthView.leftAnchor.constraint(equalTo: thirdView.rightAnchor, constant: 20).isActive = true
fourthView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
fourthView.widthAnchor.constraint(equalToConstant: 80).isActive = true
fourthView.heightAnchor.constraint(equalToConstant: 80).isActive = true
}
}
Hello My Friend You Can Make It By Code Or By Storyboard using stack view i will show you by code below hope this help you
import UIKit
class ViewController: UIViewController {
let firstView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "MyImage").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let secondView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "image").withRenderingMode(.alwaysOriginal)
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
func setupViews() {
view.addSubview(firstView)
// setup first view
firstView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
firstView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
firstView.widthAnchor.constraint(equalToConstant: 80).isActive = true
firstView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(secondView)
// setup second view
secondView.leftAnchor.constraint(equalTo: firstView.rightAnchor, constant: 20).isActive = true
secondView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
secondView.widthAnchor.constraint(equalToConstant: 80).isActive = true
secondView.heightAnchor.constraint(equalToConstant: 80).isActive = true
}
}
Follow these Steps, you can do it in Storyboard.
1 - Select first Image, align it horizontally and vertically in container by giving it constraints using the "align" tab which is usually located at the bottom-right corner of the storyboard window.
2 - Now, select the first image and goto Size Inspector.Scroll down to it's constraints and there will be a constraint named as "Align Center X To : SuperView".
3 - There will be an "Edit" label right beside it.Click on it, and a popover will show up.
4 - in the popover , in the first Line it will show Constant = 0.
5 - Now here's the fun part, if you put negative value in it , say "-20" it will move 20 spaces to the left.Similarly, if you put "20", it will move 20 spaces to the right.
Now, do the same for the second image until you have achieved your result. Both the images will now be in the centre of the screen.
I am new to IOS as Well, but this worked for me and I hope it works for u as well. :-)

UINavigationBar contentMode not being set

I am trying to make the background of the UINavigationBar an image, and the image isn't the exact size of the bar. I can't seem to set the contentMode of the bar correctly for some reason. This is the code I have:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// ...
let image = UIImage(named: object?.imageName ?? "")
navigationController?.navigationBar.alpha = 0
navigationController?.navigationBar.setBackgroundImage(image, for: .default)
self.navigationController?.navigationBar.contentMode = .scaleAspectFill
UIView.animate(withDuration: Double(UINavigationControllerHideShowBarDuration), animations: {
self.navigationController?.navigationBar.alpha = 1
})
}
I don't know what I'm doing wrong, or maybe contentMode just doesn't do anything for UINavigationBar.
What's currently happening is the background image is just presented again like mosaic
Thanks
You can create UIView and add Image and Text to it, but you must set constraints
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
titleView.addSubview(containerView)
let profileImageView = UIImageView()
profileImageView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.contentMode = .scaleAspectFill
profileImageView.layer.cornerRadius = 20
profileImageView.clipsToBounds = true
containerView.addSubview(profileImageView)
profileImageView.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true
profileImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 40).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 40).isActive = true
self.navigationItem.titleView = titleView
titleView.addGestureRecognizer(UITapGestureRecognizer(target:
self, action: #selector(func)))
I hope that I helped you

Resources