当我将页面控制元素放置在将要显示的单个视图的顶部时,逻辑结果是控制元素随着页面视图从屏幕上滚动消失。
怎样才能将控制元素放置在视图的顶部,使得页面视图全屏(就像图片一样),以便用户可以看到固定控制元素下面的视图?
我附上一个示例截图 - 感谢AppCoda和Path:
我没有足够的声望来评论这个初始答案,但我真的很喜欢它。我改进了代码并将其转换为Swift,适用于下面的UIPageViewController子类:
class UIPageViewControllerWithOverlayIndicator: UIPageViewController {
override func viewDidLayoutSubviews() {
for subView in self.view.subviews as! [UIView] {
if subView is UIScrollView {
subView.frame = self.view.bounds
} else if subView is UIPageControl {
self.view.bringSubviewToFront(subView)
}
}
super.viewDidLayoutSubviews()
}
}
干净并且运行良好。无需维护任何东西,只需在Storyboard中将您的页面视图控制器实例化为此类的一个实例,或者让您的自定义页面视图控制器类继承自此类。
在进一步调查和搜索后,我在stackoverflow上找到了一个解决方案。
关键是向自定义UIPageControl
元素发送以下消息:
[self.view bringSubviewToFront:self.pageControl];
在RootViewController
上方添加一个UIPageControl
元素 - 带有箭头的视图控制器。
在ViewController.m
中创建相关的IBOutlet
元素。
在viewDidLoad
方法中,您应该在添加所有子视图后调用以下代码作为最后一个方法。
[self.view bringSubviewToFront:self.pageControl];
为了基于当前内容视图的 pageIndex
分配当前页面,您可以在 UIPageViewControllerDataSource
方法中添加以下内容:
- (UIPageViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
// ...
index--;
[self.pageControl setCurrentPage:index];
return [self viewControllerAtIndex:index];
}
- (UIPageViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
// ...
index++;
[self.pageControl setCurrentPage:index];
// ...
return [self viewControllerAtIndex:index];
}
self.pageControl
是视图上的 Page Control 元素的 IBOutlet... - sn3ekpageControl
并不是一个好的建议。作为数据源,你唯一需要做的就是返回所请求的数据(避免其他逻辑)- 你无法控制这些方法何时被调用 - 这取决于实现。例如,在滚动之后,您可能会观察到PageViewController提前“预取”下一个相邻页面。这会完全干扰您可能潜入的任何检查逻辑(也可能解释了为什么@Gokul与@sn3ek得到不同的结果)。 (更好的方法:使用代理) - wardwsn3ek你的回答帮了我很多。虽然我没有使用viewControllerCreation
方法来设置当前页面。
我将我的ViewController
也设为UIPageViewController
的委托。然后我在那个方法中设置了PageControl
的CurrentPage
。使用在原始文章中提到的ContentViewController
中维护的pageIndex
。
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
APPChildViewController *currentViewController = pageViewController.viewControllers[0];
[self.pageControl setCurrentPage:currentViewController.pageIndex];
}
不要忘记将这个添加到viewDidLoad
。self.pageViewController.delegate = self;
为了跟进PropellerHead的评论,ViewController
的接口将采用以下形式:
@interface ViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>
@interface ViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>
- PropellerHead通过子类化UIPageViewController并如下覆盖viewDidLayoutSubviews方法,可以简单地实现相同的效果:
-(void)viewDidLayoutSubviews {
UIView* v = self.view;
NSArray* subviews = v.subviews;
if( [subviews count] == 2 ) {
UIScrollView* sv = nil;
UIPageControl* pc = nil;
for( UIView* t in subviews ) {
if( [t isKindOfClass:[UIScrollView class]] ) {
sv = (UIScrollView*)t;
} else if( [t isKindOfClass:[UIPageControl class]] ) {
pc = (UIPageControl*)t;
}
}
if( sv != nil && pc != nil ) {
// expand scroll view to fit entire view
sv.frame = v.bounds;
// put page control in front
[v bringSubviewToFront:pc];
}
}
[super viewDidLayoutSubviews];
}
UIPageControl
并将其添加到视图中。正如其他人提到的那样,必须调用 view.bringSubviewToFront(pageControl)
。UIPageControl
(与 UIPageViewController
一起使用)的所有代码。func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [UIViewController]) {
pendingIndex = pages.indexOf(pendingViewControllers.first!)
}
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
currentIndex = pendingIndex
if let index = currentIndex {
pageControl.currentPage = index
}
}
}
let pages = Variable<[UIViewController]>([])
let currentPageIndex = Variable<Int>(0)
let pendingPageIndex = Variable<(Int, Bool)>(0, false)
let db = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
pendingPageIndex
.asDriver()
.filter { $0.1 }
.map { $0.0 }
.drive(currentPageIndex)
.addDisposableTo(db)
currentPageIndex.asDriver()
.drive(pageControl.rx.currentPage)
.addDisposableTo(db)
}
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
if let index = pages.value.index(of: pendingViewControllers.first!) {
pendingPageIndex.value = (index, false)
}
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
pendingPageIndex.value = (pendingPageIndex.value.0, completed)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
var sv:UIScrollView?
var pc:UIPageControl?
for v in self.view.subviews{
if v.isKindOfClass(UIScrollView) {
sv = v as? UIScrollView
}else if v.isKindOfClass(UIPageControl) {
pc = v as? UIPageControl
}
}
if let newSv = sv {
newSv.frame = self.view.bounds
}
if let newPc = pc {
self.view.bringSubviewToFront(newPc)
}
}
let pageControlAppearance = UIPageControl.appearance()
pageControlAppearance.backgroundColor = UIColor.clearColor()
顺便说一下 - 我没有注意到任何无限循环,如上所述。