此控件允许您添加多个视图控制器,并使它们在水平方向上滚动,每个控制器都有一个较小的头部视图,该头部视图按内容滚动比例滚动。其风格类似于 Groupon 应用。
使用此控件作为其主要 UI 的应用程序的示例是 Tom Thorpe 摄影,可在App Store上获得。
添加了额外的属性 hideStatusBarWhenScrolling
,以更好地适应 iOS7 中状态栏的工作方式。
在 iOS7+ 中,状态栏现在会覆盖内容部分,这导致在使用全屏此控件时出现了问题,因为页码点(UIPageControl)现在与状态栏位于同一空间。
此属性旨在用于当 UIScrollSlidingPages 为全屏且状态栏覆盖 UIPageControl 页码点时。如果您将此新属性设置为 YES,则在非滚动时页面点会消失,并显示状态栏。相反,当您滚动时情况则相反。
要使此属性正常工作,您需要将 "基于视图控制器的外观状态栏"(UIViewControllerBasedStatusBarAppearance)键添加到 info.plist 中,并将其设置为布尔值为 NO。
如果保持当前行为而不设置上述新属性,则在 iOS7 中,您可能需要将 self.edgesForExtendedLayout = UIRectEdgeNone; 添加到您的视图控制器中,以保护状态栏的空间,并确保视图不重叠。
默认值为 NO。尽管如此,我已经将示例项目改为了 YES,因为我认为在 iOS7 中看起来更好。
UIScrollSlidingPages 是 TTScrollSlidingPagesController
UIViewController 的项目名称。这种控件是一个包含头部区域、显示当前页的标准“页面点”以及滚动之间的 UI 效果的水平分页滚动器。
如上所述,该控件包含两个主要“区域” - 内容区域和头部区域。
内容区域占用整个控件宽度,是分页的,这意味着用户每次只能看到一页。
内容区域中的每一页都对应着标题区域中的一个标题。当前页的标题显示在标题区域中央。然而,标题区域的项目不会占用全部宽度,从而使用户能够看到下一页和上一页的标题。
不过,可以通过在控件加载前设置titleScrollerHidden
选项为YES
来隐藏标题区域。
用户可以通过在控件上左右拖动或触摸标题区域中的任意一页来水平滚动页面。两个区域将保持同步,这意味着当前页的标题始终位于标题区域中央。
Source
目录中包含这些文件。#import "TTUIScrollViewSlidingPages.h"
。要使用此控件,创建TTScrollSlidingPagesController
的一个实例。这仅仅是一个UIViewController的子类,一旦创建实例,您就可以使用视图属性将其添加到视图中(通常将实例的view
属性作为子视图添加到当前视图、导航控制器、标签栏等)。
有一点主要区别,一旦创建TTScrollSlidingPagesController
,应设置dataSource
属性,这类似于设置UITableViewController
的方式。数据源应该设置为符合TTSlidingPagesDataSource
协议的对象。以下部分将详细介绍如何实现TTSlidingPagesDataSource
。
例如,要从另一个视图控制器实例化TTScrollSlidingPagesController
并将其添加到当前视图中,请执行以下操作
TTScrollSlidingPagesController slider = [[TTScrollSlidingPagesController alloc] init];
slider.dataSource = self; /*the current view controller (self) conforms to the TTSlidingPagesDataSource protocol)*/
slider.view.frame = self.view.frame; //I'm setting up the view to be fullscreen in the current view
[scrollPagerView addSubview:slider.view];
[self addChildViewController:slider]; //this makes sure the instance isn't released from memory :-)
-numberOfPagesForSlidingPagesViewController:
此方法返回一个整数,指示控件有多少页。下面的两个方法将分别调用这么多次,每次为一个页面。-pageForSlidingPagesViewController:atIndex:
此方法返回请求的页(索引)的内容视图,形式为TTSlidingPage实例。以下将描述TTSlidingPage。titleForSlidingPagesViewController:(TTScrollSlidingPagesController*)source atIndex:(int)index;
此方法返回请求的页(索引)的标题(可能是图像或文本),形式为TTSlidingPageTitle实例。以下将描述TTSlidingPageTitle。此内容由TTSlidingPagesDataSource返回。它表示要在内容区域中的特定页面放入的页面内容视图。您可以将其与一个UIViewController一起实例化,使用-initWithContentViewController:(UIViewController *)contentViewController
(推荐),或如果只有一个UIView并且将自行管理控制器,请使用initWithContentView:(UIView *)contentView;
进行实例化。
此内容由TTSlidingPagesDataSource返回。它表示要在标题区域中放入的特定页面的标题。它可以是图像或文本。使用图像进行实例化,请使用initWithHeaderImage:(UIImage*)headerImage
,或使用纯文本进行实例化,请使用initWithHeaderText:(NSString*)headerText
例如,要将 TTSlidingPagesDataSource 实现到您的类中,在 .h 头文件中在您的类名后添加 "",例如
@interface TTViewController : UIViewController<TTSlidingPagesDataSource>{
}
然后实现三个数据源方法
-(int)numberOfPagesForSlidingPagesViewController:(TTScrollSlidingPagesController *)source{
return 5; //5 pages. The below two methods will each now get called 5 times, one for
}
-(TTSlidingPage *)pageForSlidingPagesViewController:(TTScrollSlidingPagesController*)source atIndex:(int)index{
UIViewController *viewController = [[UIViewController alloc] init];
return [[TTSlidingPage alloc] initWithContentViewController:viewController]; //in reality, you would return an actual view controller for the page (given by index) that you want, rather than just a blank UIViewController. In the demo app in the repository, I return instances of my own UIViewController subclass; TabOneViewController and TabTwoViewController. You can also just use a UIView but this wont preserve the full view hierarchy unless you handle it yourself.
}
-(TTSlidingPageTitle *)titleForSlidingPagesViewController:(TTScrollSlidingPagesController *)source atIndex:(int)index{
TTSlidingPageTitle *title;
if (index == 0){ //for the first page, have an image, for all other pages use text
//use a image as the header for the first page
title= [[TTSlidingPageTitle alloc] initWithHeaderImage:[UIImage imageNamed:@"randomImage.png"]];
} else {
//all other pages just use a simple text header
title = [[TTSlidingPageTitle alloc] initWithHeaderText:@"A page"]; //in reality you would have the correct header text for your page number given by "index"
}
return title;
}
您应该在实例化控件后、设置 dataSource
之前以及控件显示之前设置这些选项)。
bool titleScrollerHidden
- 是否隐藏标题滚动条。如果只想看到页面,而不想在页面顶部看到标题,则将其设置为 YES。目前即使您设置为 YES,也仍需在数据源类中实现 -(TTSlidingPageTitle *)titleForSlidingPagesViewController:(TTScrollSlidingPagesController *)source atIndex:(int)index
方法,但您可以返回 nil 以返回所有内容。默认为 NO。int titleScrollerHeight
- 标题区域的高度(像素)。默认为 50 像素。int titleScrollerItemWidth
- 标题区域中每个“页面”的宽度(像素)。这个值越小,在标题区域中看到的下一页和前一页就越多。默认为 150 像素。UIColor *titleScrollerBackgroundColour
- 标题区域的背景颜色。作为一个提示,您可以使用 [UIColor colorWithPatternImage] 方法在此设置图像作为背景。默认值是,如果您的项目中包含它,则为特定于项目的 diagmonds.png 背景纹理(信用:来自 http://subtlepatterns.com/),如果没有,则为黑色。UIColor *titleScrollerTextColour
- 标题区域中文本的颜色。默认为白色。UIColor *titleScrollerInActiveTextColour
- 标题区域中非活动文本的颜色。如果未设置,则默认为白色。UIColor *titleScrollerTextDropShadowColour
- 标题文本的阴影颜色。如果未设置,则默认为黑色。UIFont *titleScrollerTextFont
- 标题区域中文本的字体。如果未设置,则默认为粗体系统字体。UIColor titleScrollerBottomEdgeColour
- 标题区域底部边缘的边框颜色。如果未设置,则默认为透明。int titleScrollerBottomEdgeHeight
- 标题区域底部边缘的边框高度。如果未设置,则默认为 3。BOOL disableTitleScrollerShadow
- 允许您禁用标题区域文本的阴影效果。默认为 NO。BOOL disableTitleShadow
- 禁用标题文本标签的(非常微妙的)阴影效果。BOOL disableUIPageControl
- 允许您禁用页面顶部的 UIPageControl
(这是显示有多少个页面以及当前是哪个页面的“页面点”)。默认为 NO。int initialPageNumber
- 允许您设置显示的页面起始编号(基于零,因此第一页为 0),这意味着在您从一个非 0 的页面上开始时,您可以在左右两侧同时开始页面。默认为 0。BOOL pagingEnabled
- 内容视图是否“跳转”到每个页面。默认为 YES。BOOL zoomOutAnimationDisabled
- 是否禁用在页面之间滚动时出现的“缩放出”效果。默认为 NO。BOOL hideStatusBarWhenScrolling
- 适用于iOS7及以上版本,并在UIScrollSlidingPages控件全屏时使用。iOS7的新行为可能导致状态栏与UIScrollSlidingPages控件的顶部重叠。如果您将此属性设置为YES,则屏幕顶部的页面点将在用户开始滚动之前隐藏,此时状态栏被替换为页面数字点,直到用户停止滚动。如果将其设置为YES,还需要在info.plist中将"UIViewControllerBasedStatusBarAppearance"键作为布尔值添加,并将其设置为NO,如果不这样做,应用程序会抛出异常以提醒您。请参阅示例演示项目,其中我已经将此设置为YES,适用于运行iOS7+的设备,它在iOS7+中看起来最好。如果在使用低于iOS7的任何东西时使用此功能,它可能没有意义,除非在您的视图层次结构中确保状态栏与TTScrollSlidingPagesController重叠。因此,除非您这样做,否则在iOS7+的设备上最好有条件地启用此属性。默认为NO。-(void)reloadPages
- 清空控件并重新加载所有页面。-(void)scrollToPage:(int)page animated:(BOOL)animated
跳转到特定页面。如果animated设置为NO,则更改将立即生效,否则页面将“滚动”到页面。-(int)getCurrentDisplayedPage
- 返回当前正在显示的页面的索引。页面从0开始。包含的源代码是一个XCode项目,您可以将其打开以查看演示。如果您对此有任何不明白的地方,可以参考此示例:-)
在TTViewController.m
的viewDidLoad
方法中创建了控件。其中一些选项属性已被注释出来,表示演示使用默认值。尝试取消注释它们并进行试验。最后,应用程序将dataSource属性设置为实例的self
,然后将视图作为子视图添加到当前视图。
TTViewController
还实现了TTSlidingPagesDataSource
。它返回7个页面。对于页面标题,在第0页返回一个图片,在其余页面返回文本。对于页面内容,它返回交替的TabOneViewController
和TabTwoViewController
实例 - 这可以是任何UIViewController。
顺便说一句,TabOneViewController
和TabTwoViewController
实际上是我另一个库中的实例,该库是UITableViewZoomController
,您可以从以下链接找到它:https://github.com/TomThorpe/UITableViewZoomController。这是一个类似于Google+应用的TableView Controller,它会将每个单元格以淡入和缩放的方式显示。
目前,虽然使用与UITableViewControllers相同的dataSource
委托,但控件仍然在控件出现时立即加载ALL
视图。这意味着如果您有大量页面,它仍然会将所有的页面都加载到内存中,而不是更智能地只加载当前(以及可能的下一页/上一页)页面。这有两个主要影响
该控件最适合只有少数页面(可能不到10个),否则您可能会开始看到它变慢。
viewDidAppear
方法将立即为所有页面调用,即使它们尚未实际可见。
有一天,我可能会使其仅在需要时加载页面,但我不能保证。我为自己的应用程序创建了此控件,对我自己来说并不需要,因为我只使用少数几个页面。抱歉!