Changing page control dots with images swift - ios

I'm trying to change the dots in page control with some images..
Here the code i have tried:
import UIKit
class PageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
// MARK: Data source functions.
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return orderedViewControllers.last
// Uncommment the line below, remove the line above if you don't want the page control to loop.
// return nil
}
guard orderedViewControllers.count > previousIndex else {
return nil
}
return orderedViewControllers[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers.count
// the first view controller.
guard orderedViewControllersCount != nextIndex else {
return orderedViewControllers.first
// Uncommment the line below, remove the line above if you don't want the page control to loop.
// return nil
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
return orderedViewControllers[nextIndex]
}
lazy var orderedViewControllers: [UIViewController] = {
return [self.newVc(viewController: "sbYellow"),
self.newVc(viewController: "sbRed"),
self.newVc(viewController: "sbBlue")]
}()
var pageControl = UIPageControl()
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
// This sets up the first view that will show up on our page control
if let firstViewController = orderedViewControllers.first {
setViewControllers([firstViewController],
direction: .forward,
animated: true,
completion: nil)
}
let pageControl = CustomPageControl(frame: CGRect(x: 100, y: 100, width: 104, height: 40))
pageControl.numberOfPages = 3
pageControl.currentPage = 0
self.view.addSubview(pageControl)
/*self.delegate = self
configurePageControl()*/
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
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 - 50,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)
}
func newVc(viewController: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: viewController)
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
let pageContentViewController = pageViewController.viewControllers![0]
self.pageControl.currentPage = orderedViewControllers.index(of: pageContentViewController)!
}
}
class CustomPageControl: UIPageControl {
var imageToBeReplacedByDot: UIImage {
return imageLiteral(resourceName: "av_timer - material")// Image you want to
replace with dots
}
var circleImage: UIImage {
return imageLiteral(resourceName: "cancel - material")//Default Image
}
override var numberOfPages: Int {
didSet {
updateDots()
}}
override var currentPage: Int {
didSet {
updateDots()
}}
override func awakeFromNib() {
super.awakeFromNib()
self.pageIndicatorTintColor = UIColor.clear
self.currentPageIndicatorTintColor = UIColor.clear
self.clipsToBounds = false
}
func updateDots() {
var i = 0
for view in self.subviews {
var imageView = self.imageView(forSubview: view)
if imageView == nil {
if i == 0 {
imageView = UIImageView(image: imageToBeReplacedByDot)
} else {
imageView = UIImageView(image: circleImage)
}
imageView!.center = view.center
view.addSubview(imageView!)
view.clipsToBounds = false
}
if i == self.currentPage {
imageView!.alpha = 1.0
} else {
imageView!.alpha = 0.5
}
i += 1
}
}
fileprivate func imageView(forSubview view: UIView) -> UIImageView? {
var dot: UIImageView?
if let dotImageView = view as? UIImageView {
dot = dotImageView
} else {
for foundView in view.subviews {
if let imageView = foundView as? UIImageView {
dot = imageView
break
}
}
}
return dot
}
}
Which is working fine and changing the dots with images... the issue is that the image will not change if i scrolled!.. also i want to position the page control on center top of the screen..
How to achieve that?
Screenshot:

You can use this code for Reference:
import UIKit
class LocationPageControl: UIPageControl {
let locationArrow: UIImage = UIImage(named: "locationArrow")!
let pageCircle: UIImage = UIImage(named: "pageCircle")!
override var numberOfPages: Int {
didSet {
updateDots()
}
}
override var currentPage: Int {
didSet {
updateDots()
}
}
override func awakeFromNib() {
super.awakeFromNib()
self.pageIndicatorTintColor = UIColor.clear
self.currentPageIndicatorTintColor = UIColor.clear
self.clipsToBounds = false
}
func updateDots() {
var i = 0
for view in self.subviews {
var imageView = self.imageView(forSubview: view)
if imageView == nil {
if i == 0 {
imageView = UIImageView(image: locationArrow)
} else {
imageView = UIImageView(image: pageCircle)
}
imageView!.center = view.center
view.addSubview(imageView!)
view.clipsToBounds = false
}
if i == self.currentPage {
imageView!.alpha = 1.0
} else {
imageView!.alpha = 0.5
}
i += 1
}
}
fileprivate func imageView(forSubview view: UIView) -> UIImageView? {
var dot: UIImageView?
if let dotImageView = view as? UIImageView {
dot = dotImageView
} else {
for foundView in view.subviews {
if let imageView = foundView as? UIImageView {
dot = imageView
break
}
}
}
return dot
}
}
Note:- Set your image according as per your need

Related

How to customize UIPageControl?

