ios 如何将 UIPageControl 元素放在 UIPageViewController 中的滑动页面之上?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21045630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to put the UIPageControl element on top of the sliding pages within a UIPageViewController?
提问by sn3ek
Regarding to this tutorial by AppCoda about how to implement a app with UIPageViewControllerI'd like to use a custom page control element on top of the pages instead of at the bottom.
关于AppCoda 关于如何使用 UIPageViewController 实现应用程序的本教程,我想在页面顶部而不是底部使用自定义页面控件元素。
When I just put a page control element on top of the single views which will be displayed, the logical result is that the control elements scrolls with the page view away from the screen.
当我只是将页面控制元素放在将显示的单个视图之上时,逻辑结果是控制元素随着页面视图远离屏幕滚动。
How is it possible to put the control element on top of the views so the page views are full screen (like with an image) so the user can see the views underneath the fixed control element?
如何将控制元素放在视图顶部,使页面视图全屏显示(就像图像一样),以便用户可以看到固定控制元素下方的视图?
I attached an example screenshot - credits to AppCoda and Path:
我附上了一个示例截图 - 归功于AppCoda 和 Path:
采纳答案by sn3ek
After further investigation and searching I found a solution, also on stackoverflow.
经过进一步调查和搜索,我找到了一个解决方案,也在 stackoverflow 上。
The key is the following message to send to a custom UIPageControl
element:
关键是要发送到自定义UIPageControl
元素的以下消息:
[self.view bringSubviewToFront:self.pageControl];
The AppCoda tutorial is the foundation for this solution:
Add a UIPageControl
element on top of the RootViewController
- the view controller with the arrow.
UIPageControl
在RootViewController
- 带有箭头的视图控制器之上添加一个元素。
Create a related IBOutlet
element in your ViewController.m
.
创建一个相关的IBOutlet
在你的元素ViewController.m
。
In the viewDidLoad
method you should then add the following code as the last method you call after adding all subviews.
在该viewDidLoad
方法中,您应该添加以下代码作为添加所有子视图后调用的最后一个方法。
[self.view bringSubviewToFront:self.pageControl];
To assign the current page based on the pageIndex of the current content view you can add the following to the UIPageViewControllerDataSource
methods:
要根据当前内容视图的 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];
}
回答by Eric F.
I didn't have the rep to comment on the answer that originated this, but I really like it. I improved the code and converted it to swift for the below subclass of UIPageViewController:
我没有代表对起源于此的答案发表评论,但我真的很喜欢它。我改进了代码并将其转换为 UIPageViewController 的以下子类的 swift:
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()
}
}
Clean and it works well. No need to maintain anything, just make your page view controller an instance of this class in storyboard, or make your custom page view controller class inherit from this class instead.
干净,效果很好。无需维护任何东西,只需让您的页面视图控制器成为故事板中此类的实例,或者让您的自定义页面视图控制器类从此类继承。
回答by Coderdad
sn3ek Your answer got me most of the way there. I didn't set the current page using the viewControllerCreation
methods though.
sn3ek 你的回答让我在那里度过了大部分时间。我没有使用这些viewControllerCreation
方法设置当前页面。
I made my ViewController also
the delegate of the UIPageViewController
. Then I set the PageControl
's CurrentPage
in that method. Using the pageIndex
maintained I'm the ContentViewController
mention in the original article.
我让我ViewController also
的代表UIPageViewController
。然后,我设置PageControl
的CurrentPage
,该方法中。使用pageIndex
维护的我是ContentViewController
原始文章中提到的。
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
APPChildViewController *currentViewController = pageViewController.viewControllers[0];
[self.pageControl setCurrentPage:currentViewController.pageIndex];
}
don't forget to add this to viewDidLoad
不要忘记将此添加到 viewDidLoad
self.pageViewController.delegate = self;
To follow up on PropellerHead's comment the interface for the ViewController
will have the form
要跟进 PropellerHead 的评论,界面ViewController
将具有以下形式
@interface ViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>
回答by zeroimpl
The same effect can be achieved simply by subclassing UIPageViewController and overriding viewDidLayoutSubviews as follows:
同样的效果可以简单地通过继承 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];
}
Then there is no need to maintain a seperate UIPageControl and such.
那么就没有必要维护一个单独的 UIPageControl 之类的了。
回答by samwize
You have to implement a custom UIPageControl
and add it to the view. As others have mentioned, view.bringSubviewToFront(pageControl)
must be called.
您必须实现自定义UIPageControl
并将其添加到视图中。正如其他人所提到的,view.bringSubviewToFront(pageControl)
必须调用。
I have an exampleof a view controller with all the code on setting up a custom UIPageControl
(in storyboard) with UIPageViewController
我有一个视图控制器示例,其中包含设置自定义UIPageControl
(在故事板中)的所有代码UIPageViewController
There are 2 methods which you need to implement to set the current page indicator.
您需要实现两种方法来设置当前页面指示器。
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
}
}
}
回答by Hymans205
Here is a RxSwift/RxCocoa answer I put together after looking at the other replies.
这是我在查看其他回复后整理的 RxSwift/RxCocoa 答案。
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 { 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()
.1 }
.map { ##代码##.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)
}
回答by Lee Probert
Here's the Swifty 2 answer very much based on @zerotool's answer above. Just subclass UIPageViewController and then add this override to find the scrollview and resize it. Then grab the page control and move it to the top of everything else. You also need to set the page controls background color to clear. Those last two lines could go in your app delegate.
这是非常基于@zerotool 上面的答案的 Swifty 2 答案。只需将 UIPageViewController 子类化,然后添加此覆盖以查找滚动视图并调整其大小。然后抓住页面控件并将其移动到其他所有内容的顶部。您还需要将页面控件背景颜色设置为清除。最后两行可以放在您的应用程序委托中。
##代码##btw - I'm not noticing any infinite loops, as mentioned above.
顺便说一句-如上所述,我没有注意到任何无限循环。