Swift Container View with UIPageViewController - ios

I have a container view displaying a UIPageViewController. Everything is working ok, the only problem is the dots that display the pages. They are not able to adjust with the changing screen sizes.
pageControl = UIPageControl(frame: CGRect(x: 0,y: UIScreen.main.bounds.maxY - 525,width: UIScreen.main.bounds.width,height: 50))
This is the piece of code I am using to change where the dots are displayed mainly the UIScreen.main.bounds.maxY - 525 part. I am just checking on how I can have them adapt to the different screen sizes. Screen shots below of the problem. This first orange screen is correct on where I want the dots to be and the second one is wrong.
More Code
func configurePageControl() {
// The total number of pages that are available is based on how many available colors we have.
pageControl = UIPageControl(frame: CGRect(x: 0,y: UIScreen.main.bounds.maxY - 525,width: UIScreen.main.bounds.width,height: 50))
self.pageControl.numberOfPages = orderedViewControllers.count
self.pageControl.currentPage = 0
self.pageControl.tintColor = UIColor.black
self.pageControl.pageIndicatorTintColor = UIColor.white
self.pageControl.currentPageIndicatorTintColor = UIColor.black
self.view.addSubview(pageControl)
}
How I am calling the views
lazy var orderedViewControllers: [UIViewController] = {
return [self.newVc(viewController: "sbBlue"),
self.newVc(viewController: "sbRed")]
}()

Here is solution for your issue.
You can get maxY position of your green or orange view and change your code like as follow. It will set your pageControl's vertical position by removing 30 pixel from bottom of your green or orange view.
pageControl = UIPageControl(frame: CGRect(x: 0, y: yourOrangeView.bounds.maxY - 30, width: UIScreen.main.bounds.width, height: 50))
Or
pageControl = UIPageControl(frame: CGRect(x: 0, y: yourGreenView.bounds.maxY - 30, width: UIScreen.main.bounds.width, height: 50))
I hope this will fix your issue.

There are two problems here.
You should not be creating your own UIPageControl. UIPageViewController has a UIPageControl already; you should just use it.
If you insist on supplying your own (unnecessary) UIPageControl, you need to position it with auto layout so that it takes account of size changes. This code is wrong:
pageControl = UIPageControl(frame: CGRect(x: 0,y: UIScreen.main.bounds.maxY - 525,width: UIScreen.main.bounds.width,height: 50))
Don't give the page control a frame; give it auto layout constraints.

Related

Pin content view in UIScrollView to its bottom rather than its top edge

A UIScrollView pins its content view by default to its top edge, i.e. when you add some content to a scroll view with a vertical scrolling axis and the content's total height is smaller than the height of the whole scroll view, the content is displayed at the top of the scroll view.
Is there a way to change this behavior and make the scroll view pin its content view to its bottom?
(In other words: I would like the content to "grow from the bottom".)
it is possible to add a view to the scrollview in a certain position
this is simple example code:
class ViewController: UIViewController {
var scrollView: UIScrollView!
var views: UIView!
override func viewDidLoad() {
super.viewDidLoad()
views = UIView.init()
scrollView = UIScrollView.init()
scrollView.addSubview(views)
self.view.addSubview(scrollView)
addViewToBottomScroll()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
views.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 1300)
scrollView.frame = self.view.frame
scrollView.contentSize = views.frame.size
}
func addViewToScrollView() {
let label = UILabel(frame: CGRect(x: 0, y: 10, width: self.view.frame.width, height: 40))
label.text = "ScrollView"
label.textAlignment = .center
views.addSubview(label)
let bottomView = UIView(frame: CGRect(x: 15.0, y: 950.0, width: self.view.frame.width - 30, height: 300))
bottomView.backgroundColor = .yellow
views.addSubview(bottomView)
}
}
hopefully answer your question
The usual workaround is to flip the scroll view, then flip the content view.
e.g.
scrollView.transform = CGAffineTransform(scaleX: 1, y: -1)
contentView.transform = CGAffineTransform(scaleX: 1, y: -1)
I'd really like to know a cleaner solution myself.

How to set a custom background view properly with UiActivityIndicator

