place NavigationBar subview behind the NavigationBarItem and title - swift

I want to add a view below everything that's on the navigationBar. I need to add them as subviews to my NavigationBar so that they appear on any detail ViewController.
Here is what I tried so far inside my custom NavigationBar subclass (I call this method inside layoutSubviews()):
private var backgroundView = UIView()
backgroundView.frame = CGRect(x: 0, y: 0, width: 100, height: 70)
backgroundView.backgroundColor = .blue
backgroundView.alpha = 0.7
self.insertSubview(backgroundView, at: 0)
And this is what I get:
The backgroundView appears on top of the title and the NavigationBarItem.
What can I do?

According to this post on the apple developer forum, you can do this inside the NavigationBar class (which works!):
self.subviews[0].insertSubview(backgroundView, at: 0)

Related

How to make UINavigationBar shadowImage fixed?

I have a reversed UITableView:
tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi))
NavigationBar setup:
navigationBar.shadowImage = UIImage()
navigationBar.layer.masksToBounds = false
navigationBar.layer.shadowColor = Assets.Colors.black.color.withAlphaComponent(0.2).cgColor
navigationBar.layer.shadowOpacity = 0.7
navigationBar.layer.shadowOffset = CGSize(width: 0, height: 2.0)
navigationBar.layer.shadowRadius = 5
navigationBar.isTranslucent = false
view.backgroundColor = color
Whenever I scroll to the bottom of my TableView (to the top when inverted), shadow disappears. I want it to be constant (like at the second screenshot).
Is it possible to make UINavigationBar shadow static regardless of TableView scrolling?
How it looks now:
No shadow
How it should be:
With shadow
In iOS15/Xcode13, there is a common problem with the navigation bar's appearance. You can read more here and apply the fixes.

UICollectionView not scrolling after custom UIView added to view

I'm trying to add a custom UIView after adding a UICollectionView because I wanna show the custom bar view above the collection view. This is my code:
func loadFilters() {
let categoriesFlowLayout = UICollectionViewFlowLayout()
categoriesFlowLayout.scrollDirection = .vertical
categoriesCollection = UICollectionView(frame: CGRect(x: 10, y: getY(yAxis: searchField) + 10, width: view.frame.size.width - 20, height: (view.frame.size.height * 9 / 10) - getY(yAxis: searchField) - 10), collectionViewLayout: categoriesFlowLayout)
categoriesCollection.register(categoriesCell.self, forCellWithReuseIdentifier: "categoriesCell")
categoriesCollection.delegate = self
categoriesCollection.dataSource = self
categoriesCollection.backgroundColor = UIColor.clear
categoriesCollection.showsVerticalScrollIndicator = false
categoriesCollection.showsHorizontalScrollIndicator = false
view.addSubview(categoriesCollection)
addBar()
categoriesCollection.isUserInteractionEnabled = true
}
The addBar() function is declared in the custom superclass ViewController
if addBar() is called before view.addSubview(categoriesCollection) it looks like the image below but if it is called after then my collection view does not scroll or recognize touches. Is there anyway that will make the collection view scroll and bring the custom bar to front?
I've used sendSubviewToBack() and bringSubviewToFront() functions as well but the result is the same
When you insert a view above another view, the top view gets all touch events. So the UICollectionView does not receive any touch events anymore since another view is above it.
As I see from your post, you just want the bar at the bottom of the screen. So check the size of your custom UIView. It probably fills the entire screen and is completely above the UICollectionView. Just give the UIView some sort of background color and see, how much space it fills.
If this doesn't work, you can use a UIGestureRecognizer on the custom UIView and forward the touch events to the UICollectionView.

How to set an image as title in all navigation bars in swift?

