IT TIP

UINavigationController를 사용하여 UIPageViewController에서 푸시 다운 된 콘텐츠

itqueen 2020. 12. 3. 21:30
반응형

UINavigationController를 사용하여 UIPageViewController에서 푸시 다운 된 콘텐츠


업데이트 2

4 인치 장치를 사용하여 iOS 시뮬레이터에서 내 앱을 실행하고 테스트했습니다. 3.5 인치 장치를 사용하여 실행하면 레이블이 점프하지 않습니다. 내 .xib의 Simulated Metrics에서 Retina 4 인치 전체 화면으로 설정했습니다. 4 인치 장치에서만이 문제가 나타나는 이유를 아십니까?

업데이트 1

IB에서는 Simulated Metrics에서 "Navigation Bar"를 선택해도 레이블이 계속 점프합니다. 내 레이블을 첫 화면에서 올바르게 렌더링 할 수있는 유일한 방법은 내비게이션 컨트롤러를 내 창의 루트 뷰 컨트롤러로 설정하지 않는 것입니다.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

내 창의 rootViewController는 rootViewController에 UIPageViewController가 포함 된 UINavigationController로 설정됩니다.

내 앱이로드되면 내비게이션 바와 거의 같은 크기로 콘텐츠가 약간 아래로 눌러 진 상태로 초기보기가 표시됩니다. pageViewController를 스크롤하면 내용이 nib에 배치 된 위치로 점프하고 pageViewController에 의해로드 된 다른 모든 viewController는 괜찮습니다.

navigationcontroller가있는 uipageviewcontroller

내 appDelegate에서 :

self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[ContainerViewController new]];

ContainerViewController에서 :

- (void)viewDidLoad {

    [super viewDidLoad];

    self.pvc = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
                                               navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
                                                             options:nil];
    self.pvc.dataSource = self;
    self.pvc.delegate = self;
    DetailViewController *detail = [DetailViewController new];
    [self.pvc setViewControllers:@[detail]
                       direction:UIPageViewControllerNavigationDirectionForward
                        animated:false
                      completion:nil];

    [self addChildViewController:self.pvc];
    [self.view addSubview:self.pvc.view];
    [self.pvc didMoveToParentViewController:self];
}

그래서 나는 추가 개발 후에 또 다른 대답을 추가하고 마침내 나는 무슨 일이 일어나고 있는지 알아 냈다고 생각합니다. iOS7 에서처럼 UIPageViewController에는 자체 UIScrollView가 있습니다. 이 때문에 automaticallyAdjustsScrollViewInsetsfalse 로 설정 해야합니다. viewDidLoad지금은 다음과 같습니다 .

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.automaticallyAdjustsScrollViewInsets = false;

    DetailViewController *detail = [[DetailViewController alloc] init];
    [self setViewControllers:@[detail]
                   direction:UIPageViewControllerNavigationDirectionForward
                    animated:false
                  completion:nil];
}

아무것도 넣을 필요가 없습니다 viewWillLayoutSubviews(이전 답변 중 하나가 제안했듯이).


이것은 automaticallyAdjustsScrollViewInsets다른 포스터 (@ djibouti33 포함)와 마찬가지로 에 의해 발생합니다 . 그러나이 속성은 두 가지면에서 이상합니다.

  1. 에 설정해야합니다 UINavigationController. 에서 관리하는 자식 컨트롤러에 설정하면 UINavigationController아무런 효과가 없습니다. 1
  2. 스크롤 뷰가 컨트롤러의 하위 뷰에서 인덱스 0에있을 때만 적용됩니다. 2

이 두 가지주의 사항은 스레드의 다른 사용자가 경험하는 간헐적 인 문제를 설명해야합니다.

TLDR : 해결 방법은 다음과 UIPageViewController같이 페이지 컨트롤러 내의 scrollView에 설정이 적용되는 것을 방지하기 위해 인덱스 0에 더미 뷰를 추가하는 것입니다.