I am a beginner in swift
I want to customize my UIPageControl on only code
The UIPageControl style I want is:I can change the little dot above and when I switch to it he can change to another style
I found an article that provides a how-to, which can be done using
It's good, but I don't understand how it works
The method is attached for reference by friends who have the same needs
but that's not my real intention
I want to understand how this program works, can someone explain it to me? or provide a more simple and understandable method
I know so much code is because it supports versions below ios14
but I think this part may be omitted in explaining
The reason why it is not removed is to seek better and more complete code.
thank everybody
import UIKit
class CZPageControl: UIPageControl {
var currentImage: UIImage?
var inactiveImage: UIImage?
var currentTintColor: UIColor?
var inactiveTintColor: UIColor?
override init(frame: CGRect) {
super.init(frame: frame)
self.isUserInteractionEnabled = false
if #available(iOS 14.0, *) {
self.allowsContinuousInteraction = false
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var currentPage: Int {
didSet {
updateDots()
}
}
func updateDots() {
guard let currentImage = self.currentImage, let inactiveImage = self.inactiveImage else {
return
}
if #available(iOS 14.0, *) {
guard let dotContentView = findIndicatorContentView() else {
return
}
for (index, view) in dotContentView.subviews.enumerated() {
if view.isKind(of: UIImageView.self) {
self.currentPageIndicatorTintColor = self.currentTintColor
self.pageIndicatorTintColor = self.inactiveTintColor
let indicatorView = view as! UIImageView
indicatorView.image = nil
if index == self.currentPage {
indicatorView.image = currentImage.withRenderingMode(.alwaysTemplate)
} else {
indicatorView.image = inactiveImage.withRenderingMode(.alwaysTemplate)
}
}
}
} else {
for (index, view) in self.subviews.enumerated() {
if let dot = imageViewForSubview(view, currentPage: index) {
var size = CGSize.zero
if index == self.currentPage {
dot.tintColor = self.currentTintColor
dot.image = currentImage.withRenderingMode(.alwaysTemplate)
size = dot.image!.size
} else {
dot.tintColor = self.inactiveTintColor
dot.image = inactiveImage.withRenderingMode(.alwaysTemplate)
size = dot.image!.size
}
if let superview = dot.superview {
let x = (superview.frame.size.width - size.width) / 2.0
let y = (superview.frame.size.height - size.height) / 2.0
dot.frame = CGRect(x: x, y: y, width: size.width, height: size.height)
}
}
}
}
}
// iOS 14之前创建UIImageView使用
func imageViewForSubview(_ view: UIView, currentPage: Int) -> UIImageView? {
var dot: UIImageView?
if view.isKind(of: UIView.self) {
for subview in view.subviews {
if subview.isKind(of: UIImageView.self) {
dot = (subview as! UIImageView)
break
}
}
if dot == nil {
dot = UIImageView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height))
view.addSubview(dot!)
}
} else {
dot = (view as! UIImageView)
}
return dot
}
#available(iOS 14.0, *)
func findIndicatorContentView() -> UIView? {
for contentView in self.subviews {
if let contentViewClass = NSClassFromString("_UIPageControlContentView"), contentView.isKind(of: contentViewClass) {
for indicatorContentView in contentView.subviews {
if let indicatorContentViewClass = NSClassFromString("_UIPageControlIndicatorContentView"), indicatorContentView.isKind(of: indicatorContentViewClass) {
return indicatorContentView
}
}
}
}
return nil
}
}
You will have to call "updateDots()" in viewDidAppear() and your valueChanged handler for the page control.
import UIKit
class CustomImagePageControl: UIPageControl {
let activeImage:UIImage = UIImage(named: "SelectedPage")!
let inactiveImage:UIImage = UIImage(named: "UnselectedPage")!
override func awakeFromNib() {
super.awakeFromNib()
self.pageIndicatorTintColor = UIColor.clear
self.currentPageIndicatorTintColor = UIColor.clear
self.clipsToBounds = false
}
func updateDots() {
var i = 0
for view in self.subviews {
if let imageView = self.imageForSubview(view) {
if i == self.currentPage {
imageView.image = self.activeImage
} else {
imageView.image = self.inactiveImage
}
i = i + 1
} else {
var dotImage = self.inactiveImage
if i == self.currentPage {
dotImage = self.activeImage
}
view.clipsToBounds = false
view.addSubview(UIImageView(image:dotImage))
i = i + 1
}
}
}
fileprivate func imageForSubview(_ view:UIView) -> UIImageView? {
var dot:UIImageView?
if let dotImageView = view as? UIImageView {
dot = dotImageView
} else {
for foundView in view.subviews {
if let imageView = foundView as? UIImageView {
dot = imageView
break
}
}
}
return dot
}
}

swift: UIPageViewController size

