I am facing a weird issue. There is an UIPopoverPresentationController and I have this situation:
It is working fine on Portrait, but on Landscape, I lose the background and the layout.
AND it is happening only for iPhone 11 and Max version, it is fine for iPhone X, 11 pro, 12, etc.
Obs: If I set the popover background color, it works with the new color, but why the background is transparent only on these versions above with the layout different?
I did a POC with a simple code to reproduce the problem:
ViewController
#IBAction func showPopover(sender: AnyObject) {
let popVC = PopoverViewController.init()
popVC.modalPresentationStyle = .popover
let popOverVC = popVC.popoverPresentationController
popOverVC?.delegate = self
popOverVC?.sourceView = view
popOverVC?.sourceRect = sender.frame
popVC.preferredContentSize = CGSize(width: 250, height: 250)
self.present(popVC, animated: true)
}
PopoverViewController
override func viewDidLoad() {
let view2 = UIView.init()
let view3 = UIView.init()
view2.backgroundColor = .blue
view2.alpha = 0.5
view3.backgroundColor = .blue
view3.alpha = 0.5
view.addSubview(view2)
view.addSubview(view3)
view2.translatesAutoresizingMaskIntoConstraints = false
view2.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 5).isActive = true
view2.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -5).isActive = true
view2.topAnchor.constraint(equalTo: view.topAnchor, constant: 25).isActive = true
view2.heightAnchor.constraint(equalToConstant: 30).isActive = true
view3.translatesAutoresizingMaskIntoConstraints = false
view3.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 5).isActive = true
view3.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -5).isActive = true
view3.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -25).isActive = true
view3.heightAnchor.constraint(equalToConstant: 30).isActive = true
}
public func getPopover(sourceView: UIView) {
modalPresentationStyle = .popover
let popoverPresentation = self.popoverPresentationController
popoverPresentation?.sourceView = sourceView
popoverPresentation?.sourceRect = sourceView.bounds
}
Related
I am working on a canvas view where I am trying to add image to a UIView and a text to a UIView, on satisfying some conditions.
The issue is, I am not able to add label to my UIView after satisfying the required condition. I tried this code separately without any functions and conditions and it is working fine. But if I try and run it as given below it doesn't show me the label on the UIView.
[Note- The code here is working fine for imageView.]
I tried various constraint combinations like, centerX, centerY, width, height or leading, trailing, top, bottom. But nothing is working. Please help.
My code is as below: -
class CanvasViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
createCanvasOnAspectRatio()
}
func createCanvasOnAspectRatio() {
let View1: UIView = {
let viewView = UIView()
viewView.translatesAutoresizingMaskIntoConstraints = false
viewView.contentMode = .scaleAspectFit
print(UserDefaults.standard.bool(forKey: "backgroundColourSelected"))
if UserDefaults.standard.bool(forKey: "backgroundColourSelected") {
viewView.backgroundColor = self.viewColor
}else {
viewView.backgroundColor = .white
}
viewView.clipsToBounds = true
return viewView
}()
self.canvasView.addSubview(View1)
View1.centerXAnchor.constraint(equalTo: canvasView.centerXAnchor, constant: 0).isActive = true
View1.centerYAnchor.constraint(equalTo: canvasView.centerYAnchor, constant: 0).isActive = true
View1.widthAnchor.constraint(equalTo: canvasView.widthAnchor, constant: 0).isActive = true
View1.heightAnchor.constraint(equalTo: canvasView.widthAnchor, multiplier: aspectRatio).isActive = true
if UserDefaults.standard.bool(forKey: "imageSelectedFromGallexy") == true {
for item in 0..<self.imagesForGallery.count {
let image = imagesForGallery[item]
let image_View: UIImageView = {
let imageV = UIImageView()
imageV.image = image
imageV.contentMode = .scaleAspectFill
imageV.translatesAutoresizingMaskIntoConstraints = false
imageV.clipsToBounds = true
return imageV
}()
View1.addSubview(image_View)
image_View.topAnchor.constraint(equalTo: View1.topAnchor, constant: 0).isActive = true
image_View.bottomAnchor.constraint(equalTo: View1.bottomAnchor, constant: 0).isActive = true
image_View.leadingAnchor.constraint(equalTo: View1.leadingAnchor, constant: 0).isActive = true
image_View.trailingAnchor.constraint(equalTo: View1.trailingAnchor, constant: 0).isActive = true
}
}
if UserDefaults.standard.bool(forKey: "addTextToCanvas") == true {
let labelTextView: UILabel = {
let labelView = UILabel()
//labelView.frame = CGRect(x: 0.0, y: 0.0, width: 50.0, height: 30.0)
labelView.translatesAutoresizingMaskIntoConstraints = false
labelView.textColor = .green
labelView.text = "Hello"
labelView.font = UIFont(name: "Avenir-Medium", size: 15.0)
labelView.textAlignment = .center
// labelView.clipsToBounds = true
return labelView
}()
View1.addSubview(labelTextView)
labelTextView.centerXAnchor.constraint(equalTo: View1.centerXAnchor, constant: 0).isActive = true
labelTextView.centerYAnchor.constraint(equalTo: View1.centerYAnchor, constant: 0).isActive = true
labelTextView.widthAnchor.constraint(equalTo: View1.widthAnchor, constant: 0).isActive = true
labelTextView.heightAnchor.constraint(equalTo: View1.widthAnchor, multiplier: 1.0).isActive = true
UserDefaults.standard.set(false, forKey: "addTextToCanvas")
}
}
}
I have spent a while trying to figure this out, but I just can't. There is probably something really simple I am missing here. I am trying to animate a view coming in from the bottom. This si the code I am using for the view:
private let undoView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .white
view.layer.cornerRadius = 15
view.layer.shadowOffset = .zero
view.layer.shadowOpacity = 0.3
view.layer.shadowRadius = 5
view.layer.shouldRasterize = true
view.layer.rasterizationScale = UIScreen.main.scale
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Undo", for: .normal)
button.titleLabel?.textAlignment = .center
button.setTitleColor(.systemBlue, for: .normal)
let buttonConstraints = [
button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
button.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
button.topAnchor.constraint(equalTo: view.topAnchor, constant: 16),
button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -16)
]
view.addSubview(button)
NSLayoutConstraint.activate(buttonConstraints)
let swipeGesture = UISwipeGestureRecognizer(target: view, action: #selector(undoViewSwiped))
view.addGestureRecognizer(swipeGesture)
return view
}()
And this is the code I am using to try and achieve the animation:
func addUndoView() {
var bottomConstraint = undoView.topAnchor.constraint(equalTo: view.bottomAnchor, constant: 0)
let constraints = [
undoView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
undoView.widthAnchor.constraint(equalToConstant: view.bounds.width / 3),
bottomConstraint,
undoView.heightAnchor.constraint(equalToConstant: 50)
]
view.addSubview(undoView)
NSLayoutConstraint.activate(constraints)
undoView.layoutIfNeeded()
bottomConstraint.isActive = false
bottomConstraint = undoView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor, constant: -58)
bottomConstraint.isActive = true
UIView.animate(withDuration: 0.5, delay: 0.2, animations: {
self.undoView.layoutIfNeeded()
})
}
I want the view to just be created underneath the visible view, and then slide up to 8 above the bottom layout margin. This code however just makes the view 'expand' at its final position instead of coming into view from the bottom. Using self.view.layoutIfNeeded() makes the view fly in from the top left of the screen, for some reason.
good day I usually work with transform property for move one view from x position to y portion, please check this example.
class ViewController: UIViewController {
let button : UIButton = {
let button = UIButton(type: .custom)
button.setTitle("Button", for: .normal)
button.backgroundColor = .gray
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let customView : UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .red
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(button)
view.addSubview(customView)
NSLayoutConstraint.activate([
button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
customView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
customView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
customView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
customView.heightAnchor.constraint(equalToConstant: 100)
])
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
setupAnimationCustomView()
}
private func setupAnimationCustomView(){
UIView.animate(withDuration: 1, delay: 0 , options: .curveEaseOut, animations: {
print(self.button.frame.origin.y)
let translationY = self.view.frame.height - self.button.frame.origin.y - self.button.frame.height - self.customView.frame.height - 8
self.customView.transform = CGAffineTransform(translationX: 0, y: translationY * (-1))
}, completion: nil)
}
}
on the animation I calculate the distance that I need to move my customView.
I am working on a "Profile View Controller" which is inside a TableViewCell and table cell dimension is set as UITableView.automaticDimension:
The problem is that I would like to set the background image view (Blue) with a variable height based on cell width and a 16:9 ratio. For some reason I am not being able to change the view height even if I set the constant.
Here the code:
let topView : UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 20
view.backgroundColor = .yoofitDarkBlue
view.layer.masksToBounds = true
view.layer.shadowColor = UIColor.lightGray.cgColor
view.layer.borderWidth = 0.5
view.layer.borderColor = UIColor.yoofitDarkBlue.cgColor
view.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
view.layer.shadowRadius = 12.0
view.layer.shadowOpacity = 0.7
return view
}()
let userImage : UIImageView = {
let i = UIImageView()
i.translatesAutoresizingMaskIntoConstraints = false
i.image = UIImage(named: "user2")
i.layer.masksToBounds = true
i.layer.cornerRadius = 75
i.layer.borderWidth = 1
i.layer.borderColor = UIColor.white.cgColor
return i
}()
var userNameLabel:UILabel = {
let l = UILabel()
l.translatesAutoresizingMaskIntoConstraints = false
l.font = UIFont(name: "AvenirNext-DemiBold", size: 20)
l.textAlignment = .center
l.textColor = .yoofitBlack
return l
}()
func setupViews() {
self.backgroundColor = .clear
self.selectionStyle = .none
addSubview(topView)
let width = self.frame.width
print(width) // print 320
topView.topAnchor.constraint(equalTo: topAnchor, constant: 10).isActive = true
topView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
topView.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
topView.heightAnchor.constraint(equalToConstant: width/16*9).isActive = true // this doesn't work even if I set another number like 600
topView.layoutIfNeeded()
addSubview(userImage)
userImage.centerYAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true
userImage.centerXAnchor.constraint(equalTo: topView.centerXAnchor).isActive = true
userImage.widthAnchor.constraint(equalToConstant: 150).isActive = true
userImage.heightAnchor.constraint(equalToConstant: 150).isActive = true
addSubview(userNameLabel)
userNameLabel.topAnchor.constraint(equalTo: userImage.bottomAnchor, constant: 10).isActive = true
userNameLabel.centerXAnchor.constraint(equalTo: userImage.centerXAnchor).isActive = true
userNameLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
userNameLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
userNameLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -20).isActive = true
}
PLEASE NOTE THERE ARE 2 answers to this question. The latter is definitely the correct one but the first maybe may help others.
So this is how I fixed it but I hope to get better answers. This answer helped me to go to the right path (iOS: How to Align The Center of a View With The Bottom of Another View With AutoLayout)
I have added a containing view which is twice as the required size of my top view (the blue one).
I centered the picture on the containing view.
self.conteiningView.backgroundColor = .red // I made this red so you can visually see how the views are related to each other
let width = self.frame.width
self.addSubview(conteiningView)
conteiningView.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = true
conteiningView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
conteiningView.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
conteiningView.heightAnchor.constraint(equalToConstant: (width/16*9)*2).isActive = true // twice of the blue view
conteiningView.layoutIfNeeded()
self.conteiningView.addSubview(topView)
topView.topAnchor.constraint(equalTo: conteiningView.topAnchor).isActive = true
topView.leftAnchor.constraint(equalTo: conteiningView.leftAnchor).isActive = true
topView.rightAnchor.constraint(equalTo: conteiningView.rightAnchor).isActive = true
topView.heightAnchor.constraint(equalToConstant: width/16*9).isActive = true // 16:9 ration
conteiningView.addSubview(userImage)
userImage.centerYAnchor.constraint(equalTo: conteiningView.centerYAnchor).isActive = true
userImage.centerXAnchor.constraint(equalTo: conteiningView.centerXAnchor).isActive = true
userImage.widthAnchor.constraint(equalToConstant: width/2).isActive = true
userImage.heightAnchor.constraint(equalToConstant: width/2).isActive = true
userImage.layer.cornerRadius = width/4 // to mantain nice proportions
conteiningView.addSubview(userNameLabel)
userNameLabel.topAnchor.constraint(equalTo: userImage.bottomAnchor, constant: 10).isActive = true
userNameLabel.centerXAnchor.constraint(equalTo: userImage.centerXAnchor).isActive = true
userNameLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
userNameLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
With red background:
With clear background:
UPDATE: The answer above works but I have actually found the problem:
Even if I had set:
self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = 300
For some (silly me) I had also implemented:
tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
This, of course, does not be implemented for the automatic dimension to work.
removing that allowed to use the following code to achieve the same result but without setting a predefined height:
self.addSubview(conteiningView)
conteiningView.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = true
conteiningView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
conteiningView.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
conteiningView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
conteiningView.layoutIfNeeded()
self.conteiningView.addSubview(topView)
topView.topAnchor.constraint(equalTo: conteiningView.topAnchor).isActive = true
topView.leftAnchor.constraint(equalTo: conteiningView.leftAnchor).isActive = true
topView.rightAnchor.constraint(equalTo: conteiningView.rightAnchor).isActive = true
topView.heightAnchor.constraint(equalToConstant: width/16*9).isActive = true
conteiningView.addSubview(userImage)
userImage.centerYAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true // the vertical center is now set nicely at bottom edge of my top view.
userImage.centerXAnchor.constraint(equalTo: topView.centerXAnchor).isActive = true
userImage.widthAnchor.constraint(equalToConstant: width/2).isActive = true
userImage.heightAnchor.constraint(equalToConstant: width/2).isActive = true
userImage.layer.cornerRadius = width/4
conteiningView.addSubview(userNameLabel)
userNameLabel.topAnchor.constraint(equalTo: userImage.bottomAnchor, constant: 2).isActive = true
userNameLabel.centerXAnchor.constraint(equalTo: userImage.centerXAnchor).isActive = true
userNameLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
userNameLabel.heightAnchor.constraint(equalToConstant: 35).isActive = true
Conditions:
Swift 4, Xcode 9.3
Target: iOS 11.3
UI Done Programatically
Using Constraints
My Root View Controller is a Navigation
Situation:
I wanted to float an audio player that will be visible throughout the app.
I did an AudioPlayer.swift class that contains the user interface of the audio player.
AudioPlayer.swift
import Foundation
import UIKit
import FRadioPlayer
class AudioPlayer: UIView {
let screenSize: CGRect = UIScreen.main.bounds
let playerImage: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.layer.masksToBounds = true
return iv
}()
let playerTitle: UILabel = {
let l = UILabel()
l.textColor = .darkGray
l.font = UIFont.boldSystemFont(ofSize: 13)
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
let playerSeriesTitle: UILabel = {
let l = UILabel()
l.textColor = .darkGray
l.font = UIFont.boldSystemFont(ofSize: 12)
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
override init(frame: CGRect) {
super.init(frame: frame)
translatesAutoresizingMaskIntoConstraints = false
setupAudioControls()
}
private func setupAudioControls(){
let appDelegate = AppDelegate.sharedInstance
self.backgroundColor = UIColor.init(hex: "#EBE4D3")
self.addSubview(playerImage)
self.addSubview(playerTitle)
self.addSubview(playerSeriesTitle)
self.heightAnchor.constraint(equalToConstant: 150).isActive = true
self.bottomAnchor.constraint(equalTo: appDelegate().rootView ).isActive = true
self.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor).isActive = true
self.trailingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.trailingAnchor).isActive = true
playerImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
playerImage.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10).isActive = true
playerImage.widthAnchor.constraint(equalToConstant: 55).isActive = true
playerImage.heightAnchor.constraint(equalToConstant: 55).isActive = true
playerTitle.topAnchor.constraint(equalTo: self.topAnchor, constant: 5).isActive = true
playerTitle.leadingAnchor.constraint(equalTo: playerImage.trailingAnchor, constant: 10).isActive = true
playerTitle.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 10).isActive = true
playerTitle.heightAnchor.constraint(equalToConstant: 25).isActive = true
playerSeriesTitle.topAnchor.constraint(equalTo: playerTitle.topAnchor, constant: 20).isActive = true
playerSeriesTitle.leadingAnchor.constraint(equalTo: playerImage.trailingAnchor, constant: 10).isActive = true
playerSeriesTitle.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 10).isActive = true
playerSeriesTitle.heightAnchor.constraint(equalToConstant: 20).isActive = true
UIView.animate(withDuration: 0.5, animations: {
self.frame.origin.y -= 150
self.playerImage.frame.origin.y -= 150
self.playerTitle.frame.origin.y -= 150
self.playerSeriesTitle.frame.origin.y -= 150
}, completion: nil)
self.setNeedsLayout()
self.reloadInputViews()
}
}
Problem:
How can I add this to the Root View Controller to stay on top in all view controllers that I have in my app? Wherever I navigate, the player must stay on the bottom part of every controller. As you can see, I need a reference to the rootviewcontroller to set the contraints for the AudioPlayer but I failed in so many attempts (like calling the rootviewcontroller using AppDelegate)
I update it for you
add singleton static let shared = AudioPlayer()
add public func showAudioPlayer () --> to display Audio player
add as subview to UIApplication.shared.keyWindow?
TODO- add HideAudioPlayer()
Use like this
AudioPlayer.shared.showAudioPlayer()
Here is updated code
import Foundation
import UIKit
class AudioPlayer: UIView {
static let shared = AudioPlayer()
let screenSize: CGRect = UIScreen.main.bounds
let playerImage: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.layer.masksToBounds = true
return iv
}()
let playerTitle: UILabel = {
let l = UILabel()
l.textColor = .darkGray
l.font = UIFont.boldSystemFont(ofSize: 13)
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
let playerSeriesTitle: UILabel = {
let l = UILabel()
l.textColor = .darkGray
l.font = UIFont.boldSystemFont(ofSize: 12)
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
override init(frame: CGRect) {
super.init(frame: frame)
translatesAutoresizingMaskIntoConstraints = false
// setupAudioControls()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func showAudioPlayer (){
self.setupAudioControls()
}
private func setupAudioControls(){
self.backgroundColor = .red
self.addSubview(playerImage)
self.addSubview(playerTitle)
self.addSubview(playerSeriesTitle)
UIApplication.shared.keyWindow?.addSubview(self)
if let layoutGuide = UIApplication.shared.keyWindow?.layoutMarginsGuide {
self.heightAnchor.constraint(equalToConstant: 150).isActive = true
self.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor ).isActive = true
self.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
self.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
}
playerImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
playerImage.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10).isActive = true
playerImage.widthAnchor.constraint(equalToConstant: 55).isActive = true
playerImage.heightAnchor.constraint(equalToConstant: 55).isActive = true
playerTitle.topAnchor.constraint(equalTo: self.topAnchor, constant: 5).isActive = true
playerTitle.leadingAnchor.constraint(equalTo: playerImage.trailingAnchor, constant: 10).isActive = true
playerTitle.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 10).isActive = true
playerTitle.heightAnchor.constraint(equalToConstant: 25).isActive = true
playerSeriesTitle.topAnchor.constraint(equalTo: playerTitle.topAnchor, constant: 20).isActive = true
playerSeriesTitle.leadingAnchor.constraint(equalTo: playerImage.trailingAnchor, constant: 10).isActive = true
playerSeriesTitle.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 10).isActive = true
playerSeriesTitle.heightAnchor.constraint(equalToConstant: 20).isActive = true
UIView.animate(withDuration: 0.5, animations: {
self.frame.origin.y -= 150
self.playerImage.frame.origin.y -= 150
self.playerTitle.frame.origin.y -= 150
self.playerSeriesTitle.frame.origin.y -= 150
}, completion: nil)
self.setNeedsLayout()
self.reloadInputViews()
}
}
If you want to show view in each view controller then as per view hierarchy you must have to add in UIWindow. UIWindow is base of all screen.
AppDelegate.shared.window?.addSubview(AudioPlayer)
You can add your view to UIWindow.
I am doing the same thing with below method in AppDelegate.
var window: UIWindow?
func addPlayerViewAtBottom() {
var bottomView : PlayerBottomView!
bottomView = PlayerBottomView(frame: CGRect(x: 0, y: UIScreen.main.bounds.size.height - 60, width: UIScreen.main.bounds.width, height: 60))
self.window?.addSubview(bottomView)
self.window?.bringSubview(toFront: bottomView)
}
This is new to me so forgive me if I'm not asking the right question.
I'm following a tutorial where we are creating a few subviews inside of a titleview for the navigation bar so that a picture and username displays. When I create the intial titleview with a red background, it shows up as expected. However, when I add a container subview to place the text and image, the red titleview disappears. I finished the tutorial and the text shows up in the right place, but it doesn't allow me to add a tap gesture, since the titleview isn't there anymore to tap?
I'll add my code for this function- hopefully there's a stupid mistake that I'm missing.
func setupNavBarWithUser(user: User) {
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 130, height: 35)
titleView.backgroundColor = UIColor.red
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = UIColor.blue
titleView.addSubview(containerView)
let profileImageView = UIImageView()
profileImageView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.contentMode = .scaleAspectFill
profileImageView.layer.cornerRadius = 20
profileImageView.clipsToBounds = true
if let profileImageUrl = user.profileImageUrl {
profileImageView.loadImageUsingCacheWithUrlString(urlString: profileImageUrl)
}
containerView.addSubview(profileImageView)
profileImageView.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true
profileImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 35).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 35).isActive = true
let nameLabel = UILabel()
containerView.addSubview(nameLabel)
nameLabel.text = user.name
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.leftAnchor.constraint(equalTo: profileImageView.rightAnchor, constant: 8).isActive = true
nameLabel.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
nameLabel.rightAnchor.constraint(equalTo: containerView.rightAnchor).isActive = true
nameLabel.heightAnchor.constraint(equalToConstant: 40).isActive = true
containerView.centerXAnchor.constraint(equalTo: titleView.centerXAnchor).isActive = true
containerView.centerYAnchor.constraint(equalTo: titleView.centerYAnchor).isActive = true
self.navigationItem.titleView = titleView
titleView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(showChatController)))
titleView.isUserInteractionEnabled = true
}
Replace setupNavBarWithUser method with this:
func setupNavBarWithUser(user: User) {
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 130, height: 45)
titleView.backgroundColor = UIColor.red
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = UIColor.blue
self.navigationItem.titleView = titleView
titleView.addSubview(containerView)
containerView.topAnchor.constraint(equalTo: titleView.topAnchor, constant: 0).isActive = true
containerView.bottomAnchor.constraint(equalTo: titleView.bottomAnchor, constant: 0).isActive = true
containerView.leadingAnchor.constraint(equalTo: titleView.leadingAnchor, constant: 0).isActive = true
containerView.trailingAnchor.constraint(equalTo: titleView.trailingAnchor, constant: 0).isActive = true
let profileImageView = UIImageView()
profileImageView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.contentMode = .scaleAspectFill
profileImageView.layer.cornerRadius = 20
profileImageView.clipsToBounds = true
if let profileImageUrl = user.profileImageUrl {
profileImageView.loadImageUsingCacheWithUrlString(urlString: profileImageUrl)
}
containerView.addSubview(profileImageView)
profileImageView.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true
profileImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 35).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 35).isActive = true
let nameLabel = UILabel()
containerView.addSubview(nameLabel)
nameLabel.text = user.name
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.leftAnchor.constraint(equalTo: profileImageView.rightAnchor, constant: 8).isActive = true
nameLabel.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
nameLabel.rightAnchor.constraint(equalTo: containerView.rightAnchor).isActive = true
nameLabel.heightAnchor.constraint(equalToConstant: 40).isActive = true
self.navigationItem.titleView = titleView
titleView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(showChatController)))
titleView.isUserInteractionEnabled = true
}
You can compare the codes. As you can see you have to add subview in a proper order to set your constraints.