pageViewController.view.insertSubview(UIView(), atIndex: 0) // swift

[pageViewController.view insertSubview: [UIView new] atIndex: 0]; // obj-c

contentInset스크롤 뷰에서 직접 설정하는 것이 더 좋지만 불행히도 UIPageViewController스크롤 뷰를 노출하지 않습니다.


Under Top Bars다음 UIPageViewController과 사용자 정의 모두 선택 취소 하십시오 PageContentViewController.

여기에 이미지 설명 입력


내 원래 대답은 당분간 문제를 해결했지만 잠시 후 같은 문제가 다시 나타났습니다.

다음 viewController 계층을 사용합니다.

-- UINavigationController
  -- MyPageViewController
    -- MyDetailViewController

이 문제를 해결하기 위해 다음과 같이하였습니다.

MyPageViewController.m에서

@interface MyPageViewController () <delegates>
  @property (strong) MyDetailViewController *initialViewController;
@end

- (void)viewDidLoad
{
    ...

    // set this once, because we're going to use it in viewWillLayoutSubviews,
    // which gets called multiple times
    self.initialViewController = [MyDetailViewController new];
}

// the problem seemed to stem from the fact that a pageViewController couldn't
// properly lay out it's child view controller initially if it contained a 
// scroll view. by the time we're in layoutSubviews, pageViewController seems to
// have gotten it's bearings and everything is laid out just fine.
- (void)viewWillLayoutSubviews
{
    [self setViewControllers:@[self.initialViewController]
                   direction:UIPageViewControllerNavigationDirectionForward
                    animated:false
                  completion:nil];
}

나도 같은 문제를 안고있어. UIPageViewController의 인스턴스를 만들 때 설정하는 대신 UIPageViewController의 viewDidLoad에 첫 페이지에 대한 setViewControllers를 넣어 해결합니다. 또한 automaticAdjustsScrollViewInsets를 NO로 설정해야합니다.


비슷한 문제가 있었지만 여기에 해결책이 없습니다. 내 문제는 다음 페이지로 스크롤 할 때마다 콘텐츠가 아래로 이동하여 올바른 위치에서 끝나지만 20 픽셀 높이에서 시작된다는 것입니다 (분명히 상태 표시 줄과 관련이 있음). 내 컨테이너 VC는 nav VC가 아닙니다. 잠시 동안 머리카락을 뽑은 후 결국 저에게 도움이 된 해결책은 콘텐츠 VC의 제약 조건이 상단 레이아웃 가이드에 연결되어 있지 않은지 확인하는 것이 었습니다. 이것은 귀하의 경우에는 가능할 수도 있고 불가능할 수도 있지만 제 경우에는 가능했고 콘텐츠 점프를 해결 한 유일한 방법이었습니다. 또한 매우 흥미롭게도이 문제는 전환 스타일이 스크롤로 설정된 경우에만 나타납니다. 페이지 컬로 변경하면 문제가 사라졌습니다. 하지만 스크롤이 필요했습니다. 이것이 다른 사람에게 도움이되기를 바랍니다.


스토리 보드에서이 두 가지 옵션을 선택 해제 해보세요.

여기에 이미지 설명 입력


Try to select PageViewController in storyboard and uncheck "Under Bottom Bars" and "Under Opaque Bars" in Attributes Inspector.


Initially my view controller hierarchy looked like this:

-- UINavigationController
  -- MyContainerViewController
    -- UIPageViewController
      -- MyDetailViewController

I set it up this way so MyContainerViewController could manage a toolbar. I narrowed my problem down to MyContainerViewController, and then it occurred to me that I don't even need it if I subclass UIPageViewController. Now my hierarchy looks like this:

-- UINavigationController
  -- MyPageViewController
    -- MyDetailViewController

MyPageViewController manages it's toolbar, and everything works as expected, both on a 4-inch and 3.5-inch device.


