簡體   English   中英

如何以編程方式在 UIStackView 中添加響應式 UIPageViewController?

[英]How to add a responsive UIPageViewController inside an UIStackView programmatically?

我試圖將 UIPageViewController 放在沒有預定高度的 UIView 中。 我想要實現的是構建一個響應式應用內消息,它具有一個或多個組件(按鈕、文本、輪播等),其高度由其子項決定。

模態窗口適用於除 UIPageViewController 之外的所有組件。 UIView 會根據我放入的任何組件調整大小,但不會在我放置 UIPageViewController 時調整大小。 似乎缺少一些約束。

一般的層次結構是:

UIView (centered vertically on the screen with trailing and leading margins, no height)
|  UIStackView (inside this UIStackView I place any number of components I wish)
|  |  UILabel (example component)
|  |  UIButton (example component)
|  |  UIPageViewController (example component)
|  |  |  UIStackView (inside this UIStackView I place any other number of components)
|  |  |  |  UILabel (example component)
|  |  |  |  UIButton (example component)
…

以下日志摘錄屬於具有以下特征的應用內消息:

UIView (centered vertically on the screen with trailing and leading margins, no height)
|  UIStackView (leading and trailing anchors equal to parent, top and bottom anchors equal to children)
|  |  UIPageViewController (will display bellow the first slide content)
|  |  |  UIStackView
|  |  |  |  UIImageView
|  |  |  |  UILabel
|  |  |  |  UILabel

日志:

