Hi I need some help ScrollViews. I want to have a horizontal scrollview take up the bottom 25% of a screen and stay at 25% across all iPhone screen sizes. I am just not sure how to code it in Swift. I know that I should not give it a fixed width and height like I have. Does anyone know how I can do this or where I can look for help? My main problem is that when I switch between devices it does not stay the same height and width. I am using a stackview.
import UIKit
class paintedLadiesVC: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
let WIDTH: CGFloat = 414
let HEIGTH: CGFloat = 212
override func viewDidLoad() {
super.viewDidLoad()
for var x = 1; x <= 5; x++ {
let img = UIImage(named: "\(x)")
let imgView = UIImageView(image: img)
scrollView.addSubview(imgView)
imgView.frame = CGRectMake(-WIDTH + (WIDTH * CGFloat(x)), 1, WIDTH, HEIGTH)
}
scrollView.contentSize = CGSizeMake(WIDTH * 5, scrollView.frame.size.height)
}
}
Base your sizes on the device using 'UIDevice.currentDevice().width ' 'UIDevice.currentDevice().height'
Related
I have a array of Images and i'm moving images using scroll view and ALL WORKS FINE.
As i'm new in Swift so Now i need a solution for, When the images moving how can i check which image number(or image index number) is showing from total of images and then update Navigation bar accordingly.
Here is attached sample that i'm looking for:
code of Moving Images
class ImageScrollViewController: UIViewController {
#IBOutlet weak var mainScrollView: UIScrollView!
var imageArray = [UIImage]()
override func viewDidLoad() {
//mainScrollView.frame = view.frame
imageArray.append(UIImage(named: "nature-2")!)
imageArray.append(UIImage(named: "nature")!)
imageArray.append(UIImage(named: "nature4")!)
imageArray.append(UIImage(named: "nature5")!)
imageArray.append(UIImage(named: "nature6")!)
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = (self.view.frame.width * CGFloat(i)) + CGFloat(8)
imageView.frame = CGRect(x: xPosition , y: 0, width: self.mainScrollView.frame.width - CGFloat(16), height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i+1)
mainScrollView.addSubview(imageView)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Hope so you guys, understand my Question.
Any help will be appreciated.
Thanks in Advance.
You can use contentOffset to continuously keep track of the position in UIScrollViewDelegate method scrollViewDidScroll.
So, if the screen is 1000px wide:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// how far from beginning of scrollView (ex: user scrolls 3300px to the right)
let scrollDistance = mainScrollView.contentOffset.x
// size of 1 image (each is 1000px wide + 8px spacing between images)
let sizeOfOneImage = self.view.frame.width + 8
// number of images scrolled (3300px scrolled right = ~3.3 images scrolled so far...)
let numberOfScreensScrolled = scrollDistance / sizeOfOneImage
// floor(#) turns 3.3 into 3 (removes everything after decimal)
var imageInteger = floor(numberOfScreensScrolled)
// need +1, or else 1st image will be "0", 2nd image will be "1", etc.
imageInteger = imageInteger + 1
// # / total
self.title = "\(imageInteger)/\(imageArray count)"
}
Below, + self.view.frame.width/2 exists to make the transition to the next number occur when ~50% of the next image is onscreen (can be changed to whatever seems best).
class ImageScrollViewController: UIViewController, UIScrollViewDelegate {
...
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let imageInteger = floor((mainScrollView.contentOffset.x + self.view.frame.width/2) / (self.view.frame.width + 8)) + 1
self.title = "\(imageInteger)/\(imageArray count)"
}
My view hierarchy is this
PhotoDetailViewController.swift
View
UIScrollView
UIImageView
I set this up using storyboard, and add four constraints(top=0, bottom=0, leading=0, tailing=0) to UIScrollView, four constraints(top=0, bottom=0, leading=0, tailing=0) to UIImageView, but there are two error says
"ScrollView has ambiguous scrollable content width"
"ScrollView has ambiguous scrollable content height"
I understand that this is because I haven't set UIScrollView contentSize, but What I trying to do is load photo from PHAsset asynchronously, so I can only get the photo size at run time. So the question is:
1:Given that photo size can only be get at run time, how to solve the "ambiguous scrollable content" error?
2:In which View's life cycle method should I call PHImageManager.requestImageForAsset? because I think I should set UIScrollView contentSize programmatically, but when?
update with PhotoDetailViewController.swift
import UIKit
import Photos
class PhotoDetailViewController : UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var imageViewBottomConstraint: NSLayoutConstraint!
#IBOutlet weak var imageViewLeadingConstraint: NSLayoutConstraint!
#IBOutlet weak var imageViewTopConstraint: NSLayoutConstraint!
#IBOutlet weak var imageViewTrailingConstraint: NSLayoutConstraint!
var devicePhotosAsset : PHFetchResult!
var index = 0
var photo : UIImage!
var imgManager:PHImageManager!
#IBOutlet weak var imageView : UIImageView!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func awakeFromNib() {
self.imgManager = PHImageManager()
}
override func viewDidLoad() {
super.viewDidLoad()
self.displayPhoto()
}
override func viewWillLayoutSubviews() {
super.viewDidLayoutSubviews()
updateMinZoomScaleForSize()
updateConstraintsForSize()
}
func displayPhoto () {
_ = self.imgManager.requestImageForAsset(self.devicePhotosAsset[self.index] as! PHAsset, targetSize: PHImageManagerMaximumSize, contentMode: .AspectFit, options: nil, resultHandler: {(result, info) -> Void in
NSOperationQueue.mainQueue().addOperationWithBlock(){
self.imageView.image = result
}
})
}
private func targetSize() -> CGSize {
let scale = UIScreen.mainScreen().scale
let targetSize = CGSizeMake(CGRectGetWidth(self.imageView.bounds)*scale, CGRectGetHeight(self.imageView.bounds)*scale)
return targetSize
}
private func updateMinZoomScaleForSize() {
let size = scrollView.bounds.size
let widthScale = size.width / imageView.bounds.width
let heightScale = size.height / imageView.bounds.height
let minScale = min(widthScale, heightScale)
scrollView.minimumZoomScale = minScale
scrollView.zoomScale = minScale
}
func recenterImage(){
let scrollViewSize = scrollView.bounds.size
let imageSize = imageView.frame.size
let horizontalSpace = imageSize.width < scrollViewSize.width ? (scrollViewSize.width - imageSize.width)/2 : 0
let verticalSpace = imageSize.height < scrollViewSize.height ? (scrollViewSize.height - imageSize.height)/2 : 0
scrollView.contentInset = UIEdgeInsets(top: verticalSpace, left: horizontalSpace, bottom: verticalSpace, right: horizontalSpace)
}
private func updateConstraintsForSize() {
let size = scrollView.bounds.size
let yOffset = max(0, (size.height - imageView.frame.height) / 2)
imageViewTopConstraint.constant = yOffset
imageViewBottomConstraint.constant = yOffset
let xOffset = max(0, (size.width - imageView.frame.width) / 2)
imageViewLeadingConstraint.constant = xOffset
imageViewTrailingConstraint.constant = xOffset
view.layoutIfNeeded()
}
}
extension PhotoDetailViewController: UIScrollViewDelegate {
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(scrollView: UIScrollView) {
updateConstraintsForSize()
}
}
Your existing constraints are enough to set the content size, it's just that it's based on the image view intrinsic content size and that doesn't really exist until the image view has an image.
You can add a width and height constraint to the image view with default values and deactivate those constraints when the image is set to the view. Or you could use a placeholder image and avoid those extra constraints because you'd always have an intrinsic content size for the image view.
You should set two more constraint to your imageView.
Horizontally in Container (or you can say it center X)
Fixed Height
Second thing you can put UIView on Scrollview with Constraints like,
Top,leading,trailing,bottom,Horizontally in container(center x),fixed height).
Then add your imageview to that view. And can change it's constraint after getting image to resize it's height and width.
You can connect outlet of any constraint and can change it's constant programmatically.
Xcode UI builder has special type of constraint for such cases (when you can setup constraint only in runtime). It's so called "placeholder constraint" which will be removed at build time but helps to remove constraints errors for developing.
So solution is
Add some sample constraints IB and mark them as placeholders
Add needed constraints in runtime
When you get the data, just add these lines
float sizeOfContent = 0;
UIView *lLast = [yourscrollview.subviews lastObject];
NSInteger wd = lLast.frame.origin.y;
NSInteger ht = lLast.frame.size.height;
sizeOfContent = wd+ht;
yourscrollview.contentSize = CGSizeMake(yourscrollview.frame.size.width, sizeOfContent);
Hope this helps
I am trying to make image view circled for profile pics.
It was working properly before I had put constrains of UiScreen width.
so here is the code
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var proPicH: NSLayoutConstraint! //Profile Picture Height
#IBOutlet weak var proPicW: NSLayoutConstraint! // Profile Picture Width
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
circleImage()
}
func circleImage() {
let screenSize = UIScreen.mainScreen().bounds
let screenWidth = screenSize.width
let width = screenWidth / 2
print("ScreenWidth: \(screenWidth)")
proPicW.constant = width
proPicH.constant = width
print("H:\(proPicH.constant)")
print("W:\(proPicW.constant)") //Here the height and width comes to my expectations
imageView.layer.cornerRadius = imageView.bounds.width / 2
imageView.clipsToBounds = true
print("Height: \(imageView.bounds.height)") // Here the height and width becomes more
}
}
Please help me with this to make image round
At the point in time where you set the image view corner radius its bounds haven't been updated to match the constraints yet. Change this line
imageView.layer.cornerRadius = imageView.bounds.width / 2
To
imageView.layer.cornerRadius = width / 2
So that the same value used to set the constraints is also used for the corner radius.
Note that if you update the constraints in some other piece of code you also new to update the corner radius to match.
I would suggest you to put
circleImage()
in viewDidAppears Methods
Use imageView.layer.cornerRadius = imageView.frame.size.width / 2
imageView.layer.maskToBounds=Yes;
I need to make the flowers image flipping. Images must be with the same height, but the width to set automatically. I want them to scroll right and left
Here is my code:
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
var images = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
for i in 1...3 {
images.append(UIImage(named: "bild-0\(i).jpg")!)
}
var i: CGFloat = 0
var origin: CGFloat = 0
let height: CGFloat = scrollView.bounds.height
for image in images {
let imageView = UIImageView(frame: CGRectZero)
imageView.frame.size.height = height
imageView.image = image
imageView.sizeToFit()
imageView.frame.origin.x = origin
println(imageView.frame.size.width)
println(imageView.frame.origin.x)
println(imageView.frame.size.height)
println("asd")
origin = origin + imageView.frame.size.width
i++
scrollView.addSubview(imageView)
}
scrollView.contentSize.width = origin
scrollView.bounces = false
scrollView.pagingEnabled = false
}
}
Storyboard:
Problem (Padding from top! - Red color - is a background for UIScrollView):
Images are 765x510 300x510 and so on
UIScrollView height is 170
This is caused by scrolling insets:
Click your ViewController on Storyboard and go to file inspector, and you should see this dialog:
Untick the Adjust Scroll View Insets.
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