http://jduff.github.com/2010/03/01/building-a-searchview-with-uisearchbar-and-uitableview/

 

Fading out the UITableView

If you take another look at the Flixster App or even the initial screenshot I have in this post you will notice that when you are in ‘search mode’ the background of the screen is faded black. This effect helps to show the user that the UITableView is in fact disabled.

To get this behaviour I add and remove another UIView and adjust the opacity in an Animation so that in fades in smoothly. The first thing we need to do is create an instance variable and property for thisdisableViewOverlay as I called it and initialize it when the view loads.

#import "SearchViewController.h"

@implementation SearchViewController
@synthesize disableViewOverlay;
// Additional variable synthesizes

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableData =[[NSMutableArray alloc]init];
    self.disableViewOverlay = [[UIView alloc]
     initWithFrame:CGRectMake(0.0f,44.0f,320.0f,416.0f)];
    self.disableViewOverlay.backgroundColor=[UIColor blackColor];
    self.disableViewOverlay.alpha = 0;
}

I’ll leave it to you to figure out what to put in SearchViewController.m. Now that we have this UIView all set up all we have to do is fade it in when the UISearchBar gets focus. This was actually really easy to do, I just needed to add the disableViewOverlay as a subview and then usebeginAnimations/commitAnimations for the fading.

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    // Existing code
    
    // Fading in the disableViewOverlay
    self.disableViewOverlay.alpha = 0;
    [self.view addSubview:self.disableViewOverlay];
	
    [UIView beginAnimations:@"FadeIn" context:nil];
    [UIView setAnimationDuration:0.5];
    self.disableViewOverlay.alpha = 0.6;
    [UIView commitAnimations];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    // Existing code
    
    // Removing the disableViewOverlay
    [disableViewOverlay removeFromSuperview];
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // Existing code
    
    // Removing the disableViewOverlay
    [disableViewOverlay removeFromSuperview];
}

At the end of searchBarTextDidBeginEditing we added the code to fade in the disableViewOverlay, then at the end of searchBarCancelButtonClicked and searchBarSearchButtonClicked we remove the disableViewOverlay.

If you’ve been following along you might notice a bit of a code smell coming from these last three methods. There’s a lot of code duplication which I don’t really like so I actually re-factored these three methods and created another method that all of them can call. The resulting re-factored code looks like this:

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    [self searchBar:searchBar activate:YES];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    searchBar.text=@"";
    [self searchBar:searchBar activate:NO];
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // SomeService is just a dummy class representing some 
    // api that you are using to do the search
    NSArray *results = [SomeService doSearch:searchBar.text];
	
    [self searchBar:searchBar activate:NO];
	
    [self.tableData removeAllObjects];
    [self.tableData addObjectsFromArray:results];
    [self.theTableView reloadData];
}

- (void)searchBar:(UISearchBar *)searchBar activate:(BOOL) active{	
    self.theTableView.allowsSelection = !active;
    self.theTableView.scrollEnabled = !active;
    if (!active) {
        [disableViewOverlay removeFromSuperview];
        [searchBar resignFirstResponder];
    } else {
        self.disableViewOverlay.alpha = 0;
        [self.view addSubview:self.disableViewOverlay];
		
        [UIView beginAnimations:@"FadeIn" context:nil];
        [UIView setAnimationDuration:0.5];
        self.disableViewOverlay.alpha = 0.6;
        [UIView commitAnimations];
		
        // probably not needed if you have a details view since you 
        // will go there on selection
        NSIndexPath *selected = [self.theTableView 
            indexPathForSelectedRow];
        if (selected) {
            [self.theTableView deselectRowAtIndexPath:selected 
                animated:NO];
        }
    }
    [searchBar setShowsCancelButton:active animated:YES];
}

That cleans things up nicely. Now when you run the app you should have the main view fade out smoothly when you enter the UISearchBar just like mine below:

Search View Faded with Results

 

//完整代码如下

 

 

SearchViewController.h

//
//  SearchViewController.h
//
#import <UIKit/UIKit.h>

@interface SearchViewController : UIViewController
 <UISearchBarDelegate, UITableViewDataSource> {
	NSMutableArray *tableData;
	
	UIView *disableViewOverlay;
	
	UITableView *theTableView;
	UISearchBar *theSearchBar;
}

@property(retain) NSMutableArray *tableData;
@property(retain) UIView *disableViewOverlay;