My app is using WKWebView to load my website. I need a UiActivityIndicator with a custom dark gray background view due to the UIActivityIndicator might be difficult to spot when it mixed up with my website's content. Previously, I followed https://coderwall.com/p/su1t1a/ios-customized-activity-indicator-with-swift to programmatically create an indicator. However, the tutorial is using default white and mine is large white with custom orange color. All I need just a backgroundView with an indicator inside of the backgroundView. Somehow it works until I noticed that the indicator is not that center and it ran off a little bit to the top left. Please see this image,
It is very obvious on my iPhone 5 and so on. So, I used another approach which is using auto layout. The background view is still not working as well. Here is my auto layout setup
This is my programmatically part.
loadingView.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
loadingView.center = self.view.center
loadingView.backgroundColor = UIColor(red:211/255,green:211/255,blue:211/255, alpha: 1)
loadingView.clipsToBounds = true
loadingView.layer.cornerRadius = 10
loadingIndicator.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
loadingIndicator.isOpaque = false
loadingIndicator.center = CGPoint(x: loadingView.frame.size.width / 2.0, y: loadingView.frame.size.height / 2.0)
loadingIndicator.backgroundColor = UIColor.gray
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
loadingIndicator.color = UIColor(red:232/255,green:126/255,blue:4/255,alpha:1.0)
loadingIndicator.hidesWhenStopped = true
loadingView.addSubview(loadingIndicator)
self.view.addSubview(loadingView)
I would prefer using auto layout.
There is no issue in either your auto layout setup nor the code you are trying.
The off-center issue actually seems to be an iOS bug when setting a custom color on a UIActivityIndicatorView.
You can see this for yourself.
Drag a basic UIActivityIndicatorView
Set a background color
Set it's style to "Large White"
Now set a color
This doesn't happen when the style is White or Gray
Tested it in Xcode 9.3 Storyboard as well as Simulator with Debug > Color Blended layers - ON
Try to change this code
let loadingView = UIView()
let loadingIndicator = UIActivityIndicatorView()
loadingView.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
loadingView.center = self.view.center
loadingView.backgroundColor = UIColor(red:211/255,green:211/255,blue:211/255, alpha: 1)
loadingView.clipsToBounds = true
loadingView.layer.cornerRadius = 10
loadingIndicator.frame = CGRect(x: 0, y: 0, width: 37, height: 37)
loadingIndicator.isOpaque = false
loadingIndicator.center = CGPoint(x: loadingView.bounds.size.width / 2, y: loadingView.bounds.size.height / 2)
loadingIndicator.backgroundColor = UIColor.gray
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
loadingIndicator.color = UIColor(red:232/255,green:126/255,blue:4/255,alpha:1.0)
loadingIndicator.hidesWhenStopped = true
loadingView.addSubview(loadingIndicator)
loadingIndicator.tag = 500
for subView in loadingView.subviews{
if subView.tag == 500{
print(subView.frame)
print("Bounds", subView.bounds)
}
}
loadingIndicator.startAnimating()
self.view.addSubview(loadingView)
As per style of indicator view is whiteLarge, by default its 37 so change and check.
For auto layout :
Drag UIView with 60*60 width and height.(Give width,height, horizontal center, vertical center to your super view.)
Drag Indicator view into Your UIView.(Give horizontal center, vertical center to your view.)
select Indicator view set style to white large and check its frame.(37 by default and other style 20).
set constraints like below image.

Can't fully scroll within UIScrollView

I have a UIImageView within a UIScrollView, and I want to be able to scroll around the dimensions of the "regular" photo dimensions. My issue is that I am able to scroll, however when it gets to the top or towards the bottom of the photo, the scroll position does not stay, instead it "bounces" and moves back up a little bit, and does not allow for the photo to stay in that position, how would I go about fixing this?
here is the code below:
scrollView.frame = CGRect(x: self.view.frame.width * 0, y: self.view.frame.height / 3, width: self.view.frame.width, height: self.view.frame.width)
self.view.addSubview(scrollView)
scrollView.delegate = self
let image = imageView.image
imageView.frame = CGRect(x: self.view.frame.width * 0, y: self.view.frame.height * 0, width: (image?.size.width)!, height: (image?.size.height)!)
imageView.frame = scrollView.bounds
imageView.contentMode = .scaleAspectFill
scrollView.addSubview(imageView)
An example would be if you had a full screen photo taken with the camera, and then when the photo is displayed within the view, the whole photo is not able to stay in its position when it is being scrolled.
You are doing a number of things wrong, and as mentioned you should move to auto-layout and constraints, however...
To get your image scrolling the way you are going:
// set scroll view frame to be full width of view, start 1/3 of the way down from the top, and make the height the same as the width
scrollView.frame = CGRect(x: 0, y: self.view.frame.height / 3, width: self.view.frame.width, height: self.view.frame.width)
// add the scroll view to the view
self.view.addSubview(scrollView)
// use "if let" so you're not force-unwrapping optionals
if let image = imageView.image {
// set the imageView's frame to the size of the image
imageView.frame = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
// add the imageView to the scroll view
scrollView.addSubview(imageView)
// set the contentSize of the scroll view - the "scrollable area" - to the size of the image view
scrollView.contentSize = imageView.bounds.size
}
Bouncing is an optional behavior in UIScrollView (and its subclasses, including UiTableView). You can turn it on/off via the bounces property, or in Interface Builder.
I usually bundle desired ScrollView properties together in a convenience method (or you could use UIAppearance) to ensure that all of my views have shared behavior.

