Swift 5 UIScrollView adding background image - swift

I'm trying to add a background image that will scroll with my vertical scrollView. Before adding the background image, my scrollView only scroll vertically, but after setting the background image, the scrollView can now scroll horizontally and vertically as if the background image's width is greater than the scrollview's width
let scrollView: UIScrollView = {
let view = UIScrollView()
view.translatesAutoresizingMaskIntoConstraints = false
view.isDirectionalLockEnabled = true
view.isScrollEnabled = true
return view
}()
let backgroundIV: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "background"))
imageView.contentMode = UIView.ContentMode.scaleToFill
return imageView
}()
The function I use to setup my view
private func setupContent() {
scrollViewHeight = viewHeight * 2
[scrollView].forEach { view.addSubview($0) }
scrollView.anchor(top: view.topAnchor, leading: view.leadingAnchor, bottom: view.bottomAnchor, trailing: view.trailingAnchor)
scrollView.contentSize = CGSize(width: 0, height: scrollViewHeight)
[backgroundIV].forEach { scrollView.addSubview($0) }
backgroundIV.anchor(top: scrollView.topAnchor, leading: scrollView.leadingAnchor, bottom: scrollView.bottomAnchor, trailing: scrollView.trailingAnchor, size: .init(width: 0, height: scrollViewHeight))
}
So how should i set my background image so that my scrollview won't scroll horizontally??

You have to set the right content sizes for your scrollView or adjust the content.
Set your imageView width equal to your scrollView's width. It will avoid scrollView horizontal scroll.
Please find the below code for setting the widthAchor.
imageView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true

After applying Vikram Parimi's answer and some further digging, there were two factors that effect my scrollview to become horizontal
The characteristics of constraints between Scroll View and view tells us: the alignment and the size are not contradicted anymore, both of which must be defined to eliminate ambiguity. Which I found out from https://medium.com/#tingyishih/ios-scrollview-constraints-8d8140d329a0
The other factor is that the bug only exist in iphone 11 pro max simulator and not iphone 8 simulator, which can be solve by using safeAreaLayoutGuide
if #available(iOS 11.0, *) {
imageView.widthAnchor.constraintEqualToAnchor(scrollView.safeAreaLayoutGuide.widthAnchor).active = true
} else {
imageView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
}

Related

Center ImageView in ScrollView with paging enabled - Swift

