如何使底部的UIPageViewController的点半透明?
我在制作教程的过程中,我正在试图模拟Path的教程的样式,如下所示:
wp-content/uploads/2013/06/UIPageViewController-Tutorial-Screen.jpg
我的问题是,如果设置委托方法如此:
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController { // The number of items reflected in the page indicator. return 5; }
然后,我得到这个黑点下的这个愚蠢的黑吧:
http://i.stack.imgur.com/pUEdh.png
有没有办法使这个酒吧半透明的方式类似于设置UINavigationBar半透明?
使它工作很容易。 您只需要使pageviewcontroller更高,并将一个PageControl放入XIB文件。 技巧是将PageControl放置在前台(以及所有其他常用控件)中,并使用PageViewController更新PageControl的内容。 这里是代码:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil]; self.pageController.dataSource = self; // We need to cover all the control by making the frame taller (+ 37) [[self.pageController view] setFrame:CGRectMake(0, 0, [[self view] bounds].size.width, [[self view] bounds].size.height + 37)]; TutorialPageViewController *initialViewController = [self viewControllerAtIndex:0]; NSArray *viewControllers = [NSArray arrayWithObject:initialViewController]; [self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; [self addChildViewController:self.pageController]; [[self view] addSubview:[self.pageController view]]; [self.pageController didMoveToParentViewController:self]; // Bring the common controls to the foreground (they were hidden since the frame is taller) [self.view bringSubviewToFront:self.pcDots]; [self.view bringSubviewToFront:self.btnSkip]; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSUInteger index = [(TutorialPageViewController *)viewController index]; [self.pcDots setCurrentPage:index]; if (index == 0) { return nil; } index--; return [self viewControllerAtIndex:index]; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSUInteger index = [(TutorialPageViewController *)viewController index]; [self.pcDots setCurrentPage:index]; index++; if (index == 3) { return nil; } return [self viewControllerAtIndex:index]; } - (TutorialPageViewController *)viewControllerAtIndex:(NSUInteger)index { TutorialPageViewController *childViewController = [[TutorialPageViewController alloc] initWithNibName:@"TutorialPageViewController" bundle:nil]; childViewController.index = index; return childViewController; } - (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController { // The number of items reflected in the page indicator. NSInteger tutorialSteps = 3; [self.pcDots setNumberOfPages:tutorialSteps]; return tutorialSteps; } - (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController { // The selected item reflected in the page indicator. return 0; }
简单地通过inheritanceUIPageViewController并覆盖viewDidLayoutSubviews,可以达到同样的效果,如下所示:
-(void)viewDidLayoutSubviews { UIView* v = self.view; NSArray* subviews = v.subviews; // Confirm that the view has the exact expected structure. // If you add any custom subviews, you will want to remove this check. 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等等。
下面是Zerotool解决scheme到Swift 2.1的转换,虽然可能有一个更优雅的写法:
override func viewDidLayoutSubviews() { var scrollView: UIScrollView? var pageControl: UIPageControl? // If you add any custom subviews, you will want to remove this check. if (self.view.subviews.count == 2) { for view in self.view.subviews { if (view.isKindOfClass(UIScrollView)) { scrollView = view as? UIScrollView } else if (view.isKindOfClass(UIPageControl)) { pageControl = view as? UIPageControl } } } if let scrollView = scrollView { if let pageControl = pageControl { scrollView.frame = self.view.bounds self.view.bringSubviewToFront(pageControl) } } super.viewDidLayoutSubviews() }
Swift 3片段
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if let scrollView = view.subviews.filter({ $0 is UIScrollView }).first, let pageControl = view.subviews.filter({ $0 is UIPageControl }).first { scrollView.frame = view.bounds view.bringSubview(toFront:pageControl) } }
我不认为你可以改变UIPageViewController的行为,所以Path应用程序可能使用它自己的视图控制器。 你可以这样做:创build你自己的容器视图控制器,使用UIPageControl来指示当前页面。
你可以简单地调整UIPageViewController的UIPageControl的alpha值。
首先,你应该像这样从UIPageViewController中获取它:
- (UIPageControl *)getPageControlForPageViewController:(UIPageViewController *)pageViewController { for (UIView *subview in self.pageViewController.view.subviews) { if ([subview isKindOfClass:[UIPageControl class]]) { return (UIPageControl *) subview; } } return nil; }
接下来,利用该function。 我在我的ViewController上做了一个名为childPageControl的属性。 给它的UIPageViewController的UIPageControl:
self.childPageControl = [self getPageControlForPageViewController:self.pageViewController];
接下来,您可以调整Alpha以提供半透明的效果:
self.childPageControl.alpha = .5;
你可以做些什么来影响UIPageViewController的UIPageControl,但是你至less可以做到这一点。
我今天发现的小黑客
请参阅下面的代码。
self.pageController.dataSource = self; CGRect rect = [self.view bounds]; rect.size.height+=37; [[self.pageController view] setFrame:rect]; NSArray *subviews = self.pageController.view.subviews; UIPageControl *thisControl = nil; for (int i=0; i<[subviews count]; i++) { if ([[subviews objectAtIndex:i] isKindOfClass:[UIPageControl class]]) { thisControl = (UIPageControl *)[subviews objectAtIndex:i]; } } UIView *tempview = [[UIView alloc] initWithFrame:CGRectMake(0, -30, 320, 40)]; [tempview addSubview:thisControl]; thisControl.pageIndicatorTintColor = [UIColor lightGrayColor]; thisControl.currentPageIndicatorTintColor = [UIColor greenColor]; [self.view addSubview:tempview];
这个代码是在你的UIPageViewController中的Swift Add下面
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() for view in self.view.subviews { if view.isKindOfClass(UIScrollView) { view.frame = UIScreen.mainScreen().bounds } else if view.isKindOfClass(UIPageControl) { view.backgroundColor = UIColor.clearColor() } } }
我解决使用这个代码:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.namesImage = @[@"page1.png", @"page2.png", @"page3.png", @"page4.png"]; self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"]; self.pageViewController.dataSource = self; TutorialContentViewController *startingViewController = [self viewControllerAtIndex:0]; NSArray *viewControllers = @[startingViewController]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; [self addChildViewController:self.pageViewController]; [self.view addSubview:self.pageViewController.view]; [self.pageViewController didMoveToParentViewController:self]; [[UIPageControl appearance] setPageIndicatorTintColor:[UIColor grayColor]]; [[UIPageControl appearance] setCurrentPageIndicatorTintColor:[UIColor whiteColor]]; [[UIPageControl appearance] setBackgroundColor: [[UIColor blackColor] colorWithAlphaComponent:0.1f]]; [[UIPageControl appearance] setOpaque:YES]; }
我发现了一个更适合我的工作环境。
我重复使用由zerotool给出的代码来获取UIPageControl(var称为pageControl)和UIPageViewController使用的UIScrollView(var称为pageView)。
一旦在viewDidLoad中完成,我只是防止pageView的剪辑子视图,并让内容传播更多的UIPageControl下。
pageControl在pageView下面,所以我们必须手动让它在前面。
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. if( [[[self view] subviews] count] == 2 ) { UIScrollView* pageView = nil; UIPageControl* pageControl = nil; UIView* selfView = self.view; NSArray* subviews = selfView.subviews; for( NSInteger i = 0 ; i < subviews.count && ( pageView == nil || pageControl == nil ) ; i++ ) { UIView* t = subviews[i]; if( [t isKindOfClass:[UIScrollView class]] ) { pageView = (UIScrollView*)t; } else if( [t isKindOfClass:[UIPageControl class]] ) { pageControl = (UIPageControl*)t; } } if( pageView != nil && pageControl != nil ) { [pageView setClipsToBounds:NO]; [selfView bringSubviewToFront:pageControl]; } } }
一旦我得到我的pageView覆盖pageControl占用的空间,但在pageControl下,我只需要调整显示为页面的每个viewController的nib文件使用:
- 基本视图不应该剪辑
- 第一个也是唯一的子视图:
- 应该有约束来设置从底部到-37(或更多,如果你需要,但37是pageControl的大小)
- 应该剪辑内容
我想在我正在处理的应用程序中做类似的效果 – 我用一个UIPageViewController与一个单独的UIPageControl。
这使您可以将UIPageControl放置在视图的任何位置,包括UIPageViewController的顶部,并通过UIPageViewController委托方法保持活动页面的最新状态:
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed { if (completed) { self.pageControl.currentPage = [self.pageViewControllers indexOfObject:pageViewController.viewControllers.firstObject]; } }
无需遍历子视图层次结构,试图find内部UIPageViewController页面控件,也不必调整内部滚动视图的内容大小。
希望这可以帮助。