UISearchController的自定义动画?

时间:2018-01-17 15:13:21

标签: ios swift core-animation uisearchcontroller

我在嵌入导航控制器的控制器中呈现UISearchController。将出现默认动画,其中搜索框从导航栏的顶部向下拉。

在我的情况下,这不是一个好的用户体验,因为当用户点击屏幕中间的UITextField时,我会提供搜索。我想做的是让UITextField浮动到顶部并变形到搜索框中,但我无法想象如何做到这一点。

这就是我所拥有的:

class PlacesSearchController: UISearchController, UISearchBarDelegate {

    convenience init(delegate: PlacesAutocompleteViewControllerDelegate) {

        let tableViewController = PlacesAutocompleteContainer(
            delegate: delegate
        )

        self.init(searchResultsController: tableViewController)

        self.searchResultsUpdater = tableViewController
        self.hidesNavigationBarDuringPresentation = false
        self.definesPresentationContext = true
        self.searchBar.placeholder = searchBarPlaceholder
    }
}

private extension ShowAddressViewController {

    @objc func streetAddressTextFieldEditingDidBegin() {
        present(placesSearchController, animated: true, completion: nil)
    }
}

我希望文本字段能够飞到导航栏,而不是从顶部开始搜索。我所追求的是与iOS 11 File应用程序相同的效果:

屏幕中间有一个文本字段,然后在点击它时动画到导航栏。但在我的情况下,文本字段在屏幕中较低,而不是导航栏的原始部分。

3 个答案:

答案 0 :(得分:14)

UISearchController

UISearchController是一个非常难以定制的组件。根据我的经验,我可以说,最好是按原样使用它而不需要任何激烈或重要的定制。否则,自定义可能会导致代码混乱,全局状态变量,UIView层次结构的运行时技巧等。 如果仍然需要特定的行为,最好从头开始实施搜索控制器或​​使用第三方搜索控制器。

默认实施

看起来UISearchController设计用于与表标题视图中安装的UITableView和UISearchBar配合使用。即使是苹果官方代码示例和文档也提供了这样的使用示例(请参阅UISearchController)。尝试在其他地方安装UISearchBar经常会导致搜索栏框架,位置,抽搐动画,方向更改等等各种丑陋的副作用。

从iOS 11开始,UINavigationItem获得searchController属性。它允许将搜索控制器集成到您的导航界面中,因此搜索看起来与iOS文件或iOS AppStore应用程序完全相同。 UISearchController的行为仍然与另一个组件耦合,但我相信它总是比与UITableView耦合更好。

可能的解决方案

从我的角度来看,有几种可能的解决方案可以解决您的问题。我将按照增加的努力提供它们,这是实施所需的:

  1. 如果您仍想使用UISearchController,请考虑按原样使用它,而无需进行重要的自定义。 Apple提供了示例代码,演示了如何使用UISearchController(请参阅Table Search with UISearchController)。
  2. 有几个第三方库可能更灵活,具有许多附加功能。例如:YNSearchPYSearch。请看看。
  3. 除了UISearchController演示文稿之外,您还可以尝试将UITextField从1更改为0来移动UITextField。这将产生UITextField顺利转换为UISearchBar的感觉。文章中描述的这种方法由Chris Slowik提供(请参阅对原始帖子的评论)。我唯一要改进的是使用转换协调器的动画(参见示例here),它将使同步时序的动画变得更加平滑。最终实施也将更加清洁。
  4. 作为一个选项,您可以尝试仅使用UISearchBar或简单的UITextField来设计自己的搜索控制器。
  5. 您可以继承UISearchController并添加UITextField对象。 UISearchController符合UIViewControllerAnimatedTransitioning和UIViewControllerTransitioningDelegate协议,其中UITextFiled可以与过渡动画一起删除或添加。
  6. 我希望这会有所帮助。

    更新:

    我已经实现了我在第3点描述的方法。以下是它的工作原理:

    UISearchController with UITextField

    您可以找到代码段here。请注意,这只是代码示例,可能存在未处理的情况。然后检查两次。

答案 1 :(得分:3)

  1. 在XIB中创建一个UIView。将其命名为searchView。
  2. 在同一个xib中的UIView上面添加UIButton,并将其命名为btnSearch。如下 in your scenario you have added textfield which is not mendetary

  3. 在ViewDidLoad中设置搜索控制器,如下所示:

    func setupSearchController()  {
      self.searchController = UISearchController(searchResultsController: nil)
      self.searchController.delegate = self
      self.searchController.searchBar.delegate = self
      definesPresentationContext = true
      self.searchController.dimsBackgroundDuringPresentation = false
      self.searchController.searchBar.sizeToFit()
      searchView.addSubview(self.searchController.searchBar)
      self.searchController.searchBar.isHidden = true
      self.searchController.searchBar.tintColor = UIColor.white
      self.searchController.searchBar.showsCancelButton = false
      UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = session?.makeColor(fromHexString: TYPE_COLOR, alpha: 1.0)
      self.searchController.searchBar.isTranslucent = false
      self.searchController.searchBar.barTintColor = UIColor(red: 239.0 / 255.0, green: 135.0 / 255.0, blue: 1.0 / 255.0, alpha: 1.0)
    }
    

    此方法将在searchview内以编程方式设置searchcontroller。

  4. 现在你只需要以编程方式显示searchcontroller。在步骤2中单击“按钮的方法”。在下面的方法名称中显示showsearchAnimation:

    func ShowSeachAnimation() {
      searchFrame = searchView.frame (add one global variable "searchFrame" in controller which saves searchView.frame so it will be used when cancel button clicked on search)
      self.btnSearch.isHidden = true        
      var yAxis : CGFloat = 20
      if #available(iOS 11 , *) {
         yAxis = 8
      } else  {
         yAxis = 20
      }
      searchView.translatesAutoresizingMaskIntoConstraints = true
      searchView.frame = CGRect(x: 0, y: yAxis, width: view.frame.size.width, height: view.frame.size.height - yAxis)
    
      self.searchController.searchBar.isHidden = false
      self.searchController.searchBar.becomeFirstResponder()
      self.searchController.searchBar.showsCancelButton = true
      self.searchBar(self.searchController.searchBar, textDidChange: "")
      searchView.layoutIfNeeded()
    }
    
  5. 对于隐藏搜索栏,在searchcontroller委托中添加名为“searchbarcancelbuttonclicked”的搜索隐藏方法:

    func searchViewHideAnimation()  {
      self.removeNavigationBar()
      self.navigationController?.isNavigationBarHidden = false
      self.searchController.searchBar.text = " "
      self.searchController.searchBar.isHidden = true
      UIView.animate(withDuration: 0.3, animations: {() -> Void in
          self.searchView.frame = self.searchFrame!
          self.btnSearch.isHidden = false
      }, completion: {(_ finished: Bool) -> Void in
          self.searchView.layoutIfNeeded()
      })
    }
    

答案 2 :(得分:2)

您可以尝试使用我的https://github.com/Blackjacx/SHSearchBar本质上是您的文字字段。您可以在左侧,右侧和顶部添加约束,并在文本字段编辑开始时调整顶部约束。同时,使用叠加视图隐藏导航栏动画并使背景变灰。通过这种方式,您可以最大限度地控制动画,这种方法并不像听起来那么困难。