【问题标题】:Manage Focus with multiple controls on Apple TV在 Apple TV 上使用多个控件管理焦点
【发布时间】:2016-05-03 14:19:24
【问题描述】:

我的屏幕上有多个控件。右上角的集合视图,然后是左中心的按钮,除了按钮之外,我还有另一个集合视图。请参考附图

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


        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
        }
    }

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

谢谢

【问题讨论】:

    标签: ios swift swift2 tvos


    【解决方案1】:

    我在 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
          }      
       }
    
    }
    

    【讨论】:

      【解决方案2】:

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

       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
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多