Adding view controller in scrollview - swift

I am currently working on an app that has been developed using storyboards.
I am trying to add a view controller programmatically into a paging scroll view at the beginning before 2 other views that are already added within the storyboard.
The view controller gets added but the width is slightly larger and goes across into the middle view.
let vc = Vc()
scrollView.addSubview(vc.view)

You have to assign a contentSize to the scrollview and a position for the frame of the ViewController
scrollView.contentSize = CGSize(width: 2 * view.frame.width, height: scrollView.frame.height)
let frameVC = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
vc.view.frame = frameVC
vc.willMoveToParentViewController(self)
self.addChildViewController(vc)
vc.didMoveToParentViewController(self)
scrollView.addSubview(vc.view)
Note that you have to change the frameVC to match your requirements
Swift 5 sytax update
scrollView.contentSize = CGSize(width: 2 * view.frame.width, height: scrollView.frame.height)
let frameVC = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
vc.view.frame = frameVC
vc.willMove(toParent: self)
addChild(vc)
vc.didMove(toParent: self)
scrollView.addSubview(vc.view)
Note: Frames vs Constraint layout
Instead of using a frame you can also use create a constraint layout to add a UIView to a UIScrollView
scrollView.contentSize = CGSize(width: 2 * view.frame.width, height: scrollView.frame.height)
scrollView.addSubview(vc.view)
vc.view.translatesAutoresizingMaskIntoConstraints = false
// add constrains here
vc.willMove(toParent: self)
addChild(vc)
vc.didMove(toParent: self)

Related

UIView does not change colors after setting backgroundColor programmatically

I'm creating a subview to add onto an existing view. I'm trying to assign the background color to this subview to red programmatically but displays as the defaulted color still.
let toggleView = UIView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight))
toggleView.backgroundColor = UIColor.red
As from the above code snippet it looks like that you are creating a view but not adding it as a subview to the parent view. It will be best if you can provide full function so that we can look into the actual cause.
You have created the toggleView with a red background but you have not added it to the main view, this is what you should do:
let screenWidth = view.frame.size.width
let screenHeight = view.frame.size.height
let toggleView = UIView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight))
toggleView.backgroundColor = UIColor.red
view.addSubview(toggleView)

UIImage in a UIcollectonView issue

I am trying to add a UIImage to the UICollectionViewController by using the following code:
let backgroundImage = UIImageView(frame: CGRect(x: 0, y: 0, width: 430, height: 550))
backgroundImage.image = UIImage(named: "fantasy_football_hero_tile_cropped.png")
backgroundImage.contentMode = UIView.ContentMode.scaleAspectFit
backgroundImage.clipsToBounds = true
self.view.insertSubview(backgroundImage, at: 0)
My issue is that the image is not at the bottom/lowest part of the screen which is what I am trying to achieve... how can I clip it to the bottom?! I am not using story board, can I programmatically anchor the image to the bottom as I could do in a storyboard?
This is especially true since the screen sizes for the phones are different, but the desire is still to have it anchored to the bottom.
you can add programatically. I think you add/insert some views to the self.view that will also affect simple scenario
let backgroundImageV = UIView(frame: CGRect(x: 0, y: 0, width: 430, height: 500))
backgroundImageV.backgroundColor = UIColor.blue
backgroundImageV.contentMode = UIView.ContentMode.scaleAspectFit
backgroundImageV.clipsToBounds = true
self.view.addSubview(backgroundImageV)
let backgroundImageV2 = UIView(frame: CGRect(x: 0, y: 0, width: 430, height: 510))
backgroundImageV2.backgroundColor = UIColor.green
backgroundImageV2.contentMode = UIView.ContentMode.scaleAspectFit
backgroundImageV2.clipsToBounds = true
self.view.insertSubview(backgroundImageV2, at: 0)
let backgroundImage = UIImageView(frame: CGRect(x: 0, y: 0, width: 430, height: 550))
backgroundImage.backgroundColor = UIColor.red
backgroundImage.contentMode = UIView.ContentMode.scaleAspectFit
backgroundImage.clipsToBounds = true
self.view.insertSubview(backgroundImage, at: 0)
Here Red will be bottom Green will be in 1. because you add that red colored view later. So It will work. Can you please show your full code. It will work
One problem here is that self.view for a UICollectionViewController is the UICollectionView. This is a scroll view, so no matter where you put this image view, it is going to move when the scroll view scrolls.
If that isn't what you want, there is a simple solution: set the image view as the collection view's backgroundView. That is a stationary view that forms the background to the collection view no matter how it is scrolled. If you set the image view's contentMode to bottom the image will be centered at the bottom, which seems to be what you are after.