As stated by "Bo:": Putting self.edgesForExtendedLayout = UIRectEdgeNone; in the viewDidLoad of MyPageViewController solved the problem. – Bo


this is my first time posting on stack overflow, but I have searching for a solution to this problem for over a week now.

Here is a solution I came up with, I hope this works for anyone else with the same issue.

I'm not sure how you are initializing your frame for your detail view controller, but I am going to assume you might use: self.view.frame.size.height;

try using: self.view.frame.size.height -= self.navigationController.navigationBar.bounds.size.height;

Hope this helps


I'm seeing the same issue as described by @Danny on iOS 9. I tried updating all my constraints to that they are not constrained to the margins, but it didn't fix the issue. I ended up having to adopt a hack similar to this one as follows;

  • For each content page to be displayed in the UIPageViewController, find the top-most constraint, the one between the Top of a view and the bottom of the top layout guide, and add an outlet for it to the view controller.
  • In each view controller with such an outlet, add another property for the preferred top distance. The two outlets look like this (in Swift):

    @IBOutlet weak var topGuideConstraint: NSLayoutConstraint!
    var topDistance: CGFloat!
    
  • In viewDidLoad(), set topDistance to the value assigned to the constraint in the storyboard:

    override func viewDidLoad() {
        super.viewDidLoad()
        topDistance = topGuideConstraint.constant
    }
    
  • In viewWillLayoutSubviews(), make sure the constraint has the proper value, adjusting for the height of the status bar when the topLayoutGuide.length is zero, which seems to be the case during the transition, but not once it's complete:

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        topGuideConstraint.constant = topDistance + (
            topLayoutGuide.length == 0
                ? UIApplication.sharedApplication().statusBarFrame.size.height
                : 0
        )
    }
    

Repeat for every content view controller displayed in the UIPageViewController. Adjust the offset as appropriate if you're also displaying a UINavigation bar.

This is an unfortunate hack, and I hate having to do it, but after many hours trying different things, I'm at least happy to have something that works so I can move on.


As @djibouti33 already posted:

a pageViewController couldn't properly lay out it's child view controller initially if it contained a scroll view. by the time we're in layoutSubviews, pageViewController seems to have gotten it's bearings and everything is laid out just fine

By waiting for layoutSubViews to load before setting any viewControllers to the UIPageViewController was the only thing that worked for me.

override func viewDidLoad() {
    super.viewDidLoad()
    self.pageViewController = self.storyboard?.instantiateViewController(withIdentifier: "yourPageViewController") as? UIPageViewController       
    self.pageViewController?.dataSource = self

    pageViewController?.automaticallyAdjustsScrollViewInsets = false    
    self.pageViewController?.view.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.height)       
    self.addChildViewController(self.pageViewController!)        
    self.view.addSubview((self.pageViewController?.view)!)       
    self.pageViewController?.didMove(toParentViewController: self)
}


override func viewDidLayoutSubviews() {
    let startVC = self.viewControllerAtIndex(index: 0) as infoDataViewController     
    let viewControllers = NSArray(object: startVC)    
    self.pageViewController?.setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: true, completion: nil)
}

None of above worked for me

Here I found the solution

var pageMenu : CAPSPageMenu?

Instead of adding like this

self.view.addSubview(pageMenu!.view)

아래와 같이 CAPSPageMenu를 추가하십시오.

addChildViewController(pageMenu!) 
self.view.addSubview(pageMenu!.view) 
pageMenu!.didMove(toParentViewController: self)

참조 : iOS Swift : imagePicker를 제시 한 후 SlidingMenuView 잘못된 위치

행복한 코딩!


Swift 버전의 djibouti33의 답변 (문제 해결의 일부가 아닌 줄 제외)

스위프트 3.0

override func viewDidLoad() {
    super.viewDidLoad()
    self.automaticallyAdjustsScrollViewInsets = false
}

참고 URL : https://stackoverflow.com/questions/18202475/content-pushed-down-in-a-uipageviewcontroller-with-uinavigationcontroller

반응형