问题
Given 3 Controllers: A,B,C A has a hidden navigationbar. Calls Controller B via a StoryboardReference. Controller B shows Navigationbar on viewDidLoad. It has a searchbar and a collectionView. See screenshot A of my storyboard. Calls controller C if a cell is clicked.
Problem: If A calls B the searchbar is behind the navigationbar (Screenshot B). It appears with the transition from C to B (Screenshot C).
Navigationbar is already translucent. Any ideas?
EDIT
I realized that my animated transitioning is causing my problem.
Perhaps you can spot the error?
class ZoomInCircleViewTransition: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
var transitionContext: UIViewControllerContextTransitioning?
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.6
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext
guard let toViewController: UIViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
return
}
guard let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) else { return
}
guard let fromViewTransitionFromView = fromViewController as? TransitionFromViewProtocol else {
return
}
let imageViewSnapshot = fromViewTransitionFromView.getViewForTransition()
let endFrame = CGRectMake(-CGRectGetWidth(toViewController.view.frame)/2, -CGRectGetHeight(toViewController.view.frame)/2, CGRectGetWidth(toViewController.view.frame)*2, CGRectGetHeight(toViewController.view.frame)*2)
if let containerView = transitionContext.containerView(){
containerView.addSubview(fromViewController.view)
containerView.addSubview(toViewController.view)
containerView.addSubview(imageViewSnapshot)
}
let maskPath = UIBezierPath(ovalInRect: imageViewSnapshot.frame)
let maskLayer = CAShapeLayer()
maskLayer.frame = toViewController.view.frame
maskLayer.path = maskPath.CGPath
toViewController.view.layer.mask = maskLayer
let quadraticEndFrame = CGRect(x: endFrame.origin.x - (endFrame.height - endFrame.width)/2, y: endFrame.origin.y, width: endFrame.height, height: endFrame.height)
let bigCirclePath = UIBezierPath(ovalInRect: quadraticEndFrame)
let pathAnimation = CABasicAnimation(keyPath: "path")
pathAnimation.delegate = self
pathAnimation.fromValue = maskPath.CGPath
pathAnimation.toValue = bigCirclePath
pathAnimation.duration = transitionDuration(transitionContext)
maskLayer.path = bigCirclePath.CGPath
maskLayer.addAnimation(pathAnimation, forKey: "pathAnimation")
let hideImageViewAnimation = {
imageViewSnapshot.alpha = 0.0
}
UIView.animateWithDuration(0.2, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: hideImageViewAnimation) { (completed) -> Void in
}
let scaleImageViewAnimation = {
imageViewSnapshot.frame = quadraticEndFrame
}
UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: scaleImageViewAnimation) { (completed) -> Void in
// After the complete animations have endet
imageViewSnapshot.removeFromSuperview()
toViewController.view.layer.mask = nil
}
}
override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
if let transitionContext = self.transitionContext {
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
}
// MARK: UIViewControllerTransitioningDelegate protocol methods
// return the animataor when presenting a viewcontroller
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
// return the animator used when dismissing from a viewcontroller
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
}
回答1:
I believe I was running in to some similar problems in my app, but running in to difficulties because of all the things you don't have control over. My solution was to put a search icon in the navigationbar, then have the search controller slide down over the navigationbar, keeping it out of the table/scroll view. Here is my implementation (should be complete)
import UIKit
class tvc: UITableViewController, UISearchBarDelegate, UISearchControllerDelegate {
var searchController:UISearchController!
@IBAction func startSearch() {
self.navigationController?.presentViewController(self.searchController, animated: true, completion: {})
}
override func viewDidDisappear(animated: Bool) {
cancelSearch(self)
}
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.delegate = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.loadViewIfNeeded() /* Fixes bug in iOS http://stackoverflow.com/questions/32675001/uisearchcontroller-warning-attempting-to-load-the-view-of-a-view-controller */
definesPresentationContext = true
tableView.sectionIndexBackgroundColor = UIColor.clearColor()
tableView.sectionIndexTrackingBackgroundColor = UIColor.clearColor()
}
extension tvc: UISearchResultsUpdating {
// MARK: - UISearchResultsUpdating Delegate
func updateSearchResultsForSearchController(searchController: UISearchController) {
filterContentForSearchText(searchController.searchBar.text!)
}
}
func cancelSearch(sender: AnyObject?) {
if sender!.searchController.active == true {
sender?.searchController.resignFirstResponder()
sender!.navigationController!!.dismissViewControllerAnimated(false, completion: {})
sender!.searchController.searchBar.text = ""
sender!.searchController.active = false
}
}
回答2:
I think problem is your are either you are not setting frame for imageViewSnapshot or setting wrong frame. As imageViewSnapshot includes the search bar, your have to set the frame such are it goes behind the navigation bar. or imageViewSnapshot should contain only visible area of the fromViewTransitionFromView.
来源:https://stackoverflow.com/questions/35826739/searchbar-behind-navigationbar