Is it possible to display an UIView on top of a container View?
I want to add a view with a few opacity background to still see my container View. But everything i tried made either my containerView disappear completely or on top of my View. I tried via Storyboard and code.
I'm sure I'm missing something.
just add your view to the view property of your container controller's container
simple:
let viewYouWantToAddSubviewTo = parent?.view
detail:
import UIKit
class CustomNavigationViewController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
func setupViews() {
let layout = UICollectionViewFlowLayout()
let rootVC = HomeCollectionViewController(collectionViewLayout: layout)
viewControllers = [rootVC]
let v = UIView()
v.backgroundColor = UIColor.blue
v.layer.opacity = 0.4
v.translatesAutoresizingMaskIntoConstraints = false
// add your view to this view of the controller's container
let vv = (parent?.view)!
vv.addSubview(v)
// constraints for v
v.leftAnchor.constraint(equalTo: vv.leftAnchor).isActive = true
v.rightAnchor.constraint(equalTo: vv.rightAnchor).isActive = true
v.topAnchor.constraint(equalTo: vv.topAnchor).isActive = true
v.bottomAnchor.constraint(equalTo: vv.bottomAnchor).isActive = true
}
}
result:
Related
So I found the following UI pattern online and I have been attempting to implement it in Xcode. However, I have been unsuccessful. I am unsure as to whether to create the optimal approach would be to
create three different UIViewControllers (in which case I am not sure as to how to get them to animate in and out of view/how to get them to overlap one another)
or to use a UITableView with custom overlapping cells. However, I am not sure whether this approach will allow me to animate properly upon pressing each cell. For this second approach, I saw this post, but this solution does not allow for touch interaction in the overlapping areas, something which I need.
I looked for libraries online that would allow for functionality such as this, but I was unsuccessful in finding any. The animation I am trying to achieve can be found here.
I would use a StackView to hold all the views of your ViewControllers.
Then you can set the stack view's spacing property to a negative value to make the views overlap. If you wish show the complete view of one of the view controllers on tap, you add a tap gesture recognizer to that view that changes the stackView's spacing for just that view to 0.
A really simple example:
class PlaygroundViewController: UIViewController {
let firstViewController = UIViewController()
let secondViewController = UIViewController()
let thirdViewController = UIViewController()
lazy var viewControllersToAdd = [firstViewController, secondViewController, thirdViewController]
let heightOfView: CGFloat = 300
let viewOverlap: CGFloat = 200
let stackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
firstViewController.view.backgroundColor = .red
secondViewController.view.backgroundColor = .blue
thirdViewController.view.backgroundColor = .green
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.spacing = -viewOverlap
viewControllersToAdd.forEach { (controller: UIViewController) in
if let childView = controller.view {
stackView.addArrangedSubview(childView)
NSLayoutConstraint.activate([
childView.heightAnchor.constraint(equalToConstant: heightOfView),
childView.widthAnchor.constraint(equalTo: stackView.widthAnchor)
])
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapChildView(sender:)))
childView.addGestureRecognizer(gestureRecognizer)
childView.isUserInteractionEnabled = true
}
addChild(controller)
controller.didMove(toParent: self)
}
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.rightAnchor.constraint(equalTo: view.rightAnchor),
stackView.leftAnchor.constraint(equalTo: view.leftAnchor),
stackView.topAnchor.constraint(equalTo: view.topAnchor),
])
}
#objc func didTapChildView(sender: UITapGestureRecognizer) {
if let targetView = sender.view {
UIView.animate(withDuration: 0.3, animations: {
let currentSpacing = self.stackView.customSpacing(after: targetView)
if currentSpacing == 0 {
// targetView is already expanded, collapse it
self.stackView.setCustomSpacing(-self.viewOverlap, after: targetView)
} else {
// expand view
self.stackView.setCustomSpacing(0, after: targetView)
}
})
}
}
}
I want to stop the user interacting with a tableview while I get some data.
So I can show and remove a view such that:
var dimmingView: UIView?
Is added and removed with:
func showLoading() {
let dimmingView = UIView(frame: view.frame)
dimmingView.backgroundColor = .darkGray
view.addSubview(dimmingView)
let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
dimmingView.addSubview(activityIndicator)
NSLayoutConstraint.activate([
activityIndicator.centerXAnchor.constraint(equalTo: dimmingView.centerXAnchor),
activityIndicator.centerYAnchor.constraint(equalTo: dimmingView.centerYAnchor)
])
activityIndicator.startAnimating()
self.dimmingView = dimmingView
}
And also
func removeLoading() {
dimmingView?.removeFromSuperview()
}
However, when added it moves along with the table (scrolls). If I stop the table scrolling when the new data is loaded it presents behind the UINavigationBar (the first cell at least). If I try to add to the navigationcontroller.view navigation.controller is nil (so I can't).
What is the best approach?
Edit1: I am not using a storyboard everything has been added programmatically
Edit2: Updated code snippet
Hello, i've got the following issues with UICollectionView
The CollectionView won't allow you to scroll no matter what you do.
Sometimes the cells even disappear complete leaving you with a white background CollectionView.
The problem occurs when you try to scroll up to view the cells that are not visible.
I've create a CollectionView which has different type of cells.
The CollectionView is nested inside a ViewController below an ImageView.
Constraints are added and they work just fine.
How do i make it scrollable?
GIF representing the problem
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationItem.title = "Featured"
self.view.backgroundColor = UIColor.white
// Add UImage carousel
let carousel: UIImageView = {
let imageView = UIImageView()
let image = UIImage()
imageView.backgroundColor = UIColor.purple
return imageView
}()
self.view.addSubview(carousel)
carousel.translatesAutoresizingMaskIntoConstraints = false
// Add CollectionView
let featuredControllerLayout = UICollectionViewFlowLayout()
// Add CollectionViewController
featuredControllerLayout.scrollDirection = .vertical
let featuredController = FeaturedCollectionViewController(collectionViewLayout: featuredControllerLayout)
guard let featuredView = featuredController.collectionView else { return }
self.view.addSubview(featuredView)
featuredView.translatesAutoresizingMaskIntoConstraints = false
// Setup Constraints
if #available(iOS 11.0, *) {
let guide = self.view.safeAreaLayoutGuide
let guideSize = guide.layoutFrame.size
carousel.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
carousel.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
carousel.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
carousel.frame.size.height = guideSize.width/2
carousel.heightAnchor.constraint(equalToConstant: carousel.frame.size.height).isActive = true
featuredView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
featuredView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
featuredView.topAnchor.constraint(equalTo: carousel.bottomAnchor).isActive = true
featuredView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
}
}
Heyy what you are telling is you are not able to scroll up and see the entire collection view items ?
if that is the case then you have not accounted the height of tabbar controller so you can enable translucent for example I have a git repo I made you can check and let me know if you are stuck anywhere
https://github.com/dwivediashish00/socialApp
I am trying to see how i can add a UIView under my UITabBarController so i can add ads to my app, I cant seem to figure out any way to constrain my UIView to the bottom of the tab bar. Is this possible?
EDIT: By bottom of the tab bar i mean below the tab bar
Try this add see:
Follow these steps to achieve it:
Add UIViewController in root of your storyboard
Add Container View inside UIViewController
Add AdView below Container view
Embed UITabbarController with Container view
I was able to create a UIView in my UITabBarController
lazy var bannerAd: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .black
return view
}()
And then pin it to the bottom like so:
view.addSubview(bannerAd)
bannerAd.heightAnchor.constraint(equalToConstant: 44).isActive = true
bannerAd.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
bannerAd.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
then to move up the Tab Bar i did so like this:
override func viewWillLayoutSubviews() {
if !didStyleTabBar {
self.tabBar.invalidateIntrinsicContentSize()
var tabFrame = self.tabBar.frame
tabFrame.size.height = tabBarHeight
tabFrame.origin.y = tabFrame.origin.y - 44
self.tabBar.frame = tabFrame
didStyleTabBar = true
}
}
So I've seen other SO questions but I can't really figure out mine
I know my UIScrollView code works because I tested it in a regular UIViewController so I don't think contentSize is the problem, but when I place the same code inside a UICollectionReusableView it doesn't scroll anymore
-Working in UIViewController
override func viewDidLoad() {
super.viewDidLoad()
let scrollingView = colorButtonsView(buttonSize: CGSize(width:100.0,height:50.0), buttonCount: 10)
let scrollView = UIScrollView(frame: UIScreen.main.bounds)
scrollView.backgroundColor = UIColor.black
scrollView.contentSize = scrollingView.frame.size
scrollView.showsHorizontalScrollIndicator = true
self.view.addSubview(scrollView)
scrollView.addSubview(scrollingView)
}
-Not working in UICollectionReusableView
override init(frame: CGRect) {
super.init(frame: frame)
//Add category scroll view
let scrollingView = colorButtonsView(buttonSize: CGSize(width:100.0,height:50.0), buttonCount: 10)
let scrollView = UIScrollView(frame: UIScreen.main.bounds)
scrollView.backgroundColor = UIColor.black
scrollView.contentSize = scrollingView.frame.size
scrollView.showsHorizontalScrollIndicator = true
self.addSubview(scrollView) //Only changes self.view to self
scrollView.addSubview(scrollingView)
}
Better late than never...I had the same problem, so maybe this is why;
I wanted to put a UIScrollView inside a UICollectionReusableView but by accident I had created my custom class as;
class CustomCellHeader: UICollectionViewCell {
}
instead of;
class CustomCellHeader: UICollectionReusableView {
}
Once I changed that, the UIScrollView within my header cell came to life!