I need to know if it is possible to add an image as title on all navigation controllers, this mean, that every controller that had a navigation bar had the same image title.
I used the next code to set an image as title in the navigation bar, but I have to set it on every viewController, the idea its for example set it on AppDelegate as UINavigationBar.appereance() or similar.
let imageView = UIImageView(image: UIImage(named: "my_image.png")!)
imageView.contentMode = .scaleAspectFit
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 107, height: 30))
imageView.frame = titleView.bounds
titleView.addSubview(imageView)
self.navigationItem.titleView = titleView
So the idea is to set this image as the default title for every controller, that way I will just need to configure it one time.
It is that posible? If not, What possible solution do you think that I can apply ?
The title view is a property of each view controller, not the navigation bar or navigation controller.
So start with a UIViewController subclass whose navigation item has this title view, and make all your other view controllers be subclasses of that.
Please try below code,
let logo = UIImage(named: "logo.png")
let imageView = UIImageView(image:logo)
self.navigationItem.titleView = imageView
if this not works please share the screenshot.

Swift 4 upgrade issue with imageViews as bar buttons within navigation bar

So I have upgraded to swift 4 and now my left & right uiimageviews set as left/right nav button items are showing as large icons. I have figured out that the Frame setting is not being applied and I am not sure why.
Does anyone know what may cause this?
Here is some code
lazy var leftBarPic: UIImageView = {
let pic = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 25))
pic.clipsToBounds = true
pic.contentMode = .scaleAspectFit
pic.image = myImage.withRenderingMode(.alwaysOriginal)
pic.isUserInteractionEnabled = true
pic.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(postNewsAction)))
pic.backgroundColor = .green
return pic
}()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: leftBarPic)
}
OK I found a fix. For anyone having similar, what I did was add the property (in this instance the left navigator imageView) to the view's subview. Then added the constraints for width and height. It seems that with the upgrade setting the frame for nav items (image views only) inside the property does not work.

UITableView cell background

I tried using the code below for setting the background for cells. It works fine but it obscures the disclosure indicator. How do I pull the disclosure indicator forward so that it is visible?
cell.backgroundColor = UIColor.clearColor()
let imageView = UIImageView(frame: CGRectMake(0, 0, cell.frame.width, cell.frame.height))
let image = UIImage(named: "sand background 1.png")
imageView.image = image
imageView.alpha = 0.5
cell.addSubview(imageView)
cell.sendSubviewToBack(imageView)
When I do this, the disclosure shows up fine. I'd personally do insertSubview(atIndex: 0) rather than addSubview and sendSubviewToBack if I wanted to manually add the background image view in the view hierarchy manually. Or, I would just set the cell's backgroundView (and selectedBackgroundView). But all of these approaches have the disclosure indicator visible (assuming that the disclosure indicator was turned on) for me. I'd run the app and then use the view debugger and carefully examine the view hierarchy and confirm that the disclosure indicator is really there:
You can then select the debug navigator in the left panel and choose the "View UI Hierarchy" from the button in the top right corner of the debug navigator:
This way you can confirm that the disclosure button is really there, or whether the disclosure indicator is simply not visible (e.g. its color might be too close to your sand-colored background to stand out).
If the problem is that the color of the accessory view is too similar to the background color, you can change the accessory view (see https://stackoverflow.com/a/27971576/1271826). For some accessory types (namely the details or checkmarks), you can change the color simply by changing the tintColor of the tableview. If you want to change the color of the disclosure indicator, you may have to replace the accessory view with a disclosure image that you created yourself, e.g.:
cell.accessoryView = UIImageView(image: accessoryImage)
You can either build this accessory image and add it as an asset to your project, or you can define an accessory image that you build dynamically. For example, here is a yellow disclosure accessory image:
lazy var accessoryImage: UIImage = {
let rect = CGRect(x: 0, y: 0, width: 10, height: 43.5)
let insetRect = CGRectInset(rect, 2, 15)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
UIColor(red: 1, green: 1, blue: 0, alpha: 1).setStroke()
let path = UIBezierPath()
path.moveToPoint(CGPoint(x: insetRect.origin.x, y: insetRect.origin.y))
path.addLineToPoint(CGPoint(x: insetRect.origin.x + insetRect.size.width, y: insetRect.size.height / 2.0 + insetRect.origin.y))
path.addLineToPoint(CGPoint(x: insetRect.origin.x, y: insetRect.size.height + insetRect.origin.y))
path.lineWidth = 2
path.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}()
That yields: