使用Apple TV上的多个控件管理Focus

时间:2016-05-03 14:19:25

标签: ios swift swift2 tvos

我的屏幕上有多个控件。右上角的集合视图,然后是左中心的按钮,除了按钮,我有另一个集合视图。请参阅附件中的enter image description here

图片

我可以将焦点从按钮移动到底部集合视图,反之亦然。我已经创建了一个焦点指南,如下所示:


        focusGuide.preferredFocusedView = self.btn
        self.view.addLayoutGuide(self.focusGuide)

        self.focusGuide.topAnchor.constraintEqualToAnchor(collectionViewHeader.topAnchor).active = true
        self.focusGuide.bottomAnchor.constraintEqualToAnchor(collectionViewBottom.topAnchor).active = true
        self.focusGuide.leadingAnchor.constraintEqualToAnchor(collectionViewBottom.leadingAnchor).active = true
        self.focusGuide.widthAnchor.constraintEqualToAnchor(collectionViewBottom.widthAnchor).active = true

在didUpdateFocusInContext:中,我写了:


    override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
        super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator)

        guard let nextFocusedView = context.nextFocusedView else { return }

            if(nextFocusedView .isKindOfClass(bottomCell)) {
            self.focusGuide.preferredFocusedView = self.btn
        } else {
            self.focusGuide.preferredFocusedView = self.collectionViewBottom
        }
    }

但是,我无法将焦点从按钮移动到顶部集合视图。我可能需要多个焦点指南,但我不知道应该在那里发生什么。谁可以帮我这个事?

谢谢

2 个答案:

答案 0 :(得分:0)

我的UI的很多部分都有类似的问题,所以最终定义了一个自定义视图来创建更大的屏幕区域,代表可聚焦控件组。因为我将这些较大的区域设置为覆盖不包含控件的空白区域,所以它们会截取焦点移动并转移到焦点到区域内的控件,而不是垂直或水平对齐,而原始控件则从焦点开始。

这是自定义视图。您可以通过在IB中放置一个或多个控件来使用它。

请注意,它具有其他功能,例如强制将焦点移动到特定控件,而不必覆盖preferredFocusView,但如果不需要,可以删除它们。)

class FocusGroup : UIView
{
   weak private var nextFocusView:UIView? = nil
   weak var initialView:UIView?           = nil
   var captureFocus:Bool                  = false

   func focusOnView(view:UIView, now:Bool=false)
   {
      if not(view.isDescendantOfView(self))
      || view === self
      { return }

      nextFocusView = view
      setNeedsFocusUpdate()
      if now  { updateFocusIfNeeded() }
   }

   func resetFocus(now now:Bool=false)
   {
      nextFocusView = nil
      setNeedsFocusUpdate()
      if now  { updateFocusIfNeeded() }
   }

   override func canBecomeFocused() -> Bool 
   {
      if nextFocusView != nil { return true }
      if containsFocus { return false }      
      return firstFocusableSubView() != nil 
   }


   func firstFocusableSubView() -> UIView?
   {

     return findSubview({ 
                           $0.canBecomeFocused()
                           && $0.userInteractionEnabled
                           && $0.visible
                           &&  ( not($0 is UIButton)
                                 || ($0 as! UIButton).enabled )
                       })
   }


   override var preferredFocusedView: UIView? 
   {
      if let viewToFocus = ( nextFocusView ?? initialView ) ?? firstFocusableSubView() 
      {
        return viewToFocus
      }
      return nil
   }

   override func shouldUpdateFocusInContext(context: UIFocusUpdateContext) -> Bool 
   {
      // when capturing focus, prevent navigation outside of grouped subviews
      if captureFocus 
      && containsFocus 
      && context.previouslyFocusedView!.isDescendantOfView(self)
      && (
            context.nextFocusedView == nil
            || context.nextFocusedView === self 
            || not(context.nextFocusedView!.isDescendantOfView(self))
         )
      { return false }

      return true
   }

   override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) 
   {
      // give focus to specific view as requested
      if nextFocusView != nil
      {
         if context.nextFocusedView === nextFocusView
         || not(nextFocusView!.canBecomeFocused())
         { nextFocusView = nil }
         return
      }      
   }

}

答案 1 :(得分:0)

只需在按钮上方和顶部集合视图的左侧插入焦点指南,即可将焦点重定向到顶部集合视图:

 focusGuide.preferredFocusedView = self.topView
    self.view.addLayoutGuide(focusGuide)

    self.focusGuide.topAnchor.constraintEqualToAnchor(topView.topAnchor).active = true
    self.focusGuide.bottomAnchor.constraintEqualToAnchor(topView.bottomAnchor).active = true
    self.focusGuide.leadingAnchor.constraintEqualToAnchor(btn.leadingAnchor).active = true
    self.focusGuide.trailingAnchor.constraintEqualToAnchor(btn.trailingAnchor).active = true

您可能还希望在按钮右侧和顶部收藏视图下方插入焦点指南,以便从顶部行向下导航将焦点重定向到按钮而不是底部行。