UIImageView under UIScrollview does not fit on top screen - ios

I have place UIImageView under UIScrollView on screen with constant width same as screen, and it works fine in iphone 5s but on iphone 7 or 8 the size of image is less than the width of screen size as shared on screenshots.
here is my code:
let x = CGFloat(selectedEvent.album?.count ?? 0)
pageControl.numberOfPages = (selectedEvent.album?.count ?? 0)
for index in 0..<(selectedEvent.album?.count ?? 0) {
frame.origin.x = scroll.frame.size.width * CGFloat(index)
frame.size = scroll.frame.size
print(self.frame.size.width)
print(scroll.frame.size.width)
print(frame.size.width)
let image = UIImageView(frame: frame)
image.contentMode = .scaleToFill
print(image.frame.size.width)
if (selectedEvent.album?.count ?? 0) > 0 {
selectedEvent.getAlbumImage(key: selectedEvent.album![index], completion: { (gotImage:UIImage) in
image.image = gotImage
})
} else {
image.image = UIImage(named: "defaultImage.jpg")
}
scroll .addSubview(image)
}
self.scroll.contentSize = CGSize(width: scroll.frame.size.width * x, height: scroll.frame.size.height)
pageControl.addTarget(self, action: #selector(self.changePage(sender:)), for: UIControlEvents.valueChanged)
here is the Print Log
320.0
320.0
320.0
320.0
320.0
320.0
320.0
320.0

In shorts, views might not have updated frames on viewDidLoad or ViewWillAppear methods instead views are initialised with storyboard sizes. So you are not getting updated rect for iPhone 7 or other devices.
Another reason is scrollview adjusts it's subview automatically. So disable it on viewDidLoad().
override func viewDidLoad() {
super.viewDidLoad()
self.scroll.contentInsetAdjustmentBehavior = .never;
// write your code
}
You should add subviews on viewDidLoad() method as you have done already and update frame & scrollview content related changes on viewDidLayoutSubviews().
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews();
for view:UIView in self.scroll.subviews {
frame.origin.x = self.scroll.frame.size.width * CGFloat(self.scroll.subviews.index(of: view)!);
frame.size = scroll.frame.size
view.frame = frame;
}
self.scroll.contentSize = CGSize(width: scroll.frame.size.width * selectedEvent.album?.count , height: scroll.frame.size.height)
}
Hope will work.

You want the frame width to be the screen width. Use as :
let size = UIScreen.main.bounds.size
self.scroll.contentSize = CGSize(width: size.width, height: scroll.frame.size.height)

Related

Paging by scrollView incorrect displayed

I don't understand why the iPhone 4,7 is displayed correctly, but on iphone 5,5 is not displayed correctly. I want make paging by ScrollView.
What should I do to be displayed correctly on all devices?
func showScrollView() {
var photoSlides = [Slides]()
for image in photo {
let slide: Slides = Bundle.main.loadNibNamed("Slide", owner: self, options: nil)?.first as! Slides
slide.slideImage.image = image.image
photoSlides.append(slide)
}
setupSlideScrollView(slides: photoSlides)
}
func setupSlideScrollView(slides : [Slides]) {
scrollView.contentSize = CGSize(width: scrollView.frame.width * CGFloat(slides.count), height: 200)
scrollView.isPagingEnabled = true
for i in 0 ..< slides.count {
slides[i].frame = CGRect(x: scrollView.frame.width * CGFloat(i), y: 0, width: scrollView.frame.width, height: scrollView.frame.height)
scrollView.addSubview(slides[i])
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageIndex = round(scrollView.contentOffset.x/scrollView.frame.width)
pageControl.currentPage = Int(pageIndex)
}
https://yadi.sk/i/ipS5WchP3aRtZ9 - correctly (iPhone 8)
https://yadi.sk/i/SPmriRFn3aRtgL - not correctly (iPhone 8 Plus)
If you have used storyboard or xib to design your UI, and then for some portion of your screen you want frame size to calculate frame of other controls then you have to use layoutIfNeeded method on that control. i.e in your case you can do something like below
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
scrollView.layoutIfNeeded()
// THEN CALL YOUR FUNCTION WHICH SETUP YOUR OTHER VIEWS
showScrollView()
}

my initial problems with UIScrollView now appear to be related to autolayout

