Merge pull request #41 from vector-im/search_background_image

Empty search background image
This commit is contained in:
manuroe 2016-01-05 18:20:01 +01:00
commit 2a8021aa38
9 changed files with 186 additions and 32 deletions

View file

@ -20,7 +20,7 @@
The `VectorSearch` category adds the management of the search bar in Vector screens.
*/
@interface MXKViewController (VectorSearch) <UISearchBarDelegate>
@interface UIViewController (VectorSearch) <UISearchBarDelegate>
/**
The search bar.
@ -32,6 +32,13 @@
*/
@property (nonatomic, readonly) BOOL searchBarHidden;
/**
The Vector empty search background image (champagne bubbles).
The image adapts its width to its parent view width.
Its bottom is aligned to the top of the keyboard.
*/
@property (nonatomic, readonly) UIImageView *backgroundImageView;
/**
Show/Hide the search bar.
@ -40,4 +47,18 @@
- (void)showSearch:(BOOL)animated;
- (void)hideSearch:(BOOL)animated;
/**
Initialise `backgroundImageView` and add it to the passed parent view.
@param view the view to add `backgroundImageView` to.
*/
- (void)addBackgroundImageViewToView:(UIView*)view;
/**
Provide the new height of the keyboard to align `backgroundImageView`
@param keyboardHeight the keyboard height.
*/
- (void)setKeyboardHeightForBackgroundImage:(CGFloat)keyboardHeight;
@end

View file