I need to create a paging ScrollView which shows a sequence of images.
I created a ScrollView in the main view of the Storyboard and set this constraints (to center the ScrollView in the view):
Constraint
Then I activated paging and disabled the "Content layout guides" option.
Next, in the view class I set up the UIScrollViewDelegate delegate and I wrote the following code to show 3 images (they are 3 colored squares):
class ViewController: UIViewController, UIScrollViewDelegate {
// Outlet
#IBOutlet weak var scrollview: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
scrollview.delegate = self;
let infoArray = ["01", "02", "03"];
for i in 0..<infoArray.count {
let imageView = UIImageView();
imageView.contentMode = .scaleToFill;
imageView.image = UIImage(named: infoArray[i]);
let xPos = CGFloat(i) * scrollview.bounds.size.width;
imageView.frame = CGRect(x: xPos, y: 0, width: scrollview.bounds.size.width, height: scrollview.bounds.size.height);
imageView.layer.borderWidth = 1;
scrollview.contentSize.width = scrollview.frame.size.width * CGFloat(i+1);
scrollview.contentSize.height = scrollview.frame.size.height;
scrollview.addSubview(imageView);
}
scrollview.layer.borderWidth = 1;
}
}
I have set that the images must have the same width and height as the scrollview. But these are larger in the simulator (and in my iPhone 11) and therefore the display is incorrect. I show you the sequence of the 3 squares:
Page 1
Page 2
Page 3
Page 4
I can't understand where I'm wrong. Why don't the 3 images take the size of the scrollview?
Why are there 4 pages?
Thanks for your help
Okay, here is how you do it:
Your scrollview is created in storyboard and its layout is set. Make sure content layout guides is unchecked in the size inspector and paging is checked in the attribute inspector.
Add a stackview as a subview to your scrollview (this will act as the content view). Pin your stackView to all 4 edges of the scrollView.
Set Height and Width Equal to the scrollView height and width. Set the Width priority to 250. (that indicates that the scrollview will scroll horizontally)
Set the stackView to horizontal axis, fill alignment and fillEqually distribution.
Now, go back to viewDidLoad and add the following code below. ScrollViewContentView is the stackView that acts as a contentView for the scrollView. Note that since stackView is set to fillEqually, you only need set one of the image's width constraint.
scrollViewContentView.addArrangedSubview(image1)
scrollViewContentView.addArrangedSubview(image2)
scrollViewContentView.addArrangedSubview(image3)
image1.translatesAutoresizingMaskIntoConstraints = false
image2.translatesAutoresizingMaskIntoConstraints = false
image3.translatesAutoresizingMaskIntoConstraints = false
image1.backgroundColor = .blue
image2.backgroundColor = .yellow
image3.backgroundColor = .red
image1.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
I think you need to state the frame of the scrollview before you declare the imageViews x positions or widths.
class ViewController: UIViewController, UIScrollViewDelegate {
// Outlet
#IBOutlet weak var scrollview: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
scrollview.frame = view.frame // declared here
scrollview.delegate = self;
let infoArray = ["01", "02", "03"];
for i in 0..<infoArray.count {
let imageView = UIImageView();
imageView.contentMode = .scaleToFill;
imageView.image = UIImage(named: infoArray[i]);
let xPos = CGFloat(i) * scrollview.bounds.size.width;
imageView.frame = CGRect(x: xPos, y: 0, width: scrollview.bounds.size.width, height: scrollview.bounds.size.height);
imageView.layer.borderWidth = 1;
scrollview.contentSize.width = scrollview.frame.size.width * CGFloat(i+1);
scrollview.contentSize.height = scrollview.frame.size.height;
scrollview.addSubview(imageView);
}
scrollview.layer.borderWidth = 1;
}
}

UIScrollView content inset defined by a height of a view outside of the subtree