(lldb) po [[0x7feeb7a78e30 superview ] recursiveDescription]
<UIView: 0x7feeb76c44f0; frame = (0 0; 334 0); layer = <CALayer: 0x600002afd1c0>>
   | <_UIPageViewControllerContentView: 0x7feeb7a78e30; frame = (0 0; 334 0); clipsToBounds = YES; opaque = NO; autoresize = W+H; layer = <CALayer: 0x600002ae1500>>
   |    | <_UIQueuingScrollView: 0x7feeafbc6800; frame = (0 0; 334 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x600002773600>; layer = <CALayer: 0x600002ae0e80>; contentOffset: {334, 0}; contentSize: {1002, 0}; adjustedContentInset: {0, -334, 0, -334}>
   |    |    | <UIView: 0x7feeb7a79b30; frame = (0 0; 334 0); layer = <CALayer: 0x600002ae04a0>>
   |    |    | <UIView: 0x7feeb7a79ca0; frame = (334 0; 334 0); layer = <CALayer: 0x600002ae0880>>
   |    |    |    | <UIView: 0x7feeb6f25990; frame = (0 0; 757 219.667); autoresize = W+H; layer = <CALayer: 0x600002aed700>>
   |    |    |    |    | <UIStackView: 0x7feeb6fb7a10; frame = (0 0; 757 219.667); layer = <CALayer: 0x600002aed8c0>>
   |    |    |    |    |    | <UIImageView: 0x7feeb76ceb70; frame = (0 0; 757 131.667); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600002aff560>>
   |    |    |    |    |    | <UILabel: 0x7feeb76ced40; frame = (0 141.667; 757 29.6667); text = 'This is the first slide t...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x600000bddb30>>
   |    |    |    |    |    | <UILabel: 0x7feeb6fb7c60; frame = (0 181.333; 757 18.3333); text = 'This is the description f...'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x600000bca0d0>>
   |    |    | <UIView: 0x7feeb7a79e10; frame = (668 0; 334 0); layer = <CALayer: 0x600002ae0840>>
   |    | <UIPageControl: 0x7feeb76cb9b0; frame = (10 -25; 314 20); autoresize = W; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x600002693180>; layer = <CALayer: 0x600002afdac0>>
   |    |    | <_UIPageControlContentView: 0x7feeb6fb4b10; frame = (111.667 -3; 91 26); layer = <CALayer: 0x600002aed0c0>>
   |    |    |    | <_UIPageControlIndicatorContentView: 0x7feeb6fb73b0; frame = (14.3333 0; 62.6667 26); autoresize = H; layer = <CALayer: 0x600002aec080>>
   |    |    |    |    | <_UIPageIndicatorView: 0x7feeb6f27570; frame = (0.166667 8.16667; 9.66667 9.66667); opaque = NO; userInteractionEnabled = NO; tintColor = UIExtendedGrayColorSpace 0.333333 1; layer = <CALayer: 0x600002ae5b00>>
   |    |    |    |    | <_UIPageIndicatorView: 0x7feeb0809630; frame = (17.5 8.16667; 9.66667 9.66667); opaque = NO; userInteractionEnabled = NO; tintColor = UIExtendedGrayColorSpace 0.666667 1; layer = <CALayer: 0x600002a01000>>
   |    |    |    |    | <_UIPageIndicatorView: 0x7feeb6cd34c0; frame = (35.5 8.16667; 9.66667 9.66667); opaque = NO; userInteractionEnabled = NO; tintColor = UIExtendedGrayColorSpace 0.666667 1; layer = <CALayer: 0x600002a01080>>
   |    |    |    |    | <_UIPageIndicatorView: 0x7feeb6fc6100; frame = (53.1667 8.16667; 9.66667 9.66667); opaque = NO; userInteractionEnabled = NO; tintColor = UIExtendedGrayColorSpace 0.666667 1; layer = <CALayer: 0x600002ae0140>>

這里有兩個例子。 第一個是沒有 UIPageViewController 的有效應用內消息。 第二個是我想要實現的目標,但作為 Android 上的一個工作示例。

在沒有 UIPageViewController 的情況下工作應用內消息Android 上的輪播工作示例

基於這些日志,有人能指出我糾正約束的正確方向嗎? 發生的情況是層次結構中較高的視圖具有 0 高度,但它們的子視圖沒有。 這會導致 0 高度的應用內消息。

編輯

我將模態視圖作為子視圖添加到主視圖中,當 UIPageViewController 出現在層次結構中時,我將它添加到頂部控制器:

一切都是通過代碼完成的。 我沒有添加視圖控制器,只是在主視圖中添加子視圖:

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
if (keyWindow != nil) {
    [keyWindow addSubview:self.parentView]; // self.parentView = blackish background + vertically centered UIView (the actual modal view) + UIStackView for the components
    if (hasCarousel){
        UIViewController *topController = [UIApplication getPresentedViewController];
        if (topController != nil)
            [topController embedViewController:pageViewController inView:carouselWrapper]; // carouselWrapper = UIView containing the pageViewController that is added to the UIStackView above

    }
}

根據我們的評論提供答案...

UIPageViewController加載並設置其“頁面”控制器的視圖大小。 因此,嘗試以相反的方式進行 - 設置頁面視圖控制器的大小以匹配“頁面”大小有點棘手。

此外,如果我們嘗試為每個“頁面”都這樣做,框架會不斷變化,並且(可能)會帶來糟糕的用戶體驗。

但是,我們可以預加載頁面並計算最大頁面高度以設置我們的控制器。

概述代碼將是:

MutableArray *pages = [NSMutableArray new];
// however we load and initialize our page controllers
[pages addObject:FirstPageVC()];
[pages addObject:SecondPageVC()];
// etc

CGFloat maxHeight = 0;

CGSize fitSize = CGSizeMake(_carouselWrapper.frame.size.width, UILayoutFittingCompressedSize.height);

for (UIViewController *vc in pages) {
    // get size of page view
    CGSize sz = [vc.view systemLayoutSizeFittingSize:fitSize withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityDefaultLow];
    maxHeight = MAX(sz.height, maxHeight);
}

// if using the built-in PageControl
//  add height of PageControl + 1.5 (control is shown 1.5-pts below the view)
UIPageControl *c = [UIPageControl new];
maxHeight += [c sizeForNumberOfPages:1].height + 1.5;

// here we can set the height of the view frame for our PageViewController

我玩了一下,在這里放了一個工作示例項目: https : //github.com/DonMag/DynamicPGVC

您展示的內容的基本思想,盡管我將“parentView”(我稱之為 OverlayView)作為一個單獨的視圖子類,以將大量活動排除在主視圖控制器之外。

這是它的外觀:

在此處輸入圖片說明

點擊“標簽”按鈕(細長的矩形顯示“carouselView”的框架):

在此處輸入圖片說明

點擊“圖像”按鈕:

在此處輸入圖片說明

點擊“頁面視圖控制器”按鈕 - 第一個“頁面”(“頁面”很簡單 - 帶有標題和內容標簽的垂直堆棧視圖):

在此處輸入圖片說明

和第二頁,顯示內容的最大高度:

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM