사용자 지정 컨테이너보기 컨트롤러에 포함 된 콘텐츠는 탐색 모음 아래에 있습니다.
최신 정보
Tim의 답변에 따라 사용자 지정 컨테이너의 일부인 scrollview (또는 하위 클래스)가있는 각 뷰 컨트롤러에서 다음을 구현했습니다.
- (void)didMoveToParentViewController:(UIViewController *)parent
{
if (parent) {
CGFloat top = parent.topLayoutGuide.length;
CGFloat bottom = parent.bottomLayoutGuide.length;
// this is the most important part here, because the first view controller added
// never had the layout issue, it was always the second. if we applied these
// edge insets to the first view controller, then it would lay out incorrectly.
// first detect if it's laid out correctly with the following condition, and if
// not, manually make the adjustments since it seems like UIKit is failing to do so
if (self.collectionView.contentInset.top != top) {
UIEdgeInsets newInsets = UIEdgeInsetsMake(top, 0, bottom, 0);
self.collectionView.contentInset = newInsets;
self.collectionView.scrollIndicatorInsets = newInsets;
}
}
[super didMoveToParentViewController:parent];
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
라는 사용자 지정 컨테이너보기 컨트롤러가 SegmentedPageViewController
있습니다. 나는 이것을 UINavigationController's rootViewController
.
의 목적은 NavController의 titleView로 설정된를 SegmentedPageViewController
허용하여 UISegmentedControl
다른 자식 뷰 컨트롤러간에 전환 할 수 있도록하는 것입니다 .
이러한 자식 뷰 컨트롤러는 모두 스크롤 뷰, 테이블 뷰 또는 컬렉션 뷰를 포함합니다.
첫 번째 뷰 컨트롤러가 제대로로드되고 탐색 모음 아래에 올바르게 배치 된 것을 발견했습니다. 그러나 새 뷰 컨트롤러로 전환하면 navbar가 존중되지 않고 뷰가 nav bar 아래에 설정됩니다.
우리는 자동 레이아웃과 인터페이스 빌더를 사용하고 있습니다. 생각할 수있는 모든 것을 시도했지만 일관된 해결책을 찾을 수 없습니다.
다음은 사용자가 분할 된 컨트롤을 탭할 때 첫 번째 뷰 컨트롤러를 설정하고 다른 뷰 컨트롤러로 전환하는 주요 코드 블록입니다.
- (void)switchFromViewController:(UIViewController *)oldVC toViewController:(UIViewController *)newVC
{
if (newVC == oldVC) return;
// Check the newVC is non-nil otherwise expect a crash: NSInvalidArgumentException
if (newVC) {
// Set the new view controller frame (in this case to be the size of the available screen bounds)
// Calulate any other frame animations here (e.g. for the oldVC)
newVC.view.frame = self.view.bounds;
// Check the oldVC is non-nil otherwise expect a crash: NSInvalidArgumentException
if (oldVC) {
// **** THIS RUNS WHEN A NEW VC IS SET ****
// DIFFERENT FROM FIRST VC IN THAT WE TRANSITION INSTEAD OF JUST SETTING
// Start both the view controller transitions
[oldVC willMoveToParentViewController:nil];
[self addChildViewController:newVC];
// Swap the view controllers
// No frame animations in this code but these would go in the animations block
[self transitionFromViewController:oldVC
toViewController:newVC
duration:0.25
options:UIViewAnimationOptionLayoutSubviews
animations:^{}
completion:^(BOOL finished) {
// Finish both the view controller transitions
[oldVC removeFromParentViewController];
[newVC didMoveToParentViewController:self];
// Store a reference to the current controller
self.currentViewController = newVC;
}];
} else {
// **** THIS RUNS WHEN THE FIRST VC IS SET ****
// JUST STANDARD VIEW CONTROLLER CONTAINMENT
// Otherwise we are adding a view controller for the first time
// Start the view controller transition
[self addChildViewController:newVC];
// Add the new view controller view to the view hierarchy
[self.view addSubview:newVC.view];
// End the view controller transition
[newVC didMoveToParentViewController:self];
// Store a reference to the current controller
self.currentViewController = newVC;
}
}
}
Your custom container view controller will need to adjust the contentInset
of the second view controller according to your known navigation bar height, respecting the automaticallyAdjustsScrollViewInsets
property of the child view controller. (You may also be interested in the topLayoutGuide
property of your container - make sure it returns the right value during and after the view switch.)
UIKit is remarkably inconsistent (and buggy) in how it applies this logic; sometimes you'll see it perform this adjustment automatically for you by reaching multiple view controllers down in the hierarchy, but often after a custom container switch you'll need to do the work yourself.
This seems to all be a lot simpler than what people make out.
UINavigationController will set scrollview insets only while laying out subviews. addChildViewController:
does not cause a layout, however, so after calling it, you just need to call setNeedsLayout
on your navigationController. Here's what I do while switching views in a custom tab-like view:
[self addChildViewController:newcontroller];
[self.view insertSubview:newview atIndex:0];
[self.navigationController.view setNeedsLayout];
The last line will cause scrollview insets to be re-calculated for the new view controller's contents.
FYI in case anyone is having a similar problem: this issue can occur even without embedded view controllers. It appears that automaticallyAdjustsScrollViewInsets
is only applied if your scrollview (or tableview/collectionview/webview) is the first view in their view controller's hierarchy.
나는 종종 배경 이미지를 갖기 위해 내 계층 구조에서 UIImageView를 먼저 추가합니다. 이렇게하면 viewDidLayoutSubviews에서 scrollview의 가장자리 삽입을 수동으로 설정해야합니다.
- (void) viewDidLayoutSubviews {
CGFloat top = self.topLayoutGuide.length;
CGFloat bottom = self.bottomLayoutGuide.length;
UIEdgeInsets newInsets = UIEdgeInsetsMake(top, 0, bottom, 0);
self.collectionView.contentInset = newInsets;
}
더 나은 해결책을 찾았고 문서화되지 않은 UINavigationController 메서드를 사용했습니다.
#import <UIKit/UIKit.h>
@interface UINavigationController (ContentInset)
- (void) computeAndApplyScrollContentInsetDeltaForViewController:(UIViewController*) controller;
@end
#import "UINavigationController+ContentInset.h"
@interface UINavigationController()
- (void)_computeAndApplyScrollContentInsetDeltaForViewController:(id)arg1;
@end
@implementation UINavigationController (ContentInset)
- (void) computeAndApplyScrollContentInsetDeltaForViewController:(UIViewController*) controller
{
if ([UINavigationController instancesRespondToSelector:@selector(_computeAndApplyScrollContentInsetDeltaForViewController:)])
[self _computeAndApplyScrollContentInsetDeltaForViewController:controller];
}
@end
그럼 이렇게 해
- (void) cycleFromViewController: (UIViewController*) oldC
toViewController: (UIViewController*) newC
{
[oldC willMoveToParentViewController:nil];
[self addChildViewController:newC];
[self transitionFromViewController: oldC toViewController: newC
duration: 0.25 options:0
animations:^{
newC.view.frame = oldC.view.frame;
[self.navigationController computeAndApplyScrollContentInsetDeltaForViewController:newC];
}
completion:^(BOOL finished) {
[oldC removeFromParentViewController];
[newC didMoveToParentViewController:self];
}];
}
edgesForExtendedLayout = []
내 자녀 컨트롤러에 대한 설정 이 나를 위해 일했습니다.
'Development Tip' 카테고리의 다른 글
자바 스크립트로 콘솔 입력을 받으려면 어떻게해야합니까? (0) | 2021.01.08 |
---|---|
LL (1), LR (1), LR (0), LALR (1) 문법의 예? (0) | 2021.01.08 |
MSBuild에 "VCTargetsPath"속성에 대한 값이 없습니다. (0) | 2021.01.07 |
맞춤 이벤트를 통해 추가 데이터를 전달하는 방법이 있습니까? (0) | 2021.01.07 |
Java의 String.format () 및 16 진수 (0) | 2021.01.07 |