code

iOS 11 iPhone X 시뮬레이터 UI 탭바 아이콘과 제목이 서로를 덮으면서 렌더링됩니다.

starcafe 2023. 6. 2. 20:41
반응형

iOS 11 iPhone X 시뮬레이터 UI 탭바 아이콘과 제목이 서로를 덮으면서 렌더링됩니다.

UI TabBar 구성 요소 주변에서 아이폰 X 시뮬레이터에 문제가 있는 사람이 있습니까?

내 것은 아이콘과 제목을 서로 겹쳐 렌더링하는 것 같습니다. 누락된 것이 있는지 확실하지 않습니다. iPhone 8 시뮬레이터와 스토리보드에 표시된 것처럼 정상적으로 보이는 실제 장치 하나에서도 실행했습니다.

아이폰 X:

아이폰 X UI 탭 모음 버그

아이폰 8

iPhone 8 UI 탭 모음 작동

저는 단순히 무효라고 전화를 걸어 문제를 해결할 수 있었습니다.뷰DidLayoutSubview의 UI 탭 표시줄에 있는 고유 콘텐츠 크기입니다.

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self.tabBar invalidateIntrinsicContentSize];
}

참고: 탭 모음의 하단은 안전 영역이 아닌 기본 보기의 하단에 포함되어야 하며 탭 모음에는 높이 제한이 없어야 합니다.

VoidLess에서 제공하는 답변은 TabBar 문제를 부분적으로만 해결합니다.탭 표시줄 내의 레이아웃 문제를 해결하지만, 탭 표시줄을 숨기는 뷰 컨트롤러를 사용하는 경우, 애니메이션 중에 탭 표시줄이 잘못 렌더링됩니다(복사하기 위해서는 두 개의 세그(모달 하나와 푸시 하나)가 있는 것이 좋습니다).이러한 항목을 번갈아 표시하면 탭 표시줄이 제자리에서 렌더링되는 것을 볼 수 있습니다.아래 코드는 두 가지 문제를 모두 해결합니다.사과 잘했어요.

class SafeAreaFixTabBar: UITabBar {

var oldSafeAreaInsets = UIEdgeInsets.zero

@available(iOS 11.0, *)
override func safeAreaInsetsDidChange() {
    super.safeAreaInsetsDidChange()

    if oldSafeAreaInsets != safeAreaInsets {
        oldSafeAreaInsets = safeAreaInsets

        invalidateIntrinsicContentSize()
        superview?.setNeedsLayout()
        superview?.layoutSubviews()
    }
}

override func sizeThatFits(_ size: CGSize) -> CGSize {
    var size = super.sizeThatFits(size)
    if #available(iOS 11.0, *) {
        let bottomInset = safeAreaInsets.bottom
        if bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90) {
            size.height += bottomInset
        }
    }
    return size
}

override var frame: CGRect {
    get {
        return super.frame
    }
    set {
        var tmp = newValue
        if let superview = superview, tmp.maxY != 
        superview.frame.height {
            tmp.origin.y = superview.frame.height - tmp.height
        }

        super.frame = tmp
        }
    }
}

목표-C 코드:

@implementation VSTabBarFix {
    UIEdgeInsets oldSafeAreaInsets;
}


- (void)awakeFromNib {
    [super awakeFromNib];

    oldSafeAreaInsets = UIEdgeInsetsZero;
}


- (void)safeAreaInsetsDidChange {
    [super safeAreaInsetsDidChange];

    if (!UIEdgeInsetsEqualToEdgeInsets(oldSafeAreaInsets, self.safeAreaInsets)) {
        [self invalidateIntrinsicContentSize];

        if (self.superview) {
            [self.superview setNeedsLayout];
            [self.superview layoutSubviews];
        }
    }
}

- (CGSize)sizeThatFits:(CGSize)size {
    size = [super sizeThatFits:size];

    if (@available(iOS 11.0, *)) {
        float bottomInset = self.safeAreaInsets.bottom;
        if (bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90)) {
            size.height += bottomInset;
        }
    }

    return size;
}


- (void)setFrame:(CGRect)frame {
    if (self.superview) {
        if (frame.origin.y + frame.size.height != self.superview.frame.size.height) {
            frame.origin.y = self.superview.frame.size.height - frame.size.height;
        }
    }
    [super setFrame:frame];
}


@end

우리가 그 문제를 해결할 수 있는 묘책이 있습니다.

UI 보기 안에 UI 탭 모음을 넣기만 하면 됩니다.

이것은 저에게 정말 효과가 있습니다.

또는 이 링크를 따라 자세한 내용을 확인할 수 있습니다.

오라이드를 합니다.UITabBar sizeThatFits(_)안전한 지역을 위해

extension UITabBar {
    static let height: CGFloat = 49.0

    override open func sizeThatFits(_ size: CGSize) -> CGSize {
        guard let window = UIApplication.shared.keyWindow else {
            return super.sizeThatFits(size)
        }
        var sizeThatFits = super.sizeThatFits(size)
        if #available(iOS 11.0, *) {
            sizeThatFits.height = UITabBar.height + window.safeAreaInsets.bottom
        } else {
            sizeThatFits.height = UITabBar.height
        }
        return sizeThatFits
    }
}

을 에추했니다에 했습니다.viewWillAppear의 의나습로대관로.UITabBarController제공된 답변 중 하나도 제게 효과가 없었기 때문입니다.

tabBar.invalidateIntrinsicContentSize()
tabBar.superview?.setNeedsLayout()
tabBar.superview?.layoutSubviews()

저도 같은 문제가 있었습니다.

여기에 이미지 설명 입력

UITabBar의 하단 제약 조건에서 0이 아닌 상수를 안전 영역으로 설정한 경우:

여기에 이미지 설명 입력

예상대로 작동하기 시작합니다.

여기에 이미지 설명 입력

그것이 제가 한 유일한 변화이고 왜 그것이 효과가 있는지 모르겠지만 누군가가 있다면 저는 알고 싶습니다.

하위 분류된 UI 탭 표시줄을 사용하여 safeAreaInset을 적용하여 수정합니다.

class SafeAreaFixTabBar: UITabBar {

    var oldSafeAreaInsets = UIEdgeInsets.zero

    @available(iOS 11.0, *)
    override func safeAreaInsetsDidChange() {
        super.safeAreaInsetsDidChange()

        if oldSafeAreaInsets != safeAreaInsets {
            oldSafeAreaInsets = safeAreaInsets

            invalidateIntrinsicContentSize()
            superview?.setNeedsLayout()
            superview?.layoutSubviews()
        }
    }

    override func sizeThatFits(_ size: CGSize) -> CGSize {
        var size = super.sizeThatFits(size)
        if #available(iOS 11.0, *) {
            let bottomInset = safeAreaInsets.bottom
            if bottomInset > 0 && size.height < 50 {
                size.height += bottomInset
            }
        }
        return size
    }
}

바를 아래에서 1포인트 떨어진 곳으로 이동하는 것이 저에게 효과가 있었습니다.

물론 입력해야 하는 공백이 생길 수 있지만 텍스트/아이콘이 올바르게 배치되었습니다.

아하! 사실 마법이에요!

저는 몇 시간 동안 애플을 욕한 끝에 마침내 이것을 알게 되었습니다.

UIKit는 실제로 이 문제를 처리하며, 이동된 탭 모음 항목은 잘못된 설정(그리고 아마도 실제 UIKit 버그)으로 인해 발생한 것으로 보입니다.하위 분류나 배경 보기가 필요하지 않습니다.

UITabBar는 하단 안전 영역이 아닌 하단의 수퍼뷰로 제한되는 경우 "그냥 작동"합니다.

인터페이스 빌더에서도 작동합니다.

올바른 설정

IB 관련 업무

  1. iPhone X로 보는 인터페이스 빌더에서 UIT 탭바를 끌어서 하단 안전 영역에 삽입합니다.드롭하면 올바른 모양이어야 합니다(아래쪽 가장자리까지 공간을 채웁니다).
  2. 그런 다음 "누락 제약 조건 추가"를 수행하면 IB가 올바른 제약 조건을 추가하고 탭 모음이 모든 iPhone에서 마법처럼 작동합니다! (하단 제약 조건은 iPhone X 안전하지 않은 영역의 높이와 같은 상수 값을 가지는 것처럼 보이지만 실제로 상수는 0입니다.)

