Подтвердить что ты не робот

Пользовательская анимация UISearchController

Вопрос в нижней строке:

Как переопределить анимацию по умолчанию для увольнения searchBar, принадлежащего UISearchController?


Стандартное поведение контроллера поиска:

Хорошо, поэтому я пытаюсь создать настраиваемую анимацию, когда активируется UISearchBar, подключенный к UISearchController. Кажется, стандартная анимация ожидает, что searchBar начнется с ширины, которая занимает экран. Когда анимация начинается, она сжимает SearchBar и исчезает в кнопке отмены справа от нее.

Что я хочу достичь:

Я хочу, чтобы мой searchBar начинался в небольшом состоянии, примерно на половину ширины экрана, чтобы можно было разместить две кнопки на панели навигации рядом с ней.

Присутствующая анимация:

Когда функция searchBar становится активной, я хочу, чтобы анимация расширила область поиска и нажала кнопку отмены.

Отключение анимации:

Когда отклоняется запрос searchBar, я хочу, чтобы произошла полная противоположная анимация: кнопка Cancel отменилась, а searchBar уменьшился до первоначального размера.


Проблема:

Я нашел способ добиться желаемой анимации представления с помощью метода UISearchControllerDelegate, presentSearchController:

func presentSearchController(searchController: UISearchController) {

    // Animate Buttons
    UIView.animateWithDuration(0.1, animations: {

        // First Hide Buttons
        self.createMoxyButton.alpha = 0
        self.centerMapButton.alpha  = 0
    })

    // Animate Search Bar
    UIView.animateWithDuration(0.5, animations: {

        // Search Bar
        searchController.searchBar.frame = CGRectMake(searchController.searchBar.frame.origin.x, searchController.searchBar.frame.origin.y, self.wBounds - 40, searchController.searchBar.frame.height)
        self

    })

}

но я не смог добиться анимации увольнения. Я попытался использовать метод didDismissSearchController: и willDismissSearchController: делегировать, но это приводит к странному поведению и не использует анимацию кадров, которые я установил в этих соответствующих методах делегата. Когда searchBar будет уволен, он будет расширяться до полной ширины экрана, в то время как исчезает кнопка отмены, тогда она сразу же изменит кадр в SearchBar обратно на исходный размер, игнорируя мою анимацию. Я также попытался использовать метод removeAllAnimation(), чтобы попытаться остановить анимацию по умолчанию, но безрезультатно.

func didDismissSearchController(searchController: UISearchController) {
    searchController.searchBar.layer.removeAllAnimations()

    // Animate
    UIView.animateWithDuration(0.5, animations: {

        // Show hidden buttons
        self.createMoxyButton.alpha = 1
        self.centerMapButton.alpha  = 1

        // Search Bar
        searchController.searchBar.frame = CGRectMake(searchController.searchBar.frame.origin.x, searchController.searchBar.frame.origin.y, self.wBounds - 10 - self.createMoxyButton.frame.size.width - 20 - self.centerMapButton.frame.size.width - 20, searchController.searchBar.frame.height)
        self

    })
}

Изображение проблемы, убирающей SearchBar

Gif Анимация начинается с searchBar в активном состоянии с видимой кнопкой отмены

Gif Animation begins with the searchBar in the Active state with the cancel button visible

4b9b3361

Ответ 1

Подкласс UISearchController и реализовать необязательный UIViewControllerTransitioningDelegate метод - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;

чтобы вернуть объект анимации, чтобы сделать анимацию для увольнения.

Ответ 2

Я не могу утверждать, что это создает супер гладкую анимацию, но она не выглядит ужасной и может быть полезной (или даже точно, что вам нужно). Если вы хотите попробовать, вы можете создать новый проект (приложение с одним представлением) и просто добавить контроллер навигации в качестве исходного и объект класса ViewController в качестве его корневого контроллера (просто чтобы быстро получить панель навигации). Код ниже - это моя реализация ViewController

import UIKit

class ViewController: UIViewController,UISearchBarDelegate,UISearchControllerDelegate,UISearchResultsUpdating {

    lazy var createMoxyButton:UIBarButtonItem = {
        //customize this as your equire
        let button = UIBarButtonItem(title: "Done", style: .Plain, target: nil, action: nil)
        return button
    }()

    lazy var centerMapButton:UIBarButtonItem = {
        //customize this as your equire
        let button = UIBarButtonItem(title: "Done", style: .Plain, target: nil, action: nil)
        return button
        }()

    lazy var searchController:UISearchController = {
        let controller = UISearchController(searchResultsController: self)
        controller.delegate = self
        controller.searchResultsUpdater = self
        controller.dimsBackgroundDuringPresentation = false
        controller.hidesNavigationBarDuringPresentation = false
        return controller
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.navigationItem.titleView = self.searchController.searchBar
        self.navigationItem.rightBarButtonItems = [self.centerMapButton,self.createMoxyButton]
        self.edgesForExtendedLayout = UIRectEdge.None
        self.searchController.searchBar.delegate = self
    }

    func updateSearchResultsForSearchController(searchController: UISearchController) {

    }

    func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
        //this needs to be done because in shouldEndEditing
        //we need to set it to false to smooth animation
        searchBar.showsCancelButton = true
        self.navigationItem.setRightBarButtonItems(nil, animated: true)
    }

    func searchBarShouldEndEditing(searchBar: UISearchBar) -> Bool {
        searchBar.showsCancelButton = false
        self.navigationItem.rightBarButtonItems = [self.centerMapButton,self.createMoxyButton]
        return true
    }
}