Unable to properly configure UIScrollView (Offset on top)

I have been fighting with this all morning and can't seem to find a solution. I have created a UIImageView, filled it with red, then added it to a UIScrollView and set the contentSize to the size of the UIImageView. If I print the contentOffset i see (0, 0) and if I print the contentSize and the UIImageView.frame.size they are the same but the red "image" always appears smaller than what the scrollView thinks the contentSize is.
If I scroll all the way to the top I see a cyan stripe about 100 pixels high above the red image and the scroll bar will not make it all the way to the top of what I believe the top of my scroll view to be. Although the top of the scroll bar does line up with the top of my red window so it would seem as though the scroll view is confused as to where it actually lives. Or more likely, I'm confused
Here is my what seems like very simple code...
imgHorizon = UIImage.init(named:"horizon")!
imgBezel = UIImage.init(named:"bezel_transparent")!
imgWings = UIImage.init(named:"wings_transparent")!
imgViewHorizon = UIImageView.init()
imgViewBezel = UIImageView.init()
imgViewWings = UIImageView.init()
svHorizon = UIScrollView.init()
super.init(coder: aDecoder)
imgViewHorizon = UIImageView(frame: CGRect(x: 0, y: 0, width: imgBezel.size.width, height: imgHorizon.size.height))
imgViewHorizon.backgroundColor = UIColor.red
imgViewBezel = UIImageView(frame: CGRect(x: 0, y: 0, width: imgBezel.size.width, height: imgBezel.size.height))
imgViewBezel.contentMode = UIViewContentMode.center
imgViewBezel.clipsToBounds = true
imgViewBezel.image = imgBezel
imgViewWings = UIImageView(frame: CGRect(x: 0, y: 0, width: imgBezel.size.width, height: imgBezel.size.height))
imgViewWings.contentMode = UIViewContentMode.center
imgViewWings.clipsToBounds = true
imgViewWings.image = imgWings
svHorizon = UIScrollView(frame: CGRect(x: 0, y: 0, width: imgBezel.size.width, height: imgBezel.size.width))
svHorizon.contentSize = CGSize(width: imgBezel.size.width, height: imgHorizon.size.height)
svHorizon.contentMode = UIViewContentMode.scaleToFill
svHorizon.bounces = false
svHorizon.backgroundColor = UIColor.cyan
svHorizon.contentOffset = CGPoint(x: 0, y: 0)
svHorizon.addSubview(imgViewHorizon)
addSubview(svHorizon)
addSubview(imgViewBezel)
addSubview(imgViewWings)
From the discussion in the comments it turns out that the Adjust Scroll View Insets option was checked in the attributes inspector of the ViewController. Unchecking it resolved the problem. Have a look at the image below. You need to uncheck the highlighted option.

Are iOS "views" and HTML divs similar?

I found that placing a view in my app and sizing it to my needs is pretty similar to divs in HTML. Should I be using them this way?
Here's an example of a place I want to use a view.
I want to fill that in, should I be using a view here? or something more semantical?
End result with a view:
If you want to set a rectangle somewhere you could definitely use an UIView(), If you´re using your storyboard make sure to set the right constraint and if you´re doing it programmatically you could do the following to get it work with all phone sizes:
Swift 3.0:
let screen = UIScreen.main.bounds
let anotherView = UIView(frame: CGRect(x: 0, y: 0, width: screen.width, height: 45))
anotherView.backgroundColor = UIColor.blue
view.addSubview(anotherView)
Swift 2.x:
let screen = UIScreen.mainScreen().bounds
let anotherView = UIView(frame: CGRect(x: 0, y: 0, width: screen.width, height: 45))
anotherView.backgroundColor = UIColor.blueColor()
view.addSubview(anotherView)

Resources