Given a view hierarchy:
- View `container`
- UIScrollView `scrollView`
- UIView `content`
- UIView `footer`
I would like the UIScrollView.contentInset.bottom to be equal to footer.bounds.height.
Question: Can this be expressed using Auto Layout?
Now, there is a very evident brute-force approach that I am aware of and that works:
Observe changes to the bounds property of the footer
scrollView.contentInset.bottom = -footer.bounds.height once footer's parent has finished layoutSubviews().
Or alternatively I could have a constraint between content.bottom and scrollView.bottom (which, as, I'm sure, you are aware, indicates the bottom content inset for non-ambiguously size content) and have its constant altered each time the footer bounds change.
But the point is that all of those approaches are very on-the-nose, really makes me uncomfortable for the terrible code they produce so I am wondering:
Can this be expressed using Auto Layout?
I have attempted to do the following:
content.bottomAnchor.constraint(equalTo: footer.topAnchor)
Hoping that content.bottomAnchor would be treated as the bottom inset of the scroll view content, but nope - Auto Layout literally treats it as me constraining content's bottom to the footer's top.
OK - one approach...
As of iOS 11 (I'm assuming you don't need to target earlier than that), a subview of a UIScrollView can be constrained to the scroll view's Frame Layout Guide. This made it easy to add non-scrolling UI elements to the scroll view hierarchy.
Based on this hierarchy:
- view
- scrollView
- contentView
- element1
- element2
- element3
- UILayoutGuide
- footerView
What we'll do is:
add all the "scrollable" elements to the contentView
plus add a UILayoutGuide to the contentView which will serve as or "bottom" scrollable element
add the footerView to the scrollView last so it is at the top of the z-order
constrain the footerView to the scrollView's Frame Layout Guide so it stays put
constrain the heightAnchor of our UILayoutGuide equal to the heightAnchor of the footerView
Because a UILayoutGuide is a non-rendering view, it will not be visible but it will create the space from the bottom of our last viewable element to the bottom of the contentView -- and it will automatically change height if/when the footerView changes height.
Here's a complete example - scrollView / contentView / 3 imageViews / layout guide / translucent footerView:
class ExampleViewController: UIViewController {
let scrollView: UIScrollView = {
let v = UIScrollView()
v.backgroundColor = .lightGray
return v
}()
let contentView: UIView = {
let v = UIView()
v.backgroundColor = .cyan
return v
}()
let footerView: UILabel = {
let v = UILabel()
v.textAlignment = .center
v.textColor = .white
v.font = UIFont.systemFont(ofSize: 24.0, weight: .bold)
v.text = "Footer View"
v.backgroundColor = UIColor.black.withAlphaComponent(0.65)
return v
}()
var imgView1: UIImageView = {
let v = UIImageView()
v.backgroundColor = .red
v.image = UIImage(systemName: "1.circle")
v.tintColor = .white
return v
}()
var imgView2: UIImageView = {
let v = UIImageView()
v.backgroundColor = .green
v.image = UIImage(systemName: "2.circle")
v.tintColor = .white
return v
}()
var imgView3: UIImageView = {
let v = UIImageView()
v.backgroundColor = .blue
v.image = UIImage(systemName: "3.circle")
v.tintColor = .white
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
// add 3 image views as the content we want to see
contentView.addSubview(imgView1)
contentView.addSubview(imgView2)
contentView.addSubview(imgView3)
// add contentView to srollView
scrollView.addSubview(contentView)
// add footer view to scrollView last so it's at the top of the z-order
scrollView.addSubview(footerView)
view.addSubview(scrollView)
[scrollView, contentView, footerView, imgView1, imgView2, imgView3].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
// "spacer" for bottom of scroll content
// we'll constrain it to the height of the footer view
let spacerGuide = UILayoutGuide()
contentView.addLayoutGuide(spacerGuide)
let g = view.safeAreaLayoutGuide
let svCLG = scrollView.contentLayoutGuide
let scFLG = scrollView.frameLayoutGuide
NSLayoutConstraint.activate([
// constrain scrollView view 40-pts on all 4 sides to view (safe-area)
scrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -40.0),
// contentView view 0-pts top / leading / trailing / bottom to scrollView contentLayoutGuide
contentView.topAnchor.constraint(equalTo: svCLG.topAnchor, constant: 0.0),
contentView.leadingAnchor.constraint(equalTo: svCLG.leadingAnchor, constant: 0.0),
contentView.trailingAnchor.constraint(equalTo: svCLG.trailingAnchor, constant: 0.0),
contentView.bottomAnchor.constraint(equalTo: svCLG.bottomAnchor, constant: 0.0),
// contentView width == scrollView frameLayoutGuide width
contentView.widthAnchor.constraint(equalTo: scFLG.widthAnchor, constant: 0.0),
// imgView1 to top of contentView
imgView1.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0.0),
// imgView1 width / height
imgView1.widthAnchor.constraint(equalToConstant: 240.0),
imgView1.heightAnchor.constraint(equalToConstant: 240.0),
// imgView1 centerX to contentView centerX
imgView1.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
// imgView2 top to bottom of imgView1 + 20-pt spacing
imgView2.topAnchor.constraint(equalTo: imgView1.bottomAnchor, constant: 20.0),
// imgView2 width / height
imgView2.widthAnchor.constraint(equalToConstant: 200.0),
imgView2.heightAnchor.constraint(equalToConstant: 280.0),
// imgView2 centerX to contentView centerX
imgView2.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
// imgView3 top to bottom of imgView2 + 20-pt spacing
imgView3.topAnchor.constraint(equalTo: imgView2.bottomAnchor, constant: 20.0),
// imgView3 width / height
imgView3.widthAnchor.constraint(equalToConstant: 280.0),
imgView3.heightAnchor.constraint(equalToConstant: 320.0),
// imgView3 centerX to contentView centerX
imgView3.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
// spacerGuide top to bottom of actual content
// spacerGuide top to imgView3 bottom
spacerGuide.topAnchor.constraint(equalTo: imgView3.bottomAnchor, constant: 0.0),
// spacerGuide to leading / trailing / bottom of contentView
spacerGuide.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0.0),
spacerGuide.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0.0),
spacerGuide.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0.0),
// footerView to leading / trailing / bottom of scrollView frameLayoutGuide
// (constrained to frameLayoutGuide so it won't scroll)
footerView.leadingAnchor.constraint(equalTo: scFLG.leadingAnchor, constant: 0.0),
footerView.trailingAnchor.constraint(equalTo: scFLG.trailingAnchor, constant: 0.0),
footerView.bottomAnchor.constraint(equalTo: scFLG.bottomAnchor, constant: 0.0),
// footerView height == scrollView height with 0.25 multiplier
// (so it will change height when scrollView changes height, such as device rotation)
footerView.heightAnchor.constraint(equalTo: scFLG.heightAnchor, multiplier: 0.25),
// finally, spacerGuide height equal to footerView height
spacerGuide.heightAnchor.constraint(equalTo: footerView.heightAnchor),
])
}
}
Result:
Scrolled to the bottom:
and rotated (so we see the footerView height change) scrolled all the way to the bottom:
Edit
The answer to the specific question is: you can't.
A scroll view's contentInset is not an object to which you can add constraints... it's a Property of the scroll view. Much like you could not constrain a scroll view's .backgroundColor to an auto-layout constraint.
Landed here after looking for a solution, in my case the scroll view is actually a UICollectionView, so adding "helper" elements to the layout (as suggested by another answer) would have been more challenging (changing dataSource logic etc)
I ended up doing the following:
(This example assumes you have a bottomView attached to the bottom of the screen and you want your scrollView / collectionView to be inset based on it)
Set scrollView.contentInsetAdjustmentBehavior = .never
Then in your View Controller, do this:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.scrollView.contentInset = .init(top: self.view.safeAreaLayoutGuide.layoutFrame.minY,
left: 0,
bottom: bottomView.frame.height,
right: 0)
}
Note that if you also want to account for left and right safe area (e.g. landscape avoiding iPhone notch), you can do:
[...]
left: self.view.safeAreaLayoutGuide.layoutFrame.minX
[...]
right: self.view.frame.width - self.view.safeAreaLayoutGuide.layoutFrame.maxX