I have UIPageViewController with spine mid location. Now my 2 pages occupy the whole screen. But I want to change size of my flipping pages that I can create buttons in other part of controller. How to do it?
code:
import UIKit
class PageViewController: UIViewController {
#IBOutlet weak var PageControl: UIPageControl!
var pageViewController: UIPageViewController?
var images = ["book1page1.png","book1","book1","book1page2.png","book1page1.png","book1page2.png"]
var pendingIndex: Int?
override func viewDidLoad() {
super.viewDidLoad()
createPageViewController()
setupPageControll()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func createPageViewController() {
// Instantiate the PageViewController
let pageController = self.storyboard?.instantiateViewController(withIdentifier: "PageViewController") as! UIPageViewController
pageController.dataSource = self
pageController.delegate = self
if images.count > 0{
let firstController = getContentViewController(withIndex: 0)!
let contentControllers = [firstController]
pageController.setViewControllers(contentControllers, direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
}
pageViewController = pageController
self.addChildViewController(pageViewController!)
//self.view.addSubview(pageViewController!.view)
self.view.insertSubview(pageViewController!.view, at: 0)
pageViewController!.didMove(toParentViewController: self)
}
//Setup Pagination Icons and count
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return images.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return 0
}
func setupPageControll(){
let apperance = UIPageControl.appearance()
apperance.pageIndicatorTintColor = UIColor.gray
apperance.currentPageIndicatorTintColor = UIColor.white
apperance.backgroundColor = UIColor.clear
}
func currentControllerIndex() -> Int{
let pageItemController = self.currentConroller()
if let controller = pageItemController as? ContentViewController {
return controller.itemIndex
}
return -1
}
///////////////////////////////////////////////
func currentConroller() -> UIViewController?{
if (self.pageViewController?.viewControllers?.count)! > 0{
return self.pageViewController?.viewControllers![0]
}
return nil
}
func getContentViewController(withIndex index: Int) -> ContentViewController? {
if index < images.count{
let contentVC = self.storyboard?.instantiateViewController(withIdentifier: "ContentViewController") as! ContentViewController
contentVC.itemIndex = index
contentVC.imageName = images[index]
return contentVC
}
return nil
}
}
extension PageViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
pendingIndex = (pendingViewControllers.first as! ContentViewController).itemIndex
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
let currentIndex = pendingIndex
if let index = currentIndex {
self.PageControl.currentPage = index
}
}
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentViewController
if contentVC.itemIndex > 0 {
return getContentViewController(withIndex: contentVC.itemIndex - 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let contentVC = viewController as! ContentViewController
if contentVC.itemIndex + 1 < images.count {
return getContentViewController(withIndex: contentVC.itemIndex + 1)
}
return nil
}
}
Here you have instantiate UIPageViewController (id:"PageViewController") and add as subview inside the UIViewController so if you want create UIButton you can create but if its want to visible in front of this UIPageViewController You can put self.view.insertSubview(pageViewController!.view, at: 0) to says your UIViewController to put this subview at index 0 (means behind the every subviews)
Below I have given code: Add Subview at index 0 and Make Size of the PageViewController using pageController.view.frame = CGRect(x: 50, y: 50, width: self.view.frame.width - (5.0 * 20.0), height: self.view.frame.height - (2.0 * 50.0)) also Added two buttons calls "Next" and "Previous' at the bottom of UIPageController
Check Blow Code:
func createPageViewController() {
let pageController = self.storyboard?.instantiateViewController(withIdentifier: "PageViewController") as! UIPageViewController
pageController.isDoubleSided = true
pageController.dataSource = self
pageController.delegate = self
if images.count > 1{
let firstController = getContentViewController(withIndex: 0)!
let secondController = getContentViewController(withIndex: 1)!
let contentControllers = [firstController,secondController]
pageController.setViewControllers(contentControllers, direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
}
pageViewController = pageController
self.addChildViewController(pageViewController!)
self.view.insertSubview(pageViewController!.view, at: 0)
pageController.view.frame = CGRect(x: 50, y: 50, width: self.view.frame.width - (5.0 * 20.0), height: self.view.frame.height - (2.0 * 50.0))
pageController.view.layer.borderColor = UIColor.lightGray.cgColor
pageController.view.layer.borderWidth = 1.0
pageViewController!.didMove(toParentViewController: self)
//Next Page Button
let nextButton = UIButton()
nextButton.frame = CGRect(x: pageController.view.frame.maxX - 75, y: pageController.view.frame.maxY + 5, width: 75, height: 50)
nextButton.backgroundColor = UIColor.blue
nextButton.setTitle("Next", for: .normal)
nextButton.addTarget(self, action: #selector(buttonActionNext), for: .touchUpInside)
self.view.addSubview(nextButton)
//Previous Page Button
let previousButton = UIButton()
previousButton.frame = CGRect(x: pageController.view.frame.minX, y: pageController.view.frame.maxY + 5, width: 75, height: 50)
previousButton.backgroundColor = UIColor.blue
previousButton.setTitle("Previous", for: .normal)
previousButton.addTarget(self, action: #selector(buttonActionPrevious), for: .touchUpInside)
self.view.addSubview(previousButton)
}
#objc func buttonActionNext(sender: UIButton!) {
print("Next page")
}
#objc func buttonActionPrevious(sender: UIButton!) {
print("Previous Page")
}
You need to change the frame
pageViewController!.view.frame = ///
self.view.insertSubview(pageViewController!.view, at: 0)

How hide blur for UIPopoverPresentationController in swift?

I've implemented popover for UIButton:
#objc func showList(sender: AnyObject?) {
guard let buttonView = sender?.value(forKey: "view") as? UIButton else { return }
guard let popVC = R.storyboard.first.VC() else { return }
popVC.modalPresentationStyle = .popover
let popOverVC = popVC.popoverPresentationController
popOverVC?.delegate = self
popOverVC?.sourceView = buttonView
popOverVC?.sourceRect = CGRect(x: 0, y: 190, width: 0, height: 0)
popOverVC?.permittedArrowDirections = .init(rawValue: 0)
popVC.preferredContentSize = CGSize(width: 150, height: 250)
showedViewController.present(popVC, animated: true, completion: nil)
}
extension VCInteractor: UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
}
It's working good, but I need one fix - I want to hide UIVisualEffectBackdropView for my popover (it's like blur under my UITableViewController). So, I can't find any info how to disable (hide) this blur, do you have any ideas?
I've fixed my issue with my custom class
class PopoverBackgroundView: UIPopoverBackgroundView {
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.shadowColor = UIColor.clear.cgColor
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override static func contentViewInsets() -> UIEdgeInsets {
return UIEdgeInsets.zero
}
override static func arrowHeight() -> CGFloat {
return 0
}
override var arrowDirection: UIPopoverArrowDirection {
get { return UIPopoverArrowDirection.down }
set {
setNeedsLayout()
}
}
override var arrowOffset: CGFloat {
get { return 0 }
set {
setNeedsLayout()
}
}
}
and I've added it like that
popOverVC?.popoverBackgroundViewClass = PopoverBackgroundView.self
that's all
here i have a very simple solution.
let appearance = UIVisualEffectView.appearance(whenContainedInInstancesOf: [NSClassFromString("_UIPopoverStandardChromeView")! as! UIAppearanceContainer.Type])
appearance.effect = UIVisualEffect()
add the code to the AppDelegate.swift file or anywhere the app is getting initialized.
I suggest adding this to the PopoverBackgroundView that Vadim Nikolaev has posted above. This removes the "clear halo" effect when removing the blur.
`override func didMoveToWindow() {
super.didMoveToWindow()
if #available(iOS 13, *) {
// iOS 13 (or newer)
if let window = UIApplication.shared.keyWindow {
let transitionViews = window.subviews.filter { String(describing: type(of: $0)) == "UITransitionView" }
for transitionView in transitionViews {
let shadowView = transitionView.subviews.filter { String(describing: type(of: $0)) == "_UICutoutShadowView" }.first
shadowView?.isHidden = true
}
}
}
}`