때때로 여전히 작동하지 않습니다.

IB에서 중단됨

정말 멍청한 것은 위의 단계에서 IB가 추가한 정확한 제약 조건을 추가하더라도 실제로 IB에서도 버그를 볼 수 있다는 것입니다!

  1. UI 탭 모음을 끌어 하단의 안전 영역에 삽입하지 마십시오.
  2. 선행, 후행 및 하단 제약 조건을 모두 감독에 추가합니다(안전 영역이 아님). 이상하게도 하단 제약 조건 검사기에서 "첫 번째 및 두 번째 항목 반전"을 수행하면 이 문제가 해결됩니다.¯_(ツ)_/¯

로 해결했습니다.[tabController.view setNeedsLayout];모달 완료 블록을 해제한 후.

[vc dismissViewControllerAnimated:YES completion:^(){ 
     UITabBarController* tabController = [UIApplication sharedApplication].delegate.window.rootViewController;
     [tabController.view setNeedsLayout];
}];

UI 탭 표시줄이 홈 버튼/라인 위에 오도록 높이가 증가하지만 하위 보기를 원래 위치에 그리고 하위 보기 위에 UIT 탭 표시줄 항목을 겹칩니다.

해결 방법으로 iPhone X를 검색한 다음 보기 높이를 32px 축소하여 홈 라인 위의 안전한 영역에 탭 표시줄이 표시되도록 할 수 있습니다.

예를 들어 TabBar를 프로그래밍 방식으로 작성하는 경우

self.tabBarController = [[UITabBarController alloc] init];
self.window.rootViewController = self.tabBarController;

사용:

#define IS_IPHONEX (([[UIScreen mainScreen] bounds].size.height-812)?NO:YES)
self.tabBarController = [[UITabBarController alloc] init];    
self.window.rootViewController = [[UIViewController alloc] init] ;
if(IS_IPHONEX)
    self.window.rootViewController.view.frame = CGRectMake(self.window.rootViewController.view.frame.origin.x, self.window.rootViewController.view.frame.origin.y, self.window.rootViewController.view.frame.size.width, self.window.rootViewController.view.frame.size.height + 32) ;
[self.window.rootViewController.view addSubview:self.tabBarController.view];
self.tabBarController.tabBar.barTintColor = [UIColor colorWithWhite:0.98 alpha:1.0] ;
self.window.rootViewController.view.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1.0] ;

참고: 보기 크기와 탭 모음 레이아웃은 OS에 의해 설정되므로 버그일 수 있습니다.아마도 아이폰 X 휴먼 인터페이스 가이드라인에 있는 애플의 스크린샷과 같이 https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/ 에 표시될 것입니다.

제 사례는 UITabBar 컨트롤러에서 사용자 지정 UITabBar 높이를 다음과 같이 설정한 경우입니다.

  override func viewWillLayoutSubviews() {            
        var tabFrame = tabBar.frame
        tabFrame.size.height = 60
        tabFrame.origin.y = self.view.frame.size.height - 60
        tabBar.frame = tabFrame
    }

이 코드를 제거하는 것이 아이폰 X에서 탭바가 올바르게 표시되는 해결책이었습니다.

제가 찾은 가장 간단한 해결책은 탭 모음의 하단과 안전한 AreaLayoutGuide.bottom 사이에 0.2pt 공간을 추가하는 것이었습니다.이렇게 닻을.

tabBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -0.2)

사용자 지정 TabBar 컨트롤러에서 UITTabBar 프레임을 설정할 때도 같은 문제가 발생했습니다.

self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight);

방금 새 크기로 조정했더니 문제가 사라졌습니다.

if(IS_IPHONE_X){
    self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kPhoneXTabBarHeight, self.view.frame.size.width, kPhoneXTabBarHeight);
}
else{
    self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight);
}

오늘 스토리보드의 뷰 컨트롤러에 수동으로 추가된 UI 탭바에서 이 문제를 발견했습니다. 안전 영역의 하단에 상수 0으로 정렬하면 문제가 발생하지만 1로 변경하면 문제가 해결됩니다.UIT 탭바가 정상보다 1픽셀 더 올라간 것은 제 애플리케이션에 허용되었습니다.