@property (nonatomic, retain) IBOutlet UITableView *theTableView;
@property (nonatomic, retain) IBOutlet UISearchBar *theSearchBar;

- (void)searchBar:(UISearchBar *)searchBar activate:(BOOL) active;

@end

SearchViewController.m

//
//  SearchViewController.m
//
#import "SearchViewController.h"

@implementation SearchViewController
@synthesize tableData;
@synthesize disableViewOverlay;
@synthesize theSearchBar;
@synthesize theTableView;


// Initialize tableData and disabledViewOverlay 
- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableData =[[NSMutableArray alloc]init];
    self.disableViewOverlay = [[UIView alloc]
     initWithFrame:CGRectMake(0.0f,44.0f,320.0f,416.0f)];
    self.disableViewOverlay.backgroundColor=[UIColor blackColor];
    self.disableViewOverlay.alpha = 0;
}

// Since this view is only for searching give the UISearchBar 
// focus right away
- (void)viewDidAppear:(BOOL)animated {
    [self.theSearchBar becomeFirstResponder];
    [super viewDidAppear:animated];
}

#pragma mark -
#pragma mark UISearchBarDelegate Methods

- (void)searchBar:(UISearchBar *)searchBar
    textDidChange:(NSString *)searchText {
  // We don't want to do anything until the user clicks 
  // the 'Search' button.
  // If you wanted to display results as the user types 
  // you would do that here.
}

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    // searchBarTextDidBeginEditing is called whenever 
    // focus is given to the UISearchBar
    // call our activate method so that we can do some 
    // additional things when the UISearchBar shows.
    [self searchBar:searchBar activate:YES];
}

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    // searchBarTextDidEndEditing is fired whenever the 
    // UISearchBar loses focus
    // We don't need to do anything here.
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    // Clear the search text
    // Deactivate the UISearchBar
    searchBar.text=@"";
    [self searchBar:searchBar activate:NO];
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // Do the search and show the results in tableview
    // Deactivate the UISearchBar
	
    // You'll probably want to do this on another thread
    // SomeService is just a dummy class representing some 
    // api that you are using to do the search
    NSArray *results = [SomeService doSearch:searchBar.text];
	
    [self searchBar:searchBar activate:NO];
	
    [self.tableData removeAllObjects];
    [self.tableData addObjectsFromArray:results];
    [self.theTableView reloadData];
}

// We call this when we want to activate/deactivate the UISearchBar
// Depending on active (YES/NO) we disable/enable selection and 
// scrolling on the UITableView
// Show/Hide the UISearchBar Cancel button
// Fade the screen In/Out with the disableViewOverlay and 
// simple Animations
- (void)searchBar:(UISearchBar *)searchBar activate:(BOOL) active{	
    self.theTableView.allowsSelection = !active;
    self.theTableView.scrollEnabled = !active;
    if (!active) {
        [disableViewOverlay removeFromSuperview];
        [searchBar resignFirstResponder];
    } else {
        self.disableViewOverlay.alpha = 0;
        [self.view addSubview:self.disableViewOverlay];
		
        [UIView beginAnimations:@"FadeIn" context:nil];
        [UIView setAnimationDuration:0.5];
        self.disableViewOverlay.alpha = 0.6;
        [UIView commitAnimations];
		
        // probably not needed if you have a details view since you 
        // will go there on selection
        NSIndexPath *selected = [self.theTableView 
            indexPathForSelectedRow];
        if (selected) {
            [self.theTableView deselectRowAtIndexPath:selected 
                animated:NO];
        }
    }
    [searchBar setShowsCancelButton:active animated:YES];
}


#pragma mark -
#pragma mark UITableViewDataSource Methods

- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section {
    return [tableData count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *MyIdentifier = @"SearchResult";
    UITableViewCell *cell = [tableView
     dequeueReusableCellWithIdentifier:MyIdentifier];
	
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] 
         initWithStyle:UITableViewCellStyleDefault 
         reuseIdentifier:MyIdentifier] autorelease];
    }
	
    id *data = [self.tableData objectAtIndex:indexPath.row];
    cell.textLabel.text = data.name;
    return cell;
}

#pragma mark -
#pragma mark Memory Management Methods

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];	
    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
    [theTableView release], theTableView = nil;
    [theSearchBar release], theSearchBar = nil;
    [tableData dealloc];
    [disableViewOverlay dealloc];
    [super dealloc];
}

@end

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