For my first challenge using UIScrollView I modified this example to make UIScrollView display not just another background colour but another UIView and UILabel on each page. But I could have just as easily chosen to display objects like UITableView, UIButton or UIImage.
Potentially, UIScrollView could be much more than a giant content view where users scroll from one part to the next, e.g., some pages might have a UIButton that takes a user to a specific page, the same way we use books.
Code Improvements
My question has evolved since I first posted it. Initially the labels piled up on page 1 (as shown below) but this has now been corrected. I also included this extension to make the font larger.
Further improvement ?
As the code evolved I became more aware of other issues e.g. iPhone 5 images (below) appear differently on iPhone 7 where the UILabel is centred but not the UIView. So my next challenge is possibly to learn how to combine UIScrollView with Autolayout. I invite anyone to spot other things that might be wrong.
ViewController.swift (corrected)
import UIKit
class ViewController: UIViewController,UIScrollViewDelegate {
let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
var views = [UIView]()
var lables = [UILabel]()
var colors:[UIColor] = [UIColor.red, UIColor.magenta, UIColor.blue, UIColor.cyan, UIColor.green, UIColor.yellow]
var frame: CGRect = CGRect.zero
var pageControl: UIPageControl = UIPageControl(frame: CGRect(x: 50, y: 500, width: 200, height: 50))
override func viewDidLoad() {
super.viewDidLoad()
initialiseViewsAndLables()
configurePageControl()
scrollView.delegate = self
self.view.addSubview(scrollView)
for index in 0..<colors.count {
frame.origin.x = self.scrollView.frame.size.width * CGFloat(index)
frame.size = self.scrollView.frame.size
self.scrollView.isPagingEnabled = true
views[index].frame = frame
views[index].backgroundColor = colors[Int(index)]
views[index].layer.cornerRadius = 20
views[index].layer.masksToBounds = true
lables[index].frame = frame
lables[index].center = CGPoint(x: (view.frame.midX + frame.origin.x), y: view.frame.midY)
lables[index].text = String(index + 1)
lables[index].defaultFont = UIFont(name: "HelveticaNeue", size: CGFloat(200))
lables[index].textAlignment = .center
lables[index].textColor = .black
let subView1 = views[index]
let subView2 = lables[index]
self.scrollView .addSubview(subView1)
self.scrollView .addSubview(subView2)
}
print(views, lables)
self.scrollView.contentSize = CGSize(width: self.scrollView.frame.size.width * CGFloat(colors.count), height: self.scrollView.frame.size.height)
pageControl.addTarget(self, action: Selector(("changePage:")), for: UIControlEvents.valueChanged)
}
func initialiseViewsAndLables() {
// Size of views[] and lables[] is linked to available colors
for index in 0..<colors.count {
views.insert(UIView(), at:index)
lables.insert(UILabel(), at: index)
}
}
func configurePageControl() {
// Total number of available pages is based on available colors
self.pageControl.numberOfPages = colors.count
self.pageControl.currentPage = 0
self.pageControl.backgroundColor = getColour()
self.pageControl.pageIndicatorTintColor = UIColor.black
self.pageControl.currentPageIndicatorTintColor = UIColor.green
self.view.addSubview(pageControl)
}
func getColour() -> UIColor {
let index = colors[pageControl.currentPage]
return (index)
}
func changePage(sender: AnyObject) -> () {
scrollView.setContentOffset(CGPoint(x: CGFloat(pageControl.currentPage) * scrollView.frame.size.width, y: 0), animated: true)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
pageControl.currentPage = Int(pageNumber)
pageControl.backgroundColor = getColour()
}
}
Extension
extension UILabel{
var defaultFont: UIFont? {
get { return self.font }
set { self.font = newValue }
}
}
The centre point of the lable on each frame must be offset by the origin of the content view (as Baglan pointed out). I've modified the following line of code accordingly.
lables[Int(index)].center = CGPoint(x: (view.frame.midX + frame.origin.x), y: view.frame.midY)

Change UIScrollView Content size

I have ViewController with UIScrollView, some UIImages and UIButtons.
In the Storyboard I set the size of UIScrollView to: width: 320, height: 570
I want to change Contentsize of my UIScrollView when the ViewController was loaded.
I added side in the viewDidLoad:
scrlMain.contentSize = CGSize(width: 320,height: 790)
And also I added code in the viewDidLayoutSubviews:
self.scrlMain.translatesAutoresizingMaskIntoConstraints = true
But my UIScrollView is still the last size = 570.
I can't use viewDidAppear because, when I press the button, it need it to change color. When it has changed color, my UIScrollView moves to up.
What did I do wrong?
All code:
override func viewDidLoad() {
super.viewDidLoad()
scrlMain.delegate = self
scrlMain.contentSize = CGSizeMake(320, 790)
}
override func viewDidLayoutSubviews() {
self.scrlMain.translatesAutoresizingMaskIntoConstraints = true
self.scrlMain.contentSize = CGSize(width: self.scrlMain.frame.width, height: 60.0 + 5 * (self.scrlMain.frame.width / 16.0 * 5.0));
}
there was an error in the this function:
override func viewDidLayoutSubviews() {
self.scrlMain.translatesAutoresizingMaskIntoConstraints = true
self.scrlMain.contentSize = CGSize(width: self.scrlMain.frame.width, height: 60.0 + 5 * (self.scrlMain.frame.width / 16.0 * 5.0));
}
I delete this code:
self.scrlMain.contentSize = CGSize(width: self.scrlMain.frame.width, height: 60.0 + 5 * (self.scrlMain.frame.width / 16.0 * 5.0));
And all was right
Hey #Dim you can try this-
yourScrollView.contentSize = CGSizeMake(320, 568)
And you can change size 568 to whatever you want.
Try this:
yourScrollView.userInteractionEnabled = YES
and you please maintain the difference between your screen size and your scrollview content size... so that it can be visible properly
suppose yourScrollViewSize greatertThan yourScreenSize
override func viewDidLayoutSubviews() {
DispatchQueue.main.async {
self.scrollview.translatesAutoresizingMaskIntoConstraints = true
self.scrollview.contentSize = CGSize(width:0, height:self.scrollview.frame.height*2) // whatever hight you want
}
}
It is also possible to change the content size from within the page without running ViewDidLoad again.
Just add
scrollView.layoutIfNeeded()
after you set the new contentSize
Example when you change the content size (viewImages) within the UIscrollView (scrollViewImages)
viewImages.frame.size = CGSize(width: width, height: 128)
viewImages.translatesAutoresizingMaskIntoConstraints = true
viewImages.setNeedsLayout()
scrollViewImages.setNeedsLayout()
scrollViewImages.layoutIfNeeded()