나는 이 문제로 머리를 긁적였습니다.탭바가 초기화되고 계층 보기에 추가되는 방식과 관련이 있는 것 같습니다.저는 또한 전화와 같은 위의 해결책을 시도했습니다.invalidateIntrinsicContentSize및 프임설 및정레및▁the▁settingbottomInsetsUITabBar 하위 클래스 안에 있습니다.이들은 일시적으로 작동하는 것처럼 보이며 일부 다른 시나리오를 중단하거나 모호한 레이아웃 문제를 일으켜 탭 표시줄을 후퇴시킵니다. 때 제한을 UIT 탭.Yanchor, 하지만 둘 다 문제를 해결하지 못했습니다.view debugger에서 문제가 재현되기 전과 후에 tabBar 높이가 정확하다는 것을 알게 되어 하위 뷰에 문제가 있다고 생각하게 되었습니다.저는 아래 코드를 사용하여 다른 시나리오를 되돌리지 않고 이 문제를 성공적으로 해결했습니다.

- (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    if (DEVICE_IS_IPHONEX())
    {
        [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            for (UIView *view in self.tabBar.subviews)
            {
                if ([NSStringFromClass(view.class) containsString:@"UITabBarButton"])
                {
                    if (@available (iOS 11, *))
                    {
                        [view.bottomAnchor constraintEqualToAnchor:view.superview.safeAreaLayoutGuide.bottomAnchor].active = YES;
                    }
                }
            }
        } completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            [self.tabBar layoutSubviews];
        }];
    }
}

가정:현재 다른 기기에서는 재생이 되지 않는 것 같아서 아이폰X 전용으로 하고 있습니다.향후 iOS 릴리스에서 Apple이 UITabBarButton 클래스의 이름을 변경하지 않는다는 가정을 기반으로 합니다.우리는 애플이 UITabBar에 내부 하위 보기를 더 추가할 경우 이를 위해 코드를 수정해야 할 수 있는 경우에만 UITabBarButton에서 이 작업을 수행합니다.

이 방법이 효과가 있는지 알려 주십시오. 제안과 개선 사항을 확인할 수 있습니다!

이에 대한 신속한 등가물을 만드는 것은 간단해야 합니다.

이 자습서에서:

https://github.com/eggswift/ESTabBarController

그리고 앱 대리인 클래스에서 이 줄을 쓰는 탭 모음의 초기화 후

(self.tabBarController.tabBar as? ESTabBar)?.itemCustomPositioning = .fillIncludeSeparator

탭 모음 문제를 해결합니다.

그것이 당신의 문제를 해결하기를 바랍니다.

감사해요.

탭 표시줄을 선택하고 다음과 같이 검사자 편집기에서 "면적 상대 여백 저장" 확인란을 설정합니다.

여기에 이미지 설명 입력

비슷한 문제가 있었습니다. 처음에는 올바르게 렌더링되었지만 설정한 후badgeValue탭바 중 하나에레이아웃을 깬 항목입니다.하위 분류 없이 나에게 효과가 있었던 것.UITabBar이것이, 내가 이미 만든 것입니다.UITabBarController아류의

-(void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    NSLayoutYAxisAnchor *tabBarBottomAnchor = self.tabBar.bottomAnchor;
    NSLayoutYAxisAnchor *tabBarSuperviewBottomAnchor = self.tabBar.superview.bottomAnchor;
    [tabBarBottomAnchor constraintEqualToAnchor:tabBarSuperviewBottomAnchor].active = YES;
    [self.view layoutIfNeeded];
}

구속조건/앵커가 동일한 뷰 계층에 있는지 확인하고 충돌을 방지하기 위해 tabBar superview를 사용했습니다.

제가 알기로는 UIKit 버그인 것 같으니 자동 레이아웃 엔진이 탭 바를 다시 올바르게 레이아웃 할 수 있도록 탭 바 제약 조건을 다시 작성/재설정하면 됩니다.

탭 막대에 대한 높이 제한이 있으면 제거해 보십시오.