Trouble getting UIImageView inside ScrollView programmatically

After days of trying, and searching through countless SO/google/YouTube pages, I unclear how to accomplish this: I'm trying to place a single tall, narrow image inside a UIScrollView that only takes up a section of the screen, only scrolls vertically, and is preferably only coded programmatically, no Interface Builder at all.
I've managed to create the scrollView, set the backgroundColor to blue so I can see it and managed to use constraint anchors to pin it exactly where I need it to be. I then added the top and bottom labels as every video tutorial was telling me to, but I've since deleted these as they didn't seem necessary once I added the image.
The problems start as soon as I try to add the image. I've added an example image below as it's a tall, narrow image.
https://imgur.com/7qI1IaT
If you run the code with the image, you'll see:
The image scrolls horizontally as well as vertically. I'd have thought content.didOffset.x < 0 would work, but apparently not. There's probably a simple method to fix this but I'm yet to find it.
If the height of the image is less than the height of the scrollView, i want the image to stretch to fit the scrollView. I used both .scaleAspectFit and .scaleAspectFill and neither of these seemed to change anything.
The width of the image (or at least, the image I'm using, not the example image) is larger than the section of scrollView I have, and it goes off the screen. Again, I'm sure there's an easy fix to this, but I don't know.
Here is my code, but it's probably all wrong.
import UIKit
class ViewController: UIViewController {
lazy var scrollView: UIScrollView = {
let view = UIScrollView()
view.translatesAutoresizingMaskIntoConstraints = false
view.frame.size.height = 3000
view.backgroundColor = UIColor.blue
return view
}()
let imageView: UIImageView = {
let image = UIImageView(image: imageLiteral)
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
func setupLayout() {
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 100).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollView.addSubview(imageView)
imageView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
imageView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
imageView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
imageView.frame.size.height = scrollView.frame.size.height
imageView.frame.size.width = scrollView.frame.size.width
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
setupLayout()
}
}
I don't know if I'm doing the right thing by adding the image as a subview of scrollView. I couldn't get the image to scroll at all until I changed it from the subview of view to scrollView. The labels in the tutorials I've seen were added that way, and it made more sense to me to add it into the scrollView than the main screen view, but again, this could be wrong.
I'm really not sure if it's the constraints, the contentSize or what, but it’s pretty clear I don't know what I’m doing, and I don't want to just wing it, so if anyone knows of any YouTube videos or websites that can help me out, I’d really appreciate it.
Again, apologies. I feel like this is a really simple fix, but I just don't have it.
There are a number of ways of accomplishing this, but I’d be inclined to set the zoomScale of the scroll view appropriate for this image view width, e.g.
// we want to make sure we adjust scale as views are laid out
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if imageView.intrinsicContentSize.width != 0 {
let scale = scrollView.bounds.width / imageView.intrinsicContentSize.width
scrollView.maximumZoomScale = scale
scrollView.minimumZoomScale = scale
scrollView.zoomScale = scale
}
}
To do that, you’ll have to set the delegate of the UIScrollView:
scrollView.delegate = self // we need to specify delegate so we can implement `viewForZooming(in:)`
And implement viewForZooming(in:):
extension ViewController: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
}
So pulling that all together:
class ViewController: UIViewController {
let sampleImage: UIImage = ...
let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
// view.frame.size.height = 3000 // not needed as we're using constraints
scrollView.backgroundColor = .blue
return scrollView
}()
let imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
// imageView.contentMode = .scaleAspectFit // not needed as we're going to let the intrinsic size dictate the size of the image view and therefore no scaling is happening
imageView.clipsToBounds = true
return imageView
}()
func setupLayout() {
view.addSubview(scrollView)
scrollView.addSubview(imageView)
imageView.image = sampleImage
scrollView.delegate = self // we need to specify delegate so we can implement `viewForZooming(in:)`
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 200),
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 100),
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
imageView.topAnchor.constraint(equalTo: scrollView.topAnchor),
imageView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
imageView.rightAnchor.constraint(equalTo: scrollView.rightAnchor),
imageView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor)
])
// these are not needed because we're using constraints
//
// imageView.frame.size.height = scrollView.frame.size.height
// imageView.frame.size.width = scrollView.frame.size.width
}
override func viewDidLoad() {
super.viewDidLoad()
setupLayout()
}
// we want to make sure we adjust scale as views are laid out
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if imageView.intrinsicContentSize.width != 0 {
let scale = scrollView.bounds.width / imageView.intrinsicContentSize.width
scrollView.maximumZoomScale = scale
scrollView.minimumZoomScale = scale
scrollView.zoomScale = scale
}
}
}
extension ViewController: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
}
You need to constraint the image width to the scrollview width. However you cannot do it directly, because the image is a subview of the scrollview and direct constraint would refer to width of the content of the scrollview not width. I have solved it by adding a layout guide that is constrained to the width of the scrollview "from the outside".
Also when you add constraint for the width you are left with intrinsic constraint for the height and that would change aspect ratio of the image. You need to add a constraint for the original aspect ratio.
Here is my code:
class ViewController: UIViewController {
let scrollView = UIScrollView()
let imageView = UIImageView(image: UIImage(named: "tallimage"))
let widthGuide = UILayoutGuide()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
setupLayout()
}
func setupViews() {
scrollView.backgroundColor = UIColor.blue
view.addSubview(scrollView)
scrollView.addSubview(imageView)
view.addLayoutGuide(widthGuide)
}
func setupLayout() {
let ratio: CGFloat = (imageView.image?.size.height ?? 1) / (imageView.image?.size.width ?? 1)
imageView.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 100),
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
imageView.topAnchor.constraint(equalTo: scrollView.topAnchor),
imageView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
imageView.rightAnchor.constraint(equalTo: scrollView.rightAnchor),
imageView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
// Make the image the same width as the scrollview.
widthGuide.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
imageView.widthAnchor.constraint(equalTo: widthGuide.widthAnchor),
// Keep the height/width ratio of the image so it is not deformed.
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: ratio),
])
}
}
I have also changed style of the code. Feel free to use your original style.
However, I like to
When I call a method, it is defined below the line where it is used (in order).
Use NSLayoutConstraint.activate() when activating more constraints.
Use simple instance variables (let constants) and configure them later.

