Last active
June 15, 2019 10:09
-
-
Save Apanlin/8273830117091849fe3b21459060f560 to your computer and use it in GitHub Desktop.
自定义搜索框
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PPQSearchBar.h | |
// | |
// | |
// Created by LinPan on 2018/6/29. | |
// | |
// | |
#import <UIKit/UIKit.h> | |
@class QYPDSearchBar; | |
@protocol QYPDSearchBarDelegate <NSObject> | |
@optional | |
- (void)searchBarTextDidBeginEditing:(QYPDSearchBar *)searchBar; | |
- (void)searchBarTextDidEndEditing:(QYPDSearchBar *)searchBar; | |
- (void)searchBar:(QYPDSearchBar *)searchBar textDidChange:(NSString *)searchText; | |
- (BOOL)searchBarShouldReturn:(UITextField *)textField; | |
- (void)searchBarClearText; | |
@end | |
@interface QYPDSearchBar : UIView | |
@property (nonatomic, strong) NSString *placeholder; | |
@property (nonatomic, weak) id<QYPDSearchBarDelegate> delegate; | |
@property (nonatomic, strong) NSString *text; | |
@property (nonatomic, assign) BOOL isEditing; | |
@property (nonatomic, copy) void(^cancelClicked)(void); | |
/**可用状态 和 不可用状态 间切换,设计取消按钮等icon位置的变换*/ | |
- (void)enterTouchableMode:(BOOL)animation; | |
- (void)exitTouchableMode; | |
/**光标选择状态 和 不选中状态的切换*/ | |
- (void)startEditStatus; | |
- (void)exitEditStatus; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PPQSearchBar.m | |
// | |
// | |
// Created by LinPan on 2018/6/29. | |
// | |
// | |
#import "QYPDSearchBar.h" | |
#import "QYPDSearchTextField.h" | |
#import "QYPDCollectionCutterConstant.h" | |
//UIKIT_EXTERN NSString *SEARCH_CANCEL_NOTIFICATION_KEY; | |
NSString *SEARCH_CANCEL_NOTIFICATION_KEY = @"SEARCH_CANCEL_NOTIFICATION_KEY"; | |
#define kLeftMargin (10) | |
#define kTopMargin ((kSearchBarHeight - kSearchTFHeight)/2.0) | |
#define kSearchBarHeight (44) | |
#define kSearchTFHeight (30) | |
#define kSearchTFWidthNomal (ScreenWidth - kLeftMargin*2 - 8/*TF和搜索背景框左边有8像素距离*/) | |
#define kSearchTFWidthEditing (ScreenWidth - kLeftMargin - 8 - kSearchTFRightMarginWhenEditing-32/*右边的删除按钮宽度32*/+10/*右边多10个像素视觉好点*/) | |
#define kSearchTFRightMarginWhenEditing (72) | |
@interface QYPDSearchBar ()<UITextFieldDelegate> | |
{ | |
BOOL _showWithAnimation; | |
} | |
@property (nonatomic, strong) UIView *backgroundImageView; | |
@property (nonatomic, strong) QYPDSearchTextField *searchTextField; | |
@property (nonatomic, strong) UIButton *rightButton; | |
@property (nonatomic, strong) UIButton *cancelButton; | |
@end | |
@implementation QYPDSearchBar | |
- (instancetype)initWithFrame:(CGRect)frame { | |
frame = CGRectMake(0, 0, ScreenWidth, kSearchBarHeight); | |
self = [super initWithFrame:frame]; | |
self.backgroundColor = [UIColor clearColor]; | |
[self addSubview:self.backgroundImageView]; | |
[self addSubview:self.searchTextField]; | |
[self addSubview:self.rightButton]; | |
[self addSubview:self.cancelButton]; | |
return self; | |
} | |
- (void)enterTouchableMode:(BOOL)animation | |
{ | |
_showWithAnimation = animation; | |
self.isEditing = YES; | |
} | |
- (void)exitTouchableMode | |
{ | |
self.isEditing = NO; | |
} | |
- (void)startEditStatus | |
{ | |
[self.searchTextField becomeFirstResponder]; | |
} | |
- (void)exitEditStatus | |
{ | |
[self.searchTextField resignFirstResponder]; | |
} | |
- (void)setIsEditing:(BOOL)isEditing { | |
_isEditing = isEditing; | |
if (_isEditing) { | |
[UIView animateWithDuration:(_showWithAnimation ? 0.2 : 0) animations:^{ | |
self.backgroundImageView.width = ScreenWidth - kSearchTFRightMarginWhenEditing - kLeftMargin; | |
self.rightButton.left = self.backgroundImageView.right - self.rightButton.width; | |
self.cancelButton.left = ScreenWidth - kSearchTFRightMarginWhenEditing; | |
} completion:^(BOOL finished) { | |
self.searchTextField.width = kSearchTFWidthEditing; | |
}]; | |
self.searchTextField.canTouch = YES; | |
[self.searchTextField becomeFirstResponder]; | |
} else { | |
self.searchTextField.text = nil; | |
self.text = nil; | |
_rightButton.hidden = YES; | |
[UIView animateWithDuration:0.2 animations:^{ | |
self.backgroundImageView.width = ScreenWidth - kLeftMargin*2; | |
self.rightButton.left = self.backgroundImageView.right - self.rightButton.width; | |
self.cancelButton.left = ScreenWidth; | |
} completion:^(BOOL finished) { | |
self.searchTextField.width = kSearchTFWidthNomal; | |
}]; | |
self.searchTextField.canTouch = NO; | |
[self.searchTextField resignFirstResponder]; | |
} | |
} | |
- (BOOL)isFirstResponder { | |
return self.searchTextField.isFirstResponder; | |
} | |
- (BOOL)resignFirstResponder { | |
return [self.searchTextField resignFirstResponder]; | |
} | |
- (BOOL)becomeFirstResponder { | |
return [self.searchTextField becomeFirstResponder]; | |
} | |
- (void)setText:(NSString *)text { | |
_text = text; | |
self.searchTextField.text = text; | |
[self.searchTextField sendActionsForControlEvents:UIControlEventEditingChanged]; | |
} | |
- (void)textFieldDidBeginEditing:(UITextField *)textField { | |
if ([self.delegate respondsToSelector:@selector(searchBarTextDidBeginEditing:)]) { | |
[self.delegate searchBarTextDidBeginEditing:self]; | |
} | |
} | |
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { | |
// self.searchTextField.width = kSearchTFWidthNomal; | |
return YES; | |
} | |
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { | |
// self.searchTextField.width = kSearchTFWidthEditing; | |
return YES; | |
} | |
- (void)textFieldDidEndEditing:(UITextField *)textField { | |
if ([self.delegate respondsToSelector:@selector(searchBarTextDidEndEditing:)]) { | |
[self.delegate searchBarTextDidEndEditing:self]; | |
} | |
} | |
- (BOOL)textFieldShouldReturn:(UITextField *)textField { | |
if ([self.delegate respondsToSelector:@selector(searchBarShouldReturn:)]) { | |
return [self.delegate searchBarShouldReturn:textField]; | |
} | |
return YES; | |
} | |
- (void)textFieldDidChange { | |
NSLog(@"self.searchTextField.text :%@",self.searchTextField.text); | |
NSLog(@"self.searchTextField.markedTextRange : %@",self.searchTextField.markedTextRange); | |
if (self.searchTextField.markedTextRange == nil) | |
{ | |
if ([self.delegate respondsToSelector:@selector(searchBar:textDidChange:)]) { | |
[self.delegate searchBar:self textDidChange:self.searchTextField.text]; | |
} | |
} | |
_text = self.searchTextField.text; | |
if (self.searchTextField.text.length) { | |
_rightButton.hidden = NO; | |
} else { | |
_rightButton.hidden = YES; | |
} | |
} | |
- (void)cancelButtonClick { | |
[[NSNotificationCenter defaultCenter] postNotificationName:SEARCH_CANCEL_NOTIFICATION_KEY object:nil]; | |
if (self.cancelClicked) { | |
self.cancelClicked(); | |
} | |
} | |
- (void)rightButtonClick { | |
if (self.searchTextField.text) { | |
self.searchTextField.text = @""; | |
self.text = nil; | |
_rightButton.hidden = YES; | |
if ([self.delegate respondsToSelector:@selector(searchBarClearText)]) { | |
[self.delegate searchBarClearText]; | |
} | |
} | |
} | |
- (void)drawRect:(CGRect)rect { | |
[super drawRect:rect]; | |
} | |
- (void)layoutSubviews { | |
[super layoutSubviews]; | |
NSMutableAttributedString *placeholder = [[NSMutableAttributedString alloc] initWithString:self.placeholder]; | |
[placeholder addAttribute:NSForegroundColorAttributeName | |
value:UIColorFromRGB(0x999999) | |
range:NSMakeRange(0, self.placeholder.length)]; | |
[placeholder addAttribute:NSFontAttributeName | |
value:[UIFont boldSystemFontOfSize:13] | |
range:NSMakeRange(0, self.placeholder.length)]; | |
self.searchTextField.attributedPlaceholder = placeholder; | |
} | |
- (UIView *)backgroundImageView { | |
if (!_backgroundImageView) { | |
_backgroundImageView = [[UIView alloc] init]; | |
_backgroundImageView.frame = CGRectMake(kLeftMargin, kTopMargin, ScreenWidth - kLeftMargin*2, kSearchTFHeight); | |
_backgroundImageView.backgroundColor = UIColorFromRGB(0x222224); | |
_backgroundImageView.layer.cornerRadius = kSearchTFHeight/2.0; | |
} | |
return _backgroundImageView; | |
} | |
- (UITextField *)searchTextField { | |
if (!_searchTextField) { | |
_searchTextField = [[QYPDSearchTextField alloc] initWithFrame:CGRectMake(kLeftMargin+12, kTopMargin, ScreenWidth - kLeftMargin*2-12, kSearchTFHeight)]; | |
_searchTextField.canTouch = NO; | |
// UIImageView *searchIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"search_icon"]]; | |
// searchIcon.contentMode = UIViewContentModeScaleAspectFit; | |
// searchIcon.frame = CGRectMake(0, 0, 24, 24); | |
// _searchTextField.leftView = searchIcon; | |
// _searchTextField.leftViewMode = UITextFieldViewModeAlways; | |
_searchTextField.font = [UIFont systemFontOfSize:13.0f]; | |
_searchTextField.textColor = UIColorFromRGB(0xffffff); | |
_searchTextField.tintColor = UIColorFromRGB(0x25D120); | |
[_searchTextField addTarget:self action:@selector(textFieldDidChange) forControlEvents:UIControlEventEditingChanged]; | |
_searchTextField.delegate = self; | |
_searchTextField.returnKeyType = UIReturnKeySearch; | |
_searchTextField.enablesReturnKeyAutomatically = YES; | |
} | |
return _searchTextField; | |
} | |
- (UIButton *)rightButton { | |
if (!_rightButton) { | |
_rightButton = [UIButton buttonWithType:UIButtonTypeCustom]; | |
[_rightButton setImage:[UIImage imageNamed:@"qypd_search_delete"] forState:UIControlStateNormal]; | |
[_rightButton setImage:[UIImage imageNamed:@"qypd_search_delete"] forState:UIControlStateHighlighted]; | |
[_rightButton addTarget:self action:@selector(rightButtonClick) forControlEvents:UIControlEventTouchUpInside]; | |
_rightButton.frame = CGRectMake(ScreenWidth - kLeftMargin - 36, (kSearchBarHeight-36)/2.0, 36, 36);//在setIsEditing 重新设置过 x 值 | |
_rightButton.hidden = YES; | |
} | |
return _rightButton; | |
} | |
- (UIButton *)cancelButton { | |
if (!_cancelButton) { | |
_cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; | |
_cancelButton.frame = CGRectMake(ScreenWidth, 0, kSearchTFRightMarginWhenEditing, kSearchBarHeight); | |
_cancelButton.titleLabel.font = [UIFont systemFontOfSize:15.0]; | |
[_cancelButton setTitle:@"取消" forState:UIControlStateNormal]; | |
[_cancelButton setTitleColor:UIColorFromRGB(0x999999) forState:UIControlStateNormal]; | |
[_cancelButton addTarget:self action:@selector(cancelButtonClick) forControlEvents:UIControlEventTouchUpInside]; | |
} | |
return _cancelButton; | |
} | |
- (void)dealloc { | |
NSLog(@"PPQSearchBar dealloc"); | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PPQSearchTextField.h | |
// | |
// | |
// Created by LinPan on 2018/6/29. | |
// | |
// | |
#import <UIKit/UIKit.h> | |
@interface QYPDSearchTextField : UITextField | |
@property (nonatomic, assign) BOOL canTouch; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PPQSearchTextField.m | |
// | |
// | |
// Created by LinPan on 2018/6/29. | |
// | |
// | |
#import "QYPDSearchTextField.h" | |
@implementation QYPDSearchTextField | |
- (instancetype)initWithFrame:(CGRect)frame { | |
self = [super initWithFrame:frame]; | |
self.canTouch = YES; | |
return self; | |
} | |
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { | |
BOOL result = [super pointInside:point withEvent:event]; | |
if (_canTouch) { | |
return result; | |
} else { | |
return NO; | |
} | |
} | |
- (void)dealloc { | |
NSLog(@"PPQSearchTextField dealloc"); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment