초점이 맞춰진 셀이 다음 셀 아래에 숨어 있습니다.

문제



tvOS에서 컬렉션 뷰를 구현하면 포커스가 있는 셀이 이웃 셀 아래로 잠재적으로 침투할 수 있습니다.



정말 기분 나쁘네요.

전에 가져오기



이럴 때는 UIView#bringSubview(toFront:)를 호출하거나 layer.zPosition를 변경하여 이전에 가져와야합니다.didUpdateFocus 로 구현하면 이런 느낌이 된다고 생각합니다.
    override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
        if context.nextFocusedView == self {
            self.layer.zPosition = 1.0
        } else {
            self.layer.zPosition = 0.0
        }
        super.didUpdateFocus(in: context, with: coordinator)
    }


이것으로 포커스 되고 있는 셀은 맨 앞에 오는군요.
그러나 포커스가 다른 곳으로 옮겨지는 순간에 zPosition을 되돌리고 있기 때문에, 이것은 애니메이션 중에 겹치는 순서가 이상하게 되어 버립니다.



오른쪽 셀이 덮여 있다는 것을 알 수 있습니까?

나중에 초점이 맞춰진 쪽이 앞으로 오도록



다행히 addCoordinatedAnimations에 completion을 전달할 수 있으므로 다음과 같이 구현할 수있었습니다.
private var intermediateZPosition: CGFloat = 0.5
private var workItem: DispatchWorkItem?
private func triggerResetSharedVariable() {
    workItem?.cancel()
    workItem = DispatchWorkItem {
        intermediateZPosition = 0.5
    }
    if let workItem = workItem {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0, execute: workItem)
    }
}

...

    public func applyCoordinatedZPositionState(context: UIFocusUpdateContext, coordinator: UIFocusAnimationCoordinator) {
        var completion: (() -> ())?
        if let next = context.nextFocusedView, next.isDescendant(of: self) {
            self.layer.zPosition = 1.0
        } else if let previous = context.previouslyFocusedView, previous.isDescendant(of: self) {
            intermediateZPosition += 0.000001
            self.layer.zPosition = intermediateZPosition
            completion = {
                if let f = UIScreen.main.focusedView, !f.isDescendant(of: self) {
                    self.layer.zPosition = 0.0
                    triggerResetSharedVariable()
                }
            }
        }
        coordinator.addCoordinatedAnimations(nil, completion: completion)
    }

이제 완전히 포커스 애니메이션이 끝날 때까지 zPosition이 유지됩니다.



도서관이므로 이용하십시오.
htps : // 기주 b. 코 m / 토시 0383 / 후쿠 쿠 sZ 포시 치온 무타인 g

toshi0383/FocusZPositionMutating



필요한 처리를 복사하고 붙여넣어도 괜찮습니다만, 이것만을 위해 일일이 그렇게 하는 것도 귀찮다고 생각하므로, AppDelegate에 이하의 1행을 쓰는 것만으로 셋업이 끝나도록 하고 있습니다.
UIView.fzpm_swizzleDidUpdateFocus()

그리고는, 겹치는 순서를 관리해 주었으면 하는 뷰를 FocusZPositionMutating 의 protocol에 적합시키면, didUpdateFocus 로 마음대로 위의 처리를 불러 줍니다.
class ZPositionView: UIView, FocusZPositionMutating { }
UIView#isDescendant(of:) 로 판정하고 있기 때문에, 포커스 가능한 뷰일 필요는 없습니다.

요약



포커스로 뷰가 겹쳐 버릴 때는 zPosition에 주의합시다.
AbemaTV의 프로그램표는 기본적으로 옆의 셀과 덮여 있으므로 관리가 힘들었습니다만, 라이브러리화 할 수 있었으므로 코드가 깨끗이 했습니다.

Example에 몇 종류의 샘플 준비하고 있으므로 신경이 쓰이는 분은 체크해 보세요.
htps : // 기주 b. 코 m / 토시 0383 / 후쿠 쿠 sZ 포시 치온 무타인 g

이상입니다!

좋은 웹페이지 즐겨찾기