No fullscreen with UIImage within UIScrollView with iPhone X and up

No fullscreen with UIImage within UIScrollView with iPhone X and up. Working perfect with iPhone 8 and +.
Screenshots from Xcode.
'UIImage is the color red.
UIScrollView is the color green.
Both UIScrollView and UIImage have constraints to SuperView. But with iPhone X the UIImage don´t align to the SuperView. If I move the UIImage directly to the View then it looks ok but then my Zoom option stop working.
This is the code for Zoom option.
func updateZoomFor(size: CGSize) {
let widthScale = size.width / image2.bounds.width
let heightScale = size.height / image2.bounds.height
let scale = min(widthScale,heightScale)
scrollView2.minimumZoomScale = scale
scrollView2.minimumZoomScale = 1.0
scrollView2.maximumZoomScale = 5.0
scrollView2.contentSize = .init(width: 2000, height: 2000)
}
func viewForZooming(in scrollView2: UIScrollView) -> UIView? {
return image2
}
This is the code to hide statusbar and home button.
override var prefersStatusBarHidden: Bool {
return true
}
override var prefersHomeIndicatorAutoHidden: Bool {
return true
}
I want the UIScrollView and UIImage to work with fullscreen on any Iphone both in portrait and landscape mode.
1.- set your scrollView:
let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false;
scrollView.backgroundColor = .clear
return scrollView
}()
2.- add to the subView:
private func setSubviews() {
self.addSubview(scrollView)
}
3.- Add everything to the ScrollView-Subview
example:
self.addSubview(scrollView)
self.scrollView.addSubview(screenIcon)
self.scrollView.addSubview(screenTitle)
4.- set constraints:
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0),
scrollView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0),
scrollView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0),
scrollView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 2),
])

parent UIView is not showing but the subviews are showing i nswift

this is the code I wrote
let topViewa = UIView()
topViewa.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(topViewa)
topViewa.backgroundColor = .white
topViewa.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 300).isActive = true
topViewa.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true
topViewa.frame.size = CGSize(width: screenWidth, height: 44)
let fw = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
fw.backgroundColor = .red
topViewa.addSubview(fw)
with screenWidth being the width of the screen.
and when I run this, this is what I get
Why am I not getting the parent UIView with white background?
Why am I not getting the parent UIView with white background?
Because the white view has no size.
The line
topViewa.frame.size = CGSize(width: screenWidth, height: 44)
...has no effect. You have elected to use constraints to position and size this view. Now you must fulfill that contract, giving it both position and size through constraints alone. You have not provided any height or width constraints (or alternatively, bottom or trailing constraints), so the view has zero size and you see nothing.
The red subview, meanwhile, remains visible, because the white superview's clipsToBounds is false. If it were true, you wouldn't see the red subview either.