view placed differently on iphone and ipad

i have built an app that allows the user to take their picture with a selection of glasses overlaid. it is working exactly how i want it on both an ipad and ipad mini but on the iphone the position in relation the the scroll view is wrong (see Images).
func setupPages(){
pageImages = [
UIImage(named: "glasses_one")!,
UIImage(named: "glasses_two")!,
UIImage(named: "glasses_three")!,
UIImage(named: "glasses_four")!,
UIImage(named: "glasses_five")!,
UIImage(named: "glasses_six")!
]
let pageCount = pageImages.count
for _ in 0..<pageCount {
pageViews.append(nil)
}
print(pageViews.count)
let pagesScrollViewSize = scrollView.frame.size
scrollView.contentSize = CGSize(width: scrollWidth * CGFloat(pageImages.count),
height: pagesScrollViewSize.height)
scrollView.backgroundColor = UIColor.blueColor()
loadVisiblePages()
}
func loadVisiblePages() {
let pageWidth = scrollView.frame.size.width
page = Int(floor((scrollView.contentOffset.x * 2.0 + pageWidth) / (pageWidth * 2.0)))
print(page)
pageControl.currentPage = page
for index in 0...5 {
//print(" -- Index = \(index)")
loadPage(index)
}
}
func loadPage(page: Int) {
if page < 0 || page >= pageImages.count {
// If it's outside the range of what you have to display, then do nothing
return
}
// 1
if let pageView = pageViews[page] {
print(pageView.description)
// Do nothing. The view is already loaded.
} else {
// 2
var frame = scrollView.bounds
frame.origin.x = scrollWidth * CGFloat(page)
frame.origin.y = 0.0
frame.size.width = scrollWidth
// 3
let newPageView = UIImageView(image: pageImages[page])
newPageView.contentMode = .ScaleAspectFit
newPageView.frame = frame
newPageView.clipsToBounds = false
scrollView.addSubview(newPageView)
// 4
pageViews[page] = newPageView
}
}
Ipad
Iphone
I think your issue is you need to add a constraint to center you image vertically. Or you could also solve this by making the frame for your "glasses frame" A set width and height. Smaller screens will have less space around it but will still be in the middle.

Scrollview doesn't cover all width

I have a ScrollView combined with a PageControll and it contains 5 images which I want them to scroll. My problem is that the ScrollView width even if it is 320 in simulator it doesn't show covering the all width.
This is my code:
override func viewDidLoad() {
super.viewDidLoad()
images.append(UIImage(named: "one.jpg")!)
images.append(UIImage(named: "two.jpg")!)
images.append(UIImage(named: "three.jpg")!)
images.append(UIImage(named: "four.jpg")!)
images.append(UIImage(named: "five.jpg")!)
for var i = 0; i < images.count; i++ {
var frame: CGRect = CGRectMake(0, 0, 0, 0)
frame.origin.x = self.scrollView.frame.size.width * CGFloat(i)
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
var imageView: UIImageView = UIImageView(frame: frame)
imageView.image = images[i]
self.scrollView.addSubview(imageView)
}
self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * CGFloat(images.count), scrollView.frame.size.height)
}
Most likely, the scroll view's width is the correct size, but the content-mode of the UIImageView is set incorrectly such that as a result of the image being displayed having a smaller size than the scroll view, it will not fill the whole of the image view as you wanted.
imageView.contentMode = UIViewContentModeScaleAspectFill;
// Swift
imageView.contentMode = .ScaleAspectFit
Try adding constraints to your image in your interface builder.
Put Constraints:
Main.storyboard -> UIImageView (for each UIImageView) -> Editor -> Pin -> Select leading,top space, bottom and trailing space to superview.
Your scrollView doesn't have constraints

Resources