Strange UITextField in UINavigationBar constraint issues only on iOS 10 or higher

After I updated my iPhone to iOS 10 I noticed this very strange constraint issue with a UITextField in a UINavigationBar has appeared in my app iOS Tipped. I thought updating my Xcode project to swift 3 would fix it but the problem persists. For some reason this ins't an issue with iOS 9 and lower.
Please download my app Tipped... it's free and you will be able to see
the issue described below.
1: When I launch my app and tap the tab bar to the viewController with the textfield constraint issue in the navigation bar I get this
2: When I press another tab bar option (like the home page) the tap the search tab bar option (navigating back to the page with the issue) I get this
3: Also when I tap one of the segment buttons on the search page with the constraint issue. The constraint issue will reappear and the textfield will go too far to the right.
I have tried the below code to try to fix the problem but nothing seems to be working. Really stuck here any help would be like awesome.
override func viewWillAppear(_ animated: Bool) {
// searchTextField.becomeFirstResponder()
print("viewWillAppear: searchPageViewController")
navigationView.setNeedsLayout()
navigationView.updateConstraintsIfNeeded()
searchTextField.updateConstraints()
searchTextField.setNeedsLayout()
}
Below is the code from the viewcontroller that I am having trouble with.
class SearchPageViewController: UIPageViewController, UISearchBarDelegate, UISearchDisplayDelegate, UIPageViewControllerDataSource, UIPageViewControllerDelegate, UIScrollViewDelegate, UITextFieldDelegate {
//%%% customizeable button attributes
let X_BUFFER:CGFloat = 0.0; //%%% the number of pixels on either side of the segment
let Y_BUFFER:CGFloat = 0.0; //%%% number of pixels on top of the segment
let HEIGHT:CGFloat = 44.0; //%%% height of the segment
//%%% customizeable selector bar attributes (the black bar under the buttons)
let BOUNCE_BUFFER:CGFloat = 10.0; //%%% adds bounce to the selection bar when you scroll
let ANIMATION_SPEED:CGFloat = 0.2; //%%% the number of seconds it takes to complete the animation
let SELECTOR_Y_BUFFER:CGFloat = 40.0; //%%% the y-value of the bar that shows what page you are on (0 is the top)
let SELECTOR_HEIGHT:CGFloat = 4.0; //%%% thickness of the selector bar
let X_OFFSET:CGFloat = 0.0; //%%% for some reason there's a little bit of a glitchy offset. I'm going to look for a better workaround in the future
var navigationView = UIView()
var containerView = UIView()
var buttonText:NSArray = []
var pageScrollView:UIScrollView!
var currentPageIndex:Int!
var selectionBar = UIView()
var buttonOneTap:Bool = false
var buttonTwoTap:Bool = false
fileprivate var _controllerEnum: ControllerEnum = ControllerEnum()
fileprivate var _dict: [UIViewController: ControllerEnum] = [:]
var editView = UIView()
// var delegate: ViewControllerDelegate? = nil
// var userList = NSMutableArray()
// var searchString = String()
// var viewControllerArray:NSMutableArray = NSMutableArray()
var blogSearchCollectionViewController:BlogSearchCollectionViewController!
// var pageViewController: UIPageViewController!
var pageTitles: NSArray!
var pageImages: NSArray!
let searchController = UISearchController(searchResultsController: nil)
#IBOutlet weak var searchBarView: UIView!
#IBOutlet weak var searchTextField: UITextField!
//Stretching the searchTextField full width of navbar
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
widenTextField()
}
func widenTextField() {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
self.searchTextField.leftView = paddingView
self.searchTextField.leftViewMode = .always
let paddingViewRight = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
self.searchTextField.rightView = paddingViewRight
self.searchTextField.rightViewMode = .always
searchBarView.frame = CGRect(x: 16, y: 5, width: self.view.frame.width, height: 34)
// var frame:CGRect = self.searchTextField.frame
// frame.size.width = self.view.frame.width
// self.searchTextField.frame = CGRectMake(16, 5, self.view.frame.width, 33)
}
// TextFieldDelegates
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// textField.resignFirstResponder()
handleTap(editView)
if currentPageIndex == 0 {
let vc = self.viewControllerAtIndex(currentPageIndex) as BlogSearchCollectionViewController
// vc.loadUsers(textField.text.lowercaseString)
vc.searchText = textField.text!.lowercased()
vc.loadObjects()
vc.showActivityIndicator()
let viewControllers = NSArray(object: vc)
setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: false, completion: nil)
} else if currentPageIndex == 1 {
let vc = self.viewControllerAtIndexTwo(currentPageIndex) as PhotoSearchController
vc.search(textField.text!.lowercased())
vc.showActivityIndicator()
let viewControllers = NSArray(object: vc)
setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: false, completion: nil)
}
return true
}
// var lastTextFieldEdit:String!
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
showEditView()
if let text = textField.text {
if text.characters.count > 0 {
DispatchQueue.main.async{
textField.selectAll(nil)
}
}
}
searchTextField.textAlignment = NSTextAlignment.left
return true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
print(textField)
}
override func viewWillAppear(_ animated: Bool) {
// searchTextField.becomeFirstResponder()
print("viewWillAppear: searchPageViewController")
}
override func viewDidAppear(_ animated: Bool) {
}
override func viewDidLoad() {
super.viewDidLoad()
self.setupSegmentButtons()
self.setupPage()
currentPageIndex = 0
// self.navigationItem.titleView = searchTextField
}
//Mark: SearchBar stuff
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
// searchController.searchBar.showsCancelButton = true
return true
}
func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
searchController.searchBar.showsCancelButton = true
// for subView in searchController.view.subviews {
// if let dimView = subView as? UIView {
// dimView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
// }
// }
return true
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
for subView in searchController.view.subviews {
}
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
print("hithere")
searchController.searchBar.showsCancelButton = true
// searchController.dimsBackgroundDuringPresentation = false
print("searchController.view.subviews1: - \(searchController.searchBar.subviews)")
for subView in searchController.view.subviews {
print("searchController.view.subviews2: - \(searchController.view.subviews)")
if let dimView = subView as? UIView {
dimView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.0)
}
}
// searchController.dismissViewControllerAnimated(true, completion: nil)
if currentPageIndex == 0 {
let vc = self.viewControllerAtIndex(currentPageIndex) as BlogSearchCollectionViewController
// vc.loadUsers(searchBarString.lowercaseString)
let viewControllers = NSArray(object: vc)
setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: false, completion: nil)
} else if currentPageIndex == 1 {
let vc = self.viewControllerAtIndexTwo(currentPageIndex) as PhotoSearchController
vc.search(searchBarString.lowercased())
let viewControllers = NSArray(object: vc)
setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: false, completion: nil)
}
}
var searchBarString:String!
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchController.searchBar.showsCancelButton = true
let uiButton = searchController.searchBar.value(forKey: "cancelButton") as! UIButton
uiButton.setTitle("Cancel", for: UIControlState())
uiButton.setTitleColor(UIColor.black, for: UIControlState())
uiButton.titleLabel!.font = UIFont(name: "Helvetica Neue", size: 17)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchBarString = searchText
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func setupSegmentButtons() {
navigationView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: HEIGHT))
navigationView.backgroundColor = UIColor.brown
let numControllers = 2
// if buttonText == NSNotFound {
buttonText = NSArray(objects: "BLOGS", "TIPS")
// }
let buttonOne:UIButton = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width/2, height: HEIGHT))
let buttonTwo:UIButton = UIButton(frame: CGRect(x: self.view.frame.size.width/2, y: 0, width: self.view.frame.size.width/2, height: HEIGHT))
navigationView.addSubview(buttonOne)
navigationView.addSubview(buttonTwo)
buttonOne.tag = 0
buttonOne.backgroundColor = UIColor.white
buttonOne.addTarget(self, action: #selector(SearchPageViewController.tapSegmentButtonAction(_:)), for: UIControlEvents.touchUpInside)
buttonOne.setTitle(buttonText[0] as? String, for: UIControlState())
buttonOne.setTitleColor(UIColor.black, for: UIControlState())
buttonOne.titleLabel!.font = UIFont(name: "Interstate-Bold", size: 17)!
buttonTwo.tag = 1
buttonTwo.backgroundColor = UIColor.white
buttonTwo.addTarget(self, action: #selector(SearchPageViewController.tapSegmentButtonAction(_:)), for: UIControlEvents.touchUpInside)
buttonTwo.setTitle(buttonText[1] as? String, for: UIControlState())
buttonTwo.setTitleColor(UIColor.black, for: UIControlState())
buttonTwo.titleLabel!.font = UIFont(name: "Interstate-Bold", size: 17)
self.view.addSubview(navigationView)
self.setupSelector()
}
func setupSelector() {
selectionBar = UIView(frame: CGRect(x: X_BUFFER-X_OFFSET, y: SELECTOR_Y_BUFFER,width: (self.view.frame.size.width-2*X_BUFFER)/2, height: SELECTOR_HEIGHT))
selectionBar.backgroundColor = UIColor(red: 251/255, green: 73/255, blue: 90/255, alpha: 1.0)
// selectionBar.alpha = 1
navigationView.addSubview(selectionBar)
}
func setupPage() {
// self.navigationItem.titleView = searchTextField
view.backgroundColor = UIColor.white
//TextFieldStuff
searchTextField.delegate = self
searchTextField.placeholder = "Search for blogs"
searchTextField.textAlignment = NSTextAlignment.center
searchTextField.autocorrectionType = .no
//TextField is editing translucent view
editView.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.6)
editView.frame = CGRect(x: 0, /*self.navigationController!.navigationBar.frame.size.height + 20 +*/ y: HEIGHT, width: self.view.frame.size.width, height: self.view.frame.size.height - (self.navigationController!.navigationBar.frame.size.height + 20 + HEIGHT))
self.view.addSubview(editView)
editView.isHidden = true
//tapGesture
editView.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(SearchPageViewController.handleTap(_:)))
editView.addGestureRecognizer(tapGesture)
let pageControl = UIPageControl()
pageControl.backgroundColor = UIColor.white
self.pageTitles = NSArray(objects: "Explore", "Today Widget")
self.pageImages = NSArray(objects: "page1", "page2")
//PageViewControllers
delegate = self
dataSource = self
let vc = self.viewControllerAtIndex(0) as BlogSearchCollectionViewController
// vc.loadUsers("")
vc.searchText = ""
vc.loadObjects()
vc.showActivityIndicator()
let viewControllers = NSArray(object: vc)
setViewControllers(viewControllers as? [UIViewController], direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
print("pageSetUp:- \(currentPageIndex)")
self.syncScrollView()
}
func handleTap(_ sender : UIView) {
// searchController.resignFirstResponder()
searchTextField.resignFirstResponder()
searchTextField.textAlignment = NSTextAlignment.center
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.editView.alpha = 0
}, completion: { (success:Bool) -> Void in
if success {
self.editView.isHidden = true
}
})
// UIView.animateWithDuration(0.5, animations: { () -> Void in
// self.editView.alpha = 0
// })
print("Tap Gesture recognized")
}
func showEditView() {
editView.alpha = 0
editView.isHidden = false
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.editView.alpha = 0.6
})
}
func viewControllerAtIndex(_ index: Int) -> BlogSearchCollectionViewController {
let vc: BlogSearchCollectionViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BlogSearchCollectionViewController") as! BlogSearchCollectionViewController
return vc
}
func viewControllerAtIndexTwo(_ index: Int) -> PhotoSearchController {
let vc: PhotoSearchController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoSearchController") as! PhotoSearchController
// currentPageIndex = vc.pageIndex
return vc
}
func syncScrollView() {
let x = self.view.subviews
var view:UIView!
for view in x {
if view.isKind(of: UIScrollView.self) {
pageScrollView = view as! UIScrollView
pageScrollView.delegate = self
}
}
}
//%%% when you tap one of the buttons, it shows that page,
//but it also has to animate the other pages to make it feel like you're crossing a 2d expansion,
//so there's a loop that shows every view controller in the array up to the one you selected
//eg: if you're on page 1 and you click tab 3, then it shows you page 2 and then page 3
func tapSegmentButtonAction(_ button:UIButton) {
if buttonOneTap == false && buttonTwoTap == false {
let tempIndex:Int = self.currentPageIndex
//%%% check to see if you're going left -> right or right -> left
// println("buttonTag + tempIndex \(button.tag) \(tempIndex)")
if button.tag > tempIndex {
//%%% scroll through all the objects between the two points
buttonOneTap = true
// var i = tempIndex+1
// for i in stride(from:i, through:(button.tag), by: 1) {
for tempIndex in 0..<button.tag {
// for var i = tempIndex+1; i<=button.tag; i += 1 {
// println(i)
let vc: PhotoSearchController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoSearchController") as! PhotoSearchController
let viewControllers = NSArray(object: vc)
setViewControllers(viewControllers as? [UIViewController] /*[getController(.Debts)!]viewControllerArray.objectAtIndex(i) as! [AnyObject]*/, direction: UIPageViewControllerNavigationDirection.forward, animated: true, completion: { (success:Bool) -> Void in
//%%% if the action finishes scrolling (i.e. the user doesn't stop it in the middle),
//then it updates the page that it's currently on
if success == true {
self.buttonOneTap = false
self.updateCurrentPageIndex(1)
// self.searchController.searchBar.placeholder = "Search for tips"
// let txtField = self.navigationItem.titleView as! UITextField
// txtField.placeholder = "Search for tips"
self.searchTextField.placeholder = "Search for tips"
}
})
}
//%%% this is the same thing but for going right -> left
} else if button.tag < tempIndex {
buttonTwoTap = true
// var i = tempIndex+1
// for i in stride(from:i, through:(button.tag), by: -1) {
// for var i = tempIndex-1; i >= button.tag; i -= 1 {
for tempIndex in (0...button.tag).reversed() {
// println(i)
let vc: BlogSearchCollectionViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BlogSearchCollectionViewController") as! BlogSearchCollectionViewController
// vc.loadUsers("")
vc.searchText = ""
vc.loadObjects()
vc.showActivityIndicator()
let viewControllers = NSArray(object: vc)
setViewControllers(viewControllers as? [UIViewController] /*[getController(_controllerEnum)!] viewControllerArray.objectAtIndex(i) as! [AnyObject]*/, direction: UIPageViewControllerNavigationDirection.reverse, animated: true, completion: { (success:Bool) -> Void in
if success == true {
self.buttonTwoTap = false
self.updateCurrentPageIndex(0)
// self.searchController.searchBar.placeholder = "Search for blogs"
// let txtField = self.navigationItem.titleView as! UITextField
// txtField.placeholder = "Search for blogs"
self.searchTextField.placeholder = "Search for blogs"
}
})
}
}
}
}
func updateCurrentPageIndex(_ newIndex:Int) {
self.currentPageIndex = newIndex
}
//%%% makes sure the nav bar is always aware of what page you're on
//in reference to the array of view controllers you gave
//%%% method is called when any of the pages moves.
var xFromCenter:CGFloat!
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// println(self.currentPageIndex)
//It extracts the xcoordinate from the center point and instructs the selection bar to move accordingly
xFromCenter = self.view.frame.size.width-scrollView.contentOffset.x
print(xFromCenter)
// if xFromCenter > 0 && currentPageIndex == 0 {
// updateCurrentPageIndex(0)
// }
// println(self.currentPageIndex)
var a = X_BUFFER + selectionBar.frame.size.width
var b = CGFloat(currentPageIndex) - X_OFFSET
let xCoor = selectionBar.frame.size.width * CGFloat(self.currentPageIndex)
// println(xCoor)
//%%% checks to see what page you are on and adjusts the xCoor accordingly.
//i.e. if you're on the second page, it makes sure that the bar starts from the frame.origin.x of the
//second tab instead of the beginning
selectionBar.frame = CGRect(x: xCoor - xFromCenter/2, y: selectionBar.frame.origin.y, width: selectionBar.frame.size.width, height: selectionBar.frame.size.height)
}
// MARK: - Page View Controller Data Source
var vcOne:BlogSearchCollectionViewController!
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
var index:Int = currentPageIndex
if index == NSNotFound || index == 0 {
return nil
}
// println(currentPageIndex)
index -= 1
let vcOne = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BlogSearchCollectionViewController") as! BlogSearchCollectionViewController
// currentPageIndex = vc.pageIndex
// println("actaulIndexBlogSearchCollectionViewController: - \(actaulIndex)")
return vcOne
// return getController(_dict[viewController]!.prevIndex())
}
var vcTwo:PhotoSearchController!
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
var index:Int = currentPageIndex
if index == NSNotFound {
return nil
}
index += 1
if index == buttonText.count {
return nil
}
vcTwo = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PhotoSearchController") as! PhotoSearchController
// currentPageIndex = vc.pageIndex
// if vc.pageIndex == 1 && index == 0 {
// return vc
// }
// println("actaulIndexPhotoSearchController: - \(actaulIndex)")
return vcTwo
// return getController(_dict[viewController]!.nextIndex())
}
var actaulIndex:Int!
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
print("finished: - \(finished)")
print("completed: - \(completed)")
if finished == true && completed == true {
print("currentPageIndex: - \(currentPageIndex)")
if finished == true && completed == true && currentPageIndex == 0 && xFromCenter < 0 {
print("hi")
// searchController.searchBar.placeholder = "Search for tips"
// let txtField = self.navigationItem.titleView as! UITextField
// txtField.placeholder = "Search for tips"
searchTextField.placeholder = "Search for tips"
updateCurrentPageIndex(1)
} else if finished == true && completed == true && currentPageIndex == 1 && xFromCenter > 0 {
print("hi 2")
// searchController.searchBar.placeholder = "Search for blogs"
// let txtField = self.navigationItem.titleView as! UITextField
// txtField.placeholder = "Search for blogs"
searchTextField.placeholder = "Search for blogs"
updateCurrentPageIndex(0)
}
}
}
}
I figured it out. Inside the widen textfield function. I needed to change the following line:
searchBarView.frame = CGRect(x: 16, y: 5, width: self.view.frame.width, height: 34)
to
searchBarView.frame = CGRect(x: 8, y: 5, width: self.view.frame.width - 16, height: 34)