동일한 문제에 직면하여 이 문제를 제거하면 문제가 해결됩니다.

스토리보드에 새 UITabBarController를 만들고 모든 뷰 컨트롤러를 이 새 UITabBarController에 푸시했습니다.그래서, 모든 것이 아이폰 X 시뮬레이터에서 잘 작동합니다.

iPhone의 경우 서브클래스 UI 탭바 컨트롤러를 사용할 수 있습니다.

class MyTabBarController: UITabBarController {

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if #available(iOS 11, *) {
        self.tabBar.heightAnchor.constraint(equalToConstant: 40).isActive = true
        self.tabBar.invalidateIntrinsicContentSize()
    }
  }
}

스토리보드로 이동하여 안전 영역 레이아웃 가이드 사용을 허용하고 UITabbarController의 클래스를 MyTabbarController로 변경합니다.

P.S 이 솔루션은 범용 응용 프로그램 및 iPad의 경우 테스트되지 않습니다.

@3x크기의 스플래시 화면 변경 시도(3726 x 6624)

나는, 제거[self.tabBar setBackgroundImage:]일, UIKit 버그일 수도 있습니다.

이것이 모든 문제를 해결했습니다.

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let currentHeight = tabBar.frame.height
        tabBar.frame = CGRect(x: 0, y: view.frame.size.height - currentHeight, width: view.frame.size.width, height: currentHeight)
    }

제가 사용한 것은UITabBarController스토리보드에서 처음에는 잘 작동했지만, 새로운 Xcode 버전으로 업그레이드한 후 탭바의 높이와 관련된 문제가 발생하기 시작했습니다.

나에게, 수정 사항은 기존의 것을 삭제하는 것이었습니다.UITabBarController스토리보드에서 다시 만들고 인터페이스 작성기 개체 라이브러리에서 끌어 다시 만듭니다.

전체를 쓰는 사람들을 위하여.UITabBarController프로그래밍 방식으로 사용할 수 있습니다.UITabBarItem.appearance().titlePositionAdjustment타이틀 위치를 조정하기 위해

따라서 이 경우 아이콘과 제목 사이에 공백을 추가하려면 이를 사용합니다.viewDidLoad:

    override func viewDidLoad() {
        super.viewDidLoad()

        // Specify amount to offset a position, positive for right or down, negative for left or up
        let verticalUIOffset = UIOffset(horizontal: 0, vertical: hasTopNotch() ? 5 : 0)

        UITabBarItem.appearance().titlePositionAdjustment = verticalUIOffset
    }

장치에 Notch(노치) 화면이 있는지 감지:

  func hasTopNotch() -> Bool {
      if #available(iOS 11.0, tvOS 11.0, *) {
        return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
      }
      return false
  }

이 경우 보기 계층에서 탭 표시줄을 선택한 다음 편집기 -> 자동 레이아웃 문제 해결로 이동하고 "선택된 보기"("보기의 모든 보기"가 아님)에서 "누락된 제약 조건 추가"를 선택합니다.

저는 탭바가 배치된 후 탭바의 항목을 설정하여 동일한 문제를 해결하고 있었습니다.

저의 경우 다음과 같은 경우에 문제가 발생했습니다.

  1. 사용자 지정 보기 컨트롤러가 있습니다.
  2. 보기 컨트롤러의 이니셜라이저에 UI 탭 표시줄이 생성됩니다.
  3. 탭 표시줄 항목은 보기가 로드되기 전에 설정됩니다.
  4. View did load에서 탭 표시줄이 뷰 컨트롤러의 기본 뷰에 추가됩니다.
  5. 그러면 당신이 언급한 대로 항목이 렌더링됩니다.

iPhoneX의 UIKit 버그인 것 같습니다. 작동하기 때문입니다.

if (@available(iOS 11.0, *)) {
    if ([UIApplication sharedApplication].keyWindow.safeAreaInsets.top > 0.0) {
       self.tabBarBottomLayoutConstraint.constant = 1.0;
    }
} 

언급URL : https://stackoverflow.com/questions/46214740/ios-11-iphone-x-simulator-uitabbar-icons-and-titles-being-rendered-on-top-coveri

반응형