@ -19,11 +19,11 @@
#import <objc/runtime.h>
/**
`UIViewController_VectorSearch` is the internal single point storage for the search feature.
`UIViewControllerVectorSearchInternals` is the internal single point storage for the search feature.
It hosts all required data so that only one associated object can be used in the category.
*/
@interface UIViewController_VectorSearch : NSObject
@interface UIViewControllerVectorSearchInternals : NSObject
// The search bar
@property (nonatomic) UISearchBar *searchBar;
@ -34,9 +34,13 @@
@property (nonatomic) UIBarButtonItem *backupLeftBarButtonItem;
@property (nonatomic) UIBarButtonItem *backupRightBarButtonItem;
// The Vector empty search background image (champagne bubbles)
@property (nonatomic) UIImageView *backgroundImageView;
@property (nonatomic) NSLayoutConstraint *backgroundImageViewBottomConstraint;
@end
@implementation UIViewController_VectorSearch
@implementation UIViewControllerVectorSearchInternals
@end
@ -46,7 +50,7 @@
@interface UIViewController ()
// The single associated object hosting all data.
@property(nonatomic) UIViewController_VectorSearch *searchInternals;
@property(nonatomic) UIViewControllerVectorSearchInternals *searchInternals;
@end
@ -62,6 +66,11 @@
return self.searchInternals.searchBarHidden;
}
- (UIImageView*)backgroundImageView
{
return self.searchInternals.backgroundImageView;
}
- (void)showSearch:(BOOL)animated
{
// Backup screen header before displaying the search bar in it
@ -97,6 +106,79 @@
self.searchInternals.searchBarHidden = YES;
}
- (void)addBackgroundImageViewToView:(UIView*)view
{
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"search_bg"]];
backgroundImageView.translatesAutoresizingMaskIntoConstraints = NO;
[view addSubview:backgroundImageView];
// Keep it at left
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:backgroundImageView
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0];
// Same width as parent
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:backgroundImageView
attribute:NSLayoutAttributeWidth
multiplier:1.0f
constant:0.0f];
// Keep the image aspect ratio
NSLayoutConstraint *aspectRatioConstraint = [NSLayoutConstraint
constraintWithItem:backgroundImageView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:backgroundImageView
attribute:NSLayoutAttributeWidth
multiplier:(backgroundImageView.frame.size.height / backgroundImageView.frame.size.width)
constant:0];
// Set its position according to its bottom
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:backgroundImageView
attribute:NSLayoutAttributeBottom
multiplier:1.0f
constant:216];
[NSLayoutConstraint activateConstraints:@[leftConstraint,
widthConstraint,
aspectRatioConstraint,
bottomConstraint
]];
self.searchInternals.backgroundImageView = backgroundImageView;
self.searchInternals.backgroundImageViewBottomConstraint = bottomConstraint;
// It will be showed once the keyboard appears
backgroundImageView.hidden = YES;
}
- (void)setKeyboardHeightForBackgroundImage:(CGFloat)keyboardHeight
{
// keyboardHeight = 0 means no keyboard
if (keyboardHeight > 0)
{
self.searchInternals.backgroundImageView.hidden = NO;
// 60 = 18 + 42 from the Vector design
self.searchInternals.backgroundImageViewBottomConstraint.constant = keyboardHeight - 60;
}
else
{
// Hide the search
self.searchInternals.backgroundImageView.hidden = YES;
}
}
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar2
@ -130,18 +212,18 @@
#pragma mark - Internal associated object
- (void)setSearchInternals:(UIViewController_VectorSearch *)searchInternals
- (void)setSearchInternals:(UIViewControllerVectorSearchInternals *)searchInternals
{
objc_setAssociatedObject(self, @selector(searchInternals), searchInternals, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIViewController_VectorSearch *)searchInternals
- (UIViewControllerVectorSearchInternals *)searchInternals
{
UIViewController_VectorSearch *searchInternals = objc_getAssociatedObject(self, @selector(searchInternals));
UIViewControllerVectorSearchInternals *searchInternals = objc_getAssociatedObject(self, @selector(searchInternals));
if (!searchInternals)
{
// Initialise internal data at the first call
searchInternals = [[UIViewController_VectorSearch alloc] init];
searchInternals = [[UIViewControllerVectorSearchInternals alloc] init];
UISearchBar *searchBar = [[UISearchBar alloc] init];
searchBar.showsCancelButton = YES;

View file

@ -36,6 +36,9 @@
self.title = NSLocalizedStringFromTable(@"directory_title", @"Vector", nil);
self.tableView.delegate = self;
// Hide line separators of empty cells
self.tableView.tableFooterView = [[UIView alloc] init];
}

View file

@ -30,6 +30,9 @@
[self.searchTableView registerNib:HomeSearchTableViewCell.nib forCellReuseIdentifier:HomeSearchTableViewCell.defaultReuseIdentifier];
self.searchTableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
// Hide line separators of empty cells
self.searchTableView.tableFooterView = [[UIView alloc] init];
}
- (void)displaySearch:(MXKSearchDataSource *)searchDataSource

View file

@ -68,8 +68,9 @@
[super viewDidLoad];
self.navigationItem.title = NSLocalizedStringFromTable(@"recents", @"Vector", nil);
self.backgroundImageView.image = [UIImage imageNamed:@"search_bg"];
// Add the Vector background image when search bar is empty
[self addBackgroundImageViewToView:self.view];
}
- (void)dealloc
@ -311,6 +312,43 @@
[self performSegueWithIdentifier:@"showDirectory" sender:self];
}
#pragma mark - Override MXKViewController
- (void)setKeyboardHeight:(CGFloat)keyboardHeight
{
[self setKeyboardHeightForBackgroundImage:keyboardHeight];
[super setKeyboardHeight:keyboardHeight];
}
#pragma mark - Override UIViewController+VectorSearch
- (void)setKeyboardHeightForBackgroundImage:(CGFloat)keyboardHeight
{
[super setKeyboardHeightForBackgroundImage:keyboardHeight];
if (keyboardHeight > 0)
{
[self checkAndShowBackgroundImage];
}
}
// Check if there is enough room for displaying the background
// before displaying it
- (void)checkAndShowBackgroundImage
{
// In landscape with the iPhone 5 & 6 screen size, the backgroundImageView overlaps the tabs header,
// So, hide backgroundImageView
if (self.backgroundImageView.superview.frame.size.height > 375)
{
self.backgroundImageView.hidden = NO;
}
else
{
self.backgroundImageView.hidden = YES;
}
}
#pragma mark - Override SegmentedViewController
- (void)setSelectedIndex:(NSUInteger)selectedIndex
@ -423,6 +461,7 @@
createNewRoomImageView.hidden = NO;
tableViewMaskLayer.hidden = NO;
self.backgroundImageView.hidden = YES;
[recentsDataSource searchWithPatterns:nil];
@ -440,6 +479,7 @@
if (self.searchBar.text.length)
{
self.selectedViewController.view.hidden = NO;
self.backgroundImageView.hidden = YES;
// Forward the search request to the data source
if (self.selectedViewController == recentsViewController)
@ -468,6 +508,7 @@
{
// Nothing to search = Show nothing
self.selectedViewController.view.hidden = YES;
[self checkAndShowBackgroundImage];
}
}

View file

@ -75,6 +75,9 @@
[self.recentsTableView addGestureRecognizer:longPress];
self.recentsTableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
// Hide line separators of empty cells
self.recentsTableView.tableFooterView = [[UIView alloc] init];
}
- (void)destroy

View file

@ -29,9 +29,15 @@
{
[super viewDidLoad];
// Hide line separators of empty cells
self.searchTableView.tableFooterView = [[UIView alloc] init];
// Reuse cells from the RoomViewController to display results
[self.searchTableView registerClass:RoomIncomingTextMsgBubbleCell.class forCellReuseIdentifier:RoomIncomingTextMsgBubbleCell.defaultReuseIdentifier];
[self.searchTableView registerClass:RoomIncomingAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentBubbleCell.defaultReuseIdentifier];
// Add the Vector background image when search bar is empty
[self addBackgroundImageViewToView:self.view];
}
- (void)viewWillAppear:(BOOL)animated
@ -42,14 +48,25 @@
[self showSearch:animated];
}
#pragma mark - Override MXKViewController
- (void)setKeyboardHeight:(CGFloat)keyboardHeight
{
[self setKeyboardHeightForBackgroundImage:keyboardHeight];
[super setKeyboardHeight:keyboardHeight];
}
#pragma mark - Override UIViewController+VectorSearch
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar2
{
[super searchBarSearchButtonClicked:searchBar2];
// Make the search
[self.dataSource searchMessageText:searchBar2.text];
if (searchBar2.text.length)
{
self.backgroundImageView.hidden = YES;
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar2
@ -96,6 +113,7 @@
return nil;
}
#pragma mark - Override UITableView delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

View file

@ -30,7 +30,6 @@ limitations under the License.
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *selectionContainerTopConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *selectionContainerHeightConstraint;
@property (weak, nonatomic) IBOutlet UIView *viewControllerContainer;
@property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView;
/**
The index of the view controller that currently has the focus.

View file

@ -1,13 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9531"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SegmentedViewController">
<connections>
<outlet property="backgroundImageView" destination="KfM-OD-fTP" id="AXh-ac-GWQ"/>
<outlet property="selectionContainer" destination="ynH-uD-aQj" id="taa-CW-XgW"/>
<outlet property="selectionContainerHeightConstraint" destination="fZ1-SQ-nxS" id="kQ4-n9-Gmt"/>
<outlet property="selectionContainerTopConstraint" destination="eLe-5q-IfV" id="UhZ-9k-P1r"/>
@ -22,30 +21,15 @@
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ynH-uD-aQj" userLabel="Selection Container">
<rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
<animations/>
<constraints>
<constraint firstAttribute="height" constant="44" id="fZ1-SQ-nxS"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Hbe-uP-aJY" userLabel="Selected UITableView Container">
<rect key="frame" x="0.0" y="44" width="600" height="556"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="KfM-OD-fTP">
<rect key="frame" x="0.0" y="0.0" width="600" height="556"/>
<animations/>
</imageView>
</subviews>
<animations/>
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="KfM-OD-fTP" firstAttribute="height" secondItem="Hbe-uP-aJY" secondAttribute="height" id="GBi-kq-bMR"/>
<constraint firstItem="KfM-OD-fTP" firstAttribute="leading" secondItem="Hbe-uP-aJY" secondAttribute="leading" id="cmW-5l-b7z"/>
<constraint firstItem="KfM-OD-fTP" firstAttribute="width" secondItem="Hbe-uP-aJY" secondAttribute="width" id="hVX-eX-wxE"/>
<constraint firstItem="KfM-OD-fTP" firstAttribute="top" secondItem="Hbe-uP-aJY" secondAttribute="top" id="snt-Kj-GGz"/>
</constraints>
</view>
</subviews>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="Hbe-uP-aJY" secondAttribute="bottom" id="GHr-ci-L7A"/>