使用 UISearchController 同时动画 UISearchBar 和 UIBarButtonItem [英] Animate UISearchBar and UIBarButtonItem simultaneously with UISearchController

查看:19
本文介绍了使用 UISearchController 同时动画 UISearchBar 和 UIBarButtonItem的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试重现一个类似于地图应用程序的搜索界面.

I'm trying to reproduce a search interface similar to the one of the Maps app.

我在我的 navigationBar 中使用了 UISearchController 和它的 searchBar.我在那个导航栏上也有一个 rightBarButtonItem.

I'm using a UISearchController with its searchBar inside my navigationBar. I also have a rightBarButtonItem on that navigation bar.

默认情况下,当呈现搜索控制器时,搜索栏的取消按钮显示在现有右侧项目的旁边.我想要做的——就像使用地图应用一样——是在 searchController 出现时隐藏我的正确导航项,并在它被关闭时再次显示.

By default, when presenting the search controller, the cancel button of the search bar shows next to the existing right item. What I want to do — like with the Maps app — is to hide my right navigation item while the searchController is presented and show it again when it's dismissed.

我已经设法使用委托方法来做到这一点,但是动画中有一个非常难看的跳跃,我想知道如何避免这种情况.

I have managed to do it using the delegates methods, but there is a jump in the animation which is very ugly and I would like to know how to avoid that.

这是我的代码(正确的栏项将切换慢速动画,使错误更容易看到)

Here is my code (the right bar item will toggle slow animations which makes the bug easier to see)

AppDelegate.h

//
//  AppDelegate.h
//  SearchNavigationItemAnimation
//

#import <UIKit/UIKit.h>


@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

AppDelegate.m

//
//  AppDelegate.m
//  SearchNavigationItemAnimation
//

#import "AppDelegate.h"
#import "SearchViewController.h"

@interface AppDelegate ()
@end


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

    SearchViewController *rootController = [[SearchViewController alloc] init];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootController];
    self.window.rootViewController = navigationController;

    [self.window makeKeyAndVisible];

    return YES;
}

@end

SearchViewController.h

//
//  SearchViewController.h
//  SearchNavigationItemAnimation
//

#import <UIKit/UIKit.h>


@interface SearchViewController : UIViewController

@end

SearchViewController.m

//
//  SearchViewController.m
//  SearchNavigationItemAnimation
//

#import "SearchViewController.h"

@interface SearchViewController () <UISearchControllerDelegate, UISearchResultsUpdating>
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic, strong) UIBarButtonItem *rightBarButtonItem;
@end

@implementation SearchViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor lightGrayColor];
    self.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(navigationBarButtonItemAction)];

    UITableViewController *searchResultsController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
    self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
    self.searchController.delegate = self;
    self.searchController.searchResultsUpdater = self;
    self.searchController.hidesNavigationBarDuringPresentation = NO;

    self.navigationItem.titleView = self.searchController.searchBar;
    self.navigationItem.rightBarButtonItem = self.rightBarButtonItem;

    self.definesPresentationContext = YES;
}

- (void)willPresentSearchController:(UISearchController *)searchController
{
    [self.navigationItem setRightBarButtonItem:nil animated:true];
}

- (void)willDismissSearchController:(UISearchController *)searchController
{
    [self.navigationItem setRightBarButtonItem:self.rightBarButtonItem animated:true];
}

- (void)navigationBarButtonItemAction {
    float windowLayerSpeed = [UIApplication sharedApplication].keyWindow.layer.speed;
    [UIApplication sharedApplication].keyWindow.layer.speed = (windowLayerSpeed == 1.0) ? 0.1 : 1.0;
}

- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
}

@end

编辑

让我稍微解释一下发生了什么.

Let me explain a little bit more what is going on.

在没有添加 barButtonItem 的情况下,searchBar 占据了导航栏的整个宽度.当您触摸它时,它会激活并显示带有漂亮动画的取消按钮(搜索字段缩小,为从右侧滑入的取消按钮留出空间).

With no added barButtonItem, the searchBar takes the entire width of the navigation bar. When you touch it, it activates and shows the cancel button with a nice animation (the search field shrinks leaving room for the cancel button which slides in from the right).

使用导航栏上的右键,如果您不尝试以任何方式添加/删除/修改它,它的工作方式相同.搜索栏占据除按钮宽度外的所有空间,当它激活时,取消按钮从按钮的右侧和下方滑入并位于其旁边(在搜索字段和现有的右侧按钮之间).一切都经过动画处理并且工作正常.

With a right button on the navigation bar, if you don't try to add it/remove it/modify it in any way, it works the same way. The search bar takes all the space except for the width of the button and when it actives the cancel button slides in from the right and from below the button and lands next to it (between the search field and the existing right button). Everything is animated and works fine.

现在,如果您想在取消按钮滑入时使右键消失,则必须为其框架设置动画.问题是搜索栏会自动尝试占用所有可用空间,并且不会对其框架进行动画处理.因此,假设您想将按钮的帧宽度设置为零,搜索栏将立即扩展其宽度,而不是跟随您的动画.

Now if you want to make the right button disappear when the cancel button slides in you have to animate it's frame. The problem is that the search bar automatically try to take all the available space, and does that without animating it's frame. So lets' say you want to animate your button's frame width to zero, the search bar will expand its width instantly instead of following your animation.

这显然是一个错误,或者如果您更宽容尚未实现的功能...但它在 iOS7 中使用 UISearchDisplayController 运行良好,并且苹果在地图应用程序中做到了.所以我要求任何可行的解决方法,包括必要时的私有 API 调用.

It's clearly a bug, or if you're more forgiving a feature that hasn't been implemented... But it worked fine in iOS7 with UISearchDisplayController, and Apple does it in the Maps app. So I'm asking for any workaround that will work, including private API call if necessary.

推荐答案

如果有人感兴趣,我设法使用 UISearchDisplayController 使其工作.请参阅此示例项目.

In case anyone is interested, I managed to make it work using UISearchDisplayController. See this sample project.

我仍然对与 UISearchController 一起使用的解决方案感兴趣.

I'm still interested by a solution that works with UISearchController though.

这篇关于使用 UISearchController 同时动画 UISearchBar 和 UIBarButtonItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