UIScrollView & UIPageControl - start on specific page in SWIFT

I have implemented an UIScrollView & UIpageControl to display 3 UIViewControllers.
It works very well but I want to start the display on the 2nd UIViewController.
I didn't find yet where is my fault:
var pageControl:UIPageControl!
var scrollView:UIScrollView!
var viewtest1:UIViewController!
var viewtest2:UIViewController!
var viewtest3:UIViewController!
override func viewDidLoad() {
super.viewDidLoad()
// Initialization of UIScrollView
self.scrollView = UIScrollView()
self.scrollView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.scrollView.pagingEnabled = true
self.scrollView.scrollEnabled = true
self.scrollView.showsHorizontalScrollIndicator = false
self.scrollView.showsVerticalScrollIndicator = false
self.scrollView.delegate = self
// Initialisation of UIPageControl
self.pageControl = UIPageControl()
pageControl.currentPageIndicatorTintColor = UIColor(red:0.325, green:0.667, blue:0.922, alpha: 1)
pageControl.pageIndicatorTintColor = UIColor.whiteColor()
pageControl.backgroundColor = UIColor.clearColor()
// Add different view to the screen in the order from left to right
self.addChildViewController(self.viewtest1)
self.addChildViewController(self.viewtest2)
self.addChildViewController(self.viewtest3)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
for var i=0; i < self.childViewControllers.count; i++ {
self.loadScrollViewWithPage(i)
}
self.pageControl.currentPage = 0
self.page = 0
self.pageControl.numberOfPages = self.childViewControllers.count
var viewController:UIViewController = self.childViewControllers[self.pageControl.currentPage] as! UIViewController
if viewController.view.superview != nil {
viewController.viewWillAppear(true)
}
self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * CGFloat(self.childViewControllers.count), scrollView.frame.size.height)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// Load Controllers
var viewController:UIViewController = self.childViewControllers[self.pageControl.currentPage] as! UIViewController
if viewController.view.superview != nil {
viewController.viewDidAppear(true)
}
}
override func viewWillDisappear(animated: Bool) {
var viewController:UIViewController = self.childViewControllers[self.pageControl.currentPage] as! UIViewController
if viewController.view.superview != nil {
viewController.viewWillDisappear(true)
}
super.viewWillDisappear(true)
}
override func viewDidDisappear(animated: Bool) {
var viewController:UIViewController = self.childViewControllers[self.pageControl.currentPage] as! UIViewController
if viewController.view.superview != nil {
viewController.viewDidDisappear(true)
}
super.viewDidDisappear(true)
}
func loadScrollViewWithPage(page:Int){
if page < 0 || page >= self.childViewControllers.count {
return
}
let controller:UIViewController = self.childViewControllers[page] as! UIViewController
if (controller == false) {
return
}
// add the controller's view to the scroll view
if (controller.view.superview == nil) {
var frame:CGRect = self.scrollView.frame
frame.origin.x = frame.size.width * CGFloat(page)
frame.origin.y = 0
controller.view.frame = frame
self.scrollView.addSubview(controller.view)
}
}
func changePage(sender:AnyObject) -> () {
var senderControl:UIPageControl = sender as! UIPageControl
var page:Int = Int(senderControl.currentPage)
// update the scroll view to the appropriate page
var frame:CGRect = self.scrollView.frame
frame.origin.x = frame.size.width * CGFloat(page)
frame.origin.y = 0
var oldViewController:UIViewController = self.childViewControllers[self.page] as! UIViewController
var newViewController:UIViewController = self.childViewControllers[self.pageControl.currentPage] as! UIViewController
oldViewController.viewWillDisappear(true)
newViewController.viewWillAppear(true)
self.scrollView.scrollRectToVisible(frame, animated: true)
self.pageControlUsed = true
}
override func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
var oldViewController:UIViewController = self.childViewControllers[self.page] as! UIViewController
var newViewController:UIViewController = self.childViewControllers[self.pageControl.currentPage] as! UIViewController
oldViewController.viewWillDisappear(true)
newViewController.viewWillAppear(true)
self.page = self.pageControl.currentPage
}
override func scrollViewDidScroll(scrollView: UIScrollView) {
if (self.pageControlUsed == true /*|| _rotating*/) {
// do nothing - the scroll was initiated from the page control, not the user dragging
return
}
var pageWidth:CGFloat = self.scrollView.frame.size.width
var page:Int = Int(floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1)
if (self.pageControl.currentPage != page) {
var oldViewController:UIViewController = self.childViewControllers[self.pageControl.currentPage] as! UIViewController
var newViewController:UIViewController = self.childViewControllers[page] as! UIViewController
oldViewController.viewWillDisappear(true)
newViewController.viewWillDisappear(true)
self.pageControl.currentPage = page
oldViewController.viewDidDisappear(true)
newViewController.viewDidDisappear(true)
self.page = page;
}
}
override func scrollViewWillBeginDragging(scrollView: UIScrollView) {
self.pageControlUsed = false
}
override func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
self.pageControlUsed = false
}
Thank you for your help
In storyboard set the "viewtest2" to "Is Initial View Controller". That will show that viewController first.
Or you can try in appDelegate :
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject :AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var initialViewController = storyboard.instantiateViewControllerWithIdentifier("viewTest2") as UIViewController
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}

Resources