Resize image view in swift

I need to programaticaly move an image view based on some conditions in my app. I do this by using CGAFfineTransform. However, after I move my view and try to resize it to fill in the resulting gap, the view doesn't resize. What can I do differently?
override func viewDidLoad() {
super.viewDidLoad()
imageView.transform = CGAffineTransform(translationX: 0, y: 44)
imageView.frame = CGRect(x: 0, y: 0, width: imageView.frame.width,
height: imageView.frame.height + 44)

Add subView behind items to UINavigationBar in iOS 11

In my UINavigationBar subclass I am adding a subView with insertSubview(customView, at: 0) in order to place it in the very 'back' of the UINavigationBar.
In iOS 10 the added subView will be added the Title and UIBarButtonItems as I want it, but in in iOS 11 it seems like Apple changed something because no matter what I try the customView will be placed every time in the front of the UINavigationBar.
//containerView
containerView.frame = CGRect(x: 0, y: -(statusBarHeight), width: UIScreen.main.bounds.width, height: frame.height + statusBarHeight)
containerView.clipsToBounds = true
insertSubview(containerView, at: 0)
I already tried changing the index.
Any idea how I should tackle that problem?
You can look at this. I solved it this way:
override func layoutSubviews() {
super.layoutSubviews()
for aView in self.subviews {
if NSStringFromClass(type(of: aView)) == "_UINavigationBarContentView" {
aView.frame = CGRect(x: 0, y: 20, width: aView.frame.width, height: aView.frame.height)
}
else if NSStringFromClass(type(of: aView)) == "_UIBarBackground" {
aView.frame = CGRect(x: 0, y: 0, width: aView.frame.width, height: self.frame.height)
}
}
}

UIView Orientation change in Swift

I'm developing an app to display a binary tree.
Each node will be displayed as a subview programatically generated from the ViewController - I run the following from viewDidLayoutSubviews().
let theView = BinaryTreeView(frame: CGRect(x: 0, y: 50, width: width, height: 100))
// let theView = BinaryTreeView(s: "I'm testing")
theView.backgroundColor = .white
theView.addGestureRecognizer(UIPinchGestureRecognizer(target:theView, action:#selector(BinaryTreeView.changeScale(recognizer:))))
self.view.addSubview(theView)
theView.eyesOpen = false
let secondView = BinaryTreeView(frame: CGRect(x: width/2, y: 150, width: width/2, height: 100))
// let theView = BinaryTreeView(s: "I'm testing")
secondView.backgroundColor = .white
secondView.addGestureRecognizer(UIPinchGestureRecognizer(target:secondView, action:#selector(BinaryTreeView.changeScale(recognizer:))))
self.view.addSubview(secondView)
let thirdView = BinaryTreeView(frame: CGRect(x: (width/2)+width/4, y: 250, width: width/4, height: 100))
// let theView = BinaryTreeView(s: "I'm testing")
thirdView.backgroundColor = .white
thirdView.addGestureRecognizer(UIPinchGestureRecognizer(target:thirdView, action:#selector(BinaryTreeView.changeScale(recognizer:))))
self.view.addSubview(thirdView)
The issue is that on orientation change the views repeat each other (above there are three nodes, on orientation change 4 might display.
I looked through Stack and Within my subclassed UIView I added:
self.contentMode = UIViewContentMode.redraw
Within the programatic Subview but the same happens.
Don't worry - I'm going to generate my nodes in a loop later (I'm trying to understand how layout works). Incidentally I found the same happened using a UICollectionView so I seem to be doing something fundamentally wrong.
Change the "target:" to the controller (to self) for all three. Your controller will respond to gestures, not the views themselves. The target will be the same in all three cases.
secondView.addGestureRecognizer(UIPinchGestureRecognizer(target:secondView, action:#selector(BinaryTreeView.changeScale)))
self.view.addSubview(secondView)
becomes
secondView.addGestureRecognizer(UIPinchGestureRecognizer(target:self, action:#selector(BinaryTreeView.changeScale)))
self.view.addSubview(secondView)