第一次加载APP的时候通常会采用引导页来展示特色或者告知用户如何使用。打开我们的Storyboard,然后导入一个Page View Controller,作如下设置,修改Transition Style:


然后给我们的Page View Controller设置一个storyboard的ID为PageViewController。

现在你应该很想知道我们如何能编辑我们的pageviewcontroller,它看起来并不能被编辑,首先你需要知道它的原理。

page view controller被定义成一个view controller的管理者,组织并管理多张页面,而每张页面是要被它自己的view controller管理的。所以我们首先要添加一个view controller,你可能会好奇为什么我想做三张引导页却只新建一个view controller。是因为引导页的结构十分相似,我们可以服用页面上的组件。然后我们在viewcontroller中拖入两个label(文字居中,并且第二个label足够大)和一个imageview,如图:



然后给这个viewcontroller的storyboardID取为pagecontentviewcontroller,然后新建一个同名的类,在类中加入以下代码:

 @IBOutlet weak var headingLabel:UILabel!
    @IBOutlet weak var subheadingLabel:UILabel!
    @IBOutlet weak var contentimageView:UIImageView!
var index : Int = 0
    var heading : String = ""
    var imageFile : String = ""
    var subheading : String = ""

这里的index用来表示引导页的顺序,比如第一张的index就是0

viewDidLoad方法中加入:

 headingLabel.text = heading
        subheadingLabel.text = subheading
        contentimageView.image = UIImage(named: imageFile)

之后在storyboard把代码中的label和image和界面中的连起来。




好了,现在内容的页面部分已经完成了,接着我们来实现页面的切换。把这些引导页加入到Page view Controller中,这样用户就可以切换它们了。我们可以使用on-demand 点播的方法来实现,在这个方法中,我们需要创建一个数据源,当用户切换的时候,数据源告诉我们的pageviewcontroller需要播放哪一张viewcontroller。数据源继承自PageViewControllerDataSource,需要实现下面这两个方法:


现在我们新建一个文件PageViewController,它的类型是UIPageViewController,继承PageViewControllerDataSource。

把我们想要在页面上显示的数据录入:

  var pageheadings = ["摇出美食","地图定位","美食共享"]
    var pageImages = ["fiveleaves","mapintro","homei"]
    var pageSubheadings = ["摇出心中所想,轻松搞定美食","寻找心仪的饭馆,SoFun为你导航","共享你的发现,建立吃货友谊"]


实现两个代理方法:

func pageViewController(pageViewController: UIPageViewController,viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        var index = (viewController as PageContentViewController).index
        
        index++
        
        return self.viewControllerAtIndex(index)
    }
    
    func pageViewController(pageViewController: UIPageViewController,viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        var index = (viewController as PageContentViewController).index
        
        index--
        
        return self.viewControllerAtIndex(index)
    }

当我们前进或者后退的时候首先获得当前页面的index值然后自增或者自减,将相邻的页面返回。

现在增加两个辅助的方法:

 func viewControllerAtIndex(index: Int) -> PageContentViewController? {
        
        if index == NSNotFound || index < 0 || index >= self.pageheadings.count {
            return nil
        }
        
        // Create a new view controller and pass suitable data.
        if let pageContentViewController = storyboard?.instantiateViewControllerWithIdentifier("PageContentViewController") as? PageContentViewController {
            
            pageContentViewController.imageFile = pageImages[index]
            pageContentViewController.heading = pageheadings[index]
            pageContentViewController.subheading = pageSubheadings[index]
            pageContentViewController.index = index
            
            return pageContentViewController
        }
        
        return nil
    }

在viewDidLoad方法中加入以下代码:
// Set the data source to itself
        dataSource = self
        
        // Create the first walkthrough screen
        if let startingViewController = self.viewControllerAtIndex(0) {
            setViewControllers([startingViewController],direction: .Forward,animated: true,completion: nil)
        }

现在我们的引导页基本完工了,我们要把引导页放到程序的第一个页面之前,在你的第一个页面的代码的viewDidLoad方法中加入如下代码:
if let pageViewController = storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as? PageViewController {
        self.presentViewController(pageViewController,completion: nil)
        }

可以运行一下看看了!



通过滑动可以切换


我们现在来增加一些控制,再在pageviewcontroller中加入下面两个方法:

    func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
        return pageheadings.count
    }
    
    func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
        if let pageContentViewController = storyboard?.instantiateViewControllerWithIdentifier("PageContentViewController") as? PageContentViewController {

            return pageContentViewController.index
        }
        
        return 0
    }

运行一下看看屏幕下方:


出现了一个指示器,指示总的页面数和我们当前停留的页面。

可以看到调用系统自带的页面指示器很容易实现,但是它的风格是固定的,我们想要自己定义一款指示器。

把上面那段代码注释掉,然后我们去storyboard中拖拽一个page control到heading的顶部


设置它的背景色和选中的颜色如下:


现在页面上的控制器如图:



在pagecontentviewcontroller中加入对应的对象,然后关联:

 @IBOutlet weak var pageControl:UIPageControl!
在viewDidLoad方法中加入以下代码标示当前的页面数:
        pageControl.currentPage = index

页面指示器有了,之前我们靠着滑动页面来切换并且无法切出,现在我们增加一个按钮,来实现页面切换和切出。

按钮的样式自己设计


继续与类关联,我这里开始体验的按钮用了第三方的库,所以不是UIButton,效果是一样的。

    @IBOutlet weak var getStartedButton:MKButton!
    @IBOutlet weak var forwardButton:UIButton!

在viewDidLoad中增加以下代码:
      getStartedButton.hidden = (index == 2) ? false : true
        forwardButton.hidden = (index == 2) ? true: false

前两页显示forward按钮,最后一页隐藏forward按钮,显示“开始体验”按钮。

然后增加两个方法来关联两个按钮:

@IBAction func close(sender: AnyObject) {
        
        dismissViewControllerAnimated(true,completion: nil)
    }
    
    @IBAction func nextScreen(sender: AnyObject) {
        let pageViewController = self.parentViewController as PageViewController
        pageViewController.forward(index)
    }


}

@IBAction func nextScreen(sender: AnyObject) { let pageViewController = self.parentViewController as PageViewController pageViewController.forward(index) }
 nextScreen方法中调用了pageViewController中的forward这个辅助方法,这个方法还没有实现,现在回到pageViewController中,加入以下代码: 
 
 
func forward(index: Int) {
        
        if let nextViewController = self.viewControllerAtIndex(index + 1) {
            setViewControllers([nextViewController],completion: nil)
        }
    }

现在运行一下看看效果吧!





现在就剩最后一个问题了:保证引导页只在第一次打开时出现。IOS的SDK中有一个类NSUserDefault,来映射应用和用户的设置,比如你可以用它来保存一个状态位用来判断是否需要启动引导页。再比如用户标示了一个价格,而你也可以用这个类来记录用户标示这个价格使用的货币类型。NSUserDefault类使用了与操作系统相关联的借口,也就是说你在其中配置的数据在APP关闭时依旧起作用。现在我们需要重新写close方法,关闭了一次后用户的使用状况就改变了:

@IBAction func close(sender: AnyObject) {
        let defaults = NSUserDefaults.standardUserDefaults()
        defaults.setBool(true,forKey: "hasViewedWalkthrough")
        
        dismissViewControllerAnimated(true,completion: nil)
    }

我们给一个key值为“hasViewedWalkthrough”的系统量设置了布尔值,当引导页运行过一次后它变为true,现在在我们系统的第一张页面的viewDidLoad方法中修改如下:
       let hasViewedWalkthrough = defaults.boolForKey("hasViewedWalkthrough")
       
       if hasViewedWalkthrough == false {
           if let pageViewController = storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as? PageViewController {
               
                self.presentViewController(pageViewController,completion: nil)
            }
        }
好了大功告成,快来试试吧!

swift UI专项训练43 Swift实现APP引导页的更多相关文章

  1. ios – 在新的Storyboard中将值传递给UIViewController – Swift

    我试图将值传递给新的视图控制器–位于新的故事板文件中.但是当我这样做时,我从NewViewController得到的结果总是为零.下面是我在新故事板中显示视图控制器的方法:我尝试在这里发送信息:然后呈现视图控制器.这是我的NewViewController,我尝试接收值.但最终仍然是零.我错误地发送了这些值吗?解决方法您正在使用此行创建NewViewController的新实例而是将变量和委托分配给已从StoryBoard实例化的vc

  2. ios – 将UIViewController视图属性设置为不带有storyboard / nib的自定义UIView类

    或者上面的代码片段是推荐的吗?

  3. ios – Xcode Storyboard中“推断”和“自由形式”有什么区别?

    我有一个自定义视图,需要在所有iPhone设备上显示.在创建自定义视图XIB时,我将其称为“推断”,但它没有为iPhone6和iPhone6Plus设备调整大小.我无法弄清楚这个问题.我对“推断”和“自由形式”之间的实际差异感到困惑.有人可以解释一下这些差异吗?

  4. 在ios中将故事板从一个应用程序复制到另一个应用程序的最佳方法是什么?

    或者我在这里遗漏了什么?编辑-1我认为StoryBoard的布局大小仅限于iphone5.解决方法你这样做的方式是正确的.您只是遇到了布局约束不存在或错误的事实.关于故事板没有什么神奇之处……它只是一个像你复制到你的新项目中的任何其他文件.您应该在每个视图控制器中选择您的顶层视图,然后告诉Xcode删除所有约束并将它们重置为建议的约束,然后从那里开始.

  5. ios – Interface Builder无法确定“Main.storyboard”的类型.这可能是由于缺少SDK

    解决方法这没有你想象的那么复杂.该错误是因为您在Main.storyboard的源代码上输错了一些内容,例如我不小心在Main.storyboard的第一个打开标记之前放了一个“”.1)你必须做的是删除Main.storyboard2)转到垃圾箱,将Main.storyboard移动到桌面,用任何文本编辑器打开并修复代码;然后“全选”和“复制”.3)在Xcode上,创建一个全新的Main.storyboard,然后按右键单击文件并选择OpenAs–>源代码,然后粘贴您在剪贴板上的固定代码.4)右键单击文件

  6. 使用Xcode 6中的Storyboard的AppDelegate for Cocoa应用程序

    我有一个现有的OSX应用程序,在转换为Storyboards作为主界面后,我的app代理不再被使用.之前,MainMenu.xib有一个“AppDelegate”对象,我可以将它的类设置为我的appdelegate.但是,Storyboard不包含此类对象.如何恢复AppDelegate并保留故事板?

  7. ios – storyboard在导入xcassets后为每个图像都有问号

    图片.这是在我将所有媒体资产导入新的.xcassets结构后发生的.该应用程序运行正常,图像显示应用程序运行时,但我该怎么做才能在故事板中恢复它们?解决方法从故事板中的图像名称中删除.png扩展名.Xcode5现在使用图像名称,而不是文件名.

  8. xcode – 使用Storyboard参考AppDelegate中的主要NSWindow?

    我正在尝试在AppDelegate中为我的应用程序的主窗口设置一个插座,然后在InterfaceBuilder中连接它.我轻松地在AppDelegate中创建插座:但是,在界面构建器中,我无法将引用插座连接到AppDelegate.相反,我只能将它连接到WindowController,我希望这张图片显示:第一个对象是WindowController,第二个对象是FirstResponder,但缺

  9. 将数据从一个视图控制器传递到另一个; iOS &lt;= 4 vs iOS 5

    只是使用id并谨慎对待风?

  10. 在iOS中解除视图控制器时,ContentInset设置错误

    在我的iOS应用程序(使用Xamarin开发)中,我使用自定义容器视图控制器在与UISegmentedControl的段相关联的不同子视图控制器(都包含UITableView)之间切换.在开始时,我遇到了切换到新视图控制器时分配的错误contentInset的问题,因为视图位于导航栏下方.我用其他stackoverflowquestion中提供的解决方案解决了这个问题,它就像魅力一样.现在的问题是

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部