iOS 13도 Navigation BarButton의 위치를 조정하고 싶어요.

14712 단어 iOSiOS13Swift5.1Swift

입문


StackView가 iOS11에 들어간 Navigation BarButton의 영향으로 저는 예전에 Qiita에 private view를 조작하는 방법을 썼지만 iOS13에서 private view를 조작하면 욕을 먹습니다(Crash).
참고로 다음과 같은 오류가 발생할 수 있습니다.
Client error attempting to change layout margins of a private view
그래서 애플을 화나게 하지 않는 조작법을 소개해 드리겠습니다.
다음은 이전의 보도입니다.이 글은 아래 개량판의 서 있는 위치이다.
iOS11에서 NavigationBarButton으로 주변 사양이 변경되어 UIBarButton Item의 위치 조정이 원활하지 않음 - Qiita
https://qiita.com/rd0501/items/2309e14c5a3f365867ec

하면, 만약, 만약...


Tap 범위도 좋으려면 양쪽 8pt 바깥쪽에 BarButton을 설정하는 것은 불가능합니다
참고: UIBarButtonItem & iOS11
https://www.matrixprojects.net/p/uibarbuttonitem-ios11#alignment-rect-insets

우선, 각 운영체제의 보기 차원을 검사한다


iOS13
iOS11
iOS10



※ 지난번 이미지의 반복 사용이라 불균형이 있습니다...
View Hierarchy를 본 느낌으로 iOS11과 iOS13의 차이는 많지 않다.
다른 것은 프라이빗 클래스를 사용했는지 여부입니다.

처리 방법


본론입니다.
먼저 말하면 위에서 인용한 다음과 같은 보도의 총체적인 느낌이다.
UIBarButtonItem & iOS 11
https://www.matrixprojects.net/p/uibarbuttonitem-ios11/

개요


1. 작업 가능alignmentRectInsets View 등 준비
2. navigationItem.left or rightBarButtonItems의 firstItem에 폭 8pt.fixedSpace의 UIBarButtonItem 추가
3. 추가할 UIBarButtonItem을 생성하지만 alignmentRectInsets를 사용하여 spacer(.fixedSpace)의 양을 엇갈리게 합니다(leftBarButtonItem 왼쪽 8pt, rightBarButtonItem 오른쪽 8pt)

alignmentRectInsets를 조작할 수 있는 View 등을 준비합니다.

// 以下のような、後からalignmentRectInsetsを操作できるView等を用意します。

class CustomView: UIView {
    var alignmentRectInsetsOverride: UIEdgeInsets?
    override var alignmentRectInsets: UIEdgeInsets {
        return alignmentRectInsetsOverride ?? super.alignmentRectInsets
    }
}

class CustomButton: UIButton {
    var alignmentRectInsetsOverride: UIEdgeInsets?
    override var alignmentRectInsets: UIEdgeInsets {
        return alignmentRectInsetsOverride ?? super.alignmentRectInsets
    }
}

navigationItem.left or rightBarButton Items first Item에서 너비 8pt의.fixedSpace의 UIBarButton Item 가입

// UIViewController の extension などに以下のような処理を追加して、 UIBarButtonItem を Set するときは以下の setNavLeftButton と setNavRightButton のメソッドを使用するようにする

extension UIViewController {

    func setNavLeftButton(_ button: UIBarButtonItem) {
        self.navigationItem.leftBarButtonItems = self.createBarButtonItemsForEachOS(button: button)
    }

    func setNavRightButton(_ button: UIBarButtonItem) {
        self.navigationItem.rightBarButtonItems = self.createBarButtonItemsForEachOS(button: button)
    }

    // iOS11以降の場合はcustom以外のButtonを入れないと外側からの余白が16ptになってしまうので、その対応のために.fixedSpaceを入れている
    // 入れると8ptになる
    private func createBarButtonItemsForEachOS(button: UIBarButtonItem) -> [UIBarButtonItem] {
        if #available(iOS 11, *) {
            return [self.createSpacer(), button]
        } else {
            return [button]
        }
    }

    private func createSpacer() -> UIBarButtonItem {
        let spacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
        spacer.width = 8 // なんか0にしても8になるので一旦8で
        return spacer
    }
}

추가할 UIBarButtonItem을 생성하지만 alignmentRectInsets를 사용하여 spacer(.fixedSpace)의 양을 엇갈리게 함**(leftBarButtonItem 왼쪽 8pt, rightBarButtonItem 오른쪽 8pt)

// 以下のような、処理を行ってUIBarButtonItemを生成して、Right or LeftBarButtonItem に入れます。

extension UIBarButtonItem {

    enum BarButtonItemPosition {
        case right
        case left
    }

    static func createBarButtonItem(position: BarButtonItemPosition) -> UIBarButtonItem {
        let button = CustomButton(frame: CGRect(x:0, y: 0, width: 24, height: 24))
        // spacerが入っている分8pt外側にずらす
        switch position {
        case .left:
            button.alignmentRectInsetsOverride = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: -8)
        case .right:
            button.alignmentRectInsetsOverride = UIEdgeInsets(top: 0, left: -8, bottom: 0, right: 8)
        }
        button.translatesAutoresizingMaskIntoConstraints = false
        return UIBarButtonItem(customView: button)
    }
}
다음은 구현 예입니다.
// 使用例
class HogeViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // barItem
        let leftButton = UIBarButtonItem.createBarButtonItem(position: .left)
        let rightButton = UIBarButtonItem.createBarButtonItem(position: .right)
        self.setNavLeftButton(leftButton)
        self.setNavRightButton(rightButton)
    }
}
※ 위의 코드는 일부 이동이 불가능할 수 있습니다. 오류가 발생하면 수정 요청을 제출하십시오!

참고 자료


UIBarButtonItem & iOS 11
https://www.matrixprojects.net/p/uibarbuttonitem-ios11/
alignmentRectInsets - UIView | Apple Developer Documentation
https://developer.apple.com/documentation/uikit/uiview/1622648-alignmentrectinsets?language=objc
iOS11에서 NavigationBarButton으로 주변 사양이 변경되어 UIBarButton Item의 위치 조정이 원활하지 않음 - Qiita
https://qiita.com/rd0501/items/2309e14c5a3f365867ec

좋은 웹페이지 즐겨찾기