mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-30 00:02:47 +00:00
Merge pull request #41 from vector-im/search_background_image
Empty search background image
This commit is contained in:
commit
2a8021aa38
9 changed files with 186 additions and 32 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"/>
|
||||
|
|
Loading…
Reference in a new issue