藤原とうふ店(自家用)好东西小知识点

iOS自定义搜索框和历史搜索显示

2017-09-23  本文已影响2475人  Maj_sunshine

前言

搜索框的使用在开发过程中已经是非常见了。现在几乎的app都带有搜索功能。系统给我们提供了搜索框UISeacherBar,但我在用了几次这个发现使用起来不是很方便,很多东西不好扩展。最近开发ipad就改用textField自定义一个SeacherBar ,点击搜索后保存搜索记录到本地,再将历史搜索记录显示。有点儿类似爱奇艺搜索界面。我修改了下布局,在iphone上使用。demo并没有封装太多接口修改属性。要修改可以去各个.m文件中修改。

这个demo地址

其实把项目中的功能提出来,也方便我以后查看。或许我以后会笑自己怎么会写成这么low的代码。。哈哈哈。不开玩笑了。

先看下效果图

搜索框界面.gif

主要思路

上面截屏截的不好。尴尬了旁边都看到了。。

1 搜索框实现思路

  1. 输入框初始化的配置
/*! 基础配置 */

- (void)baseSetting{
   /*! 边框处理 */
   _textField.layer.borderColor = ZDGreenColor.CGColor;
   _textField.layer.borderWidth = 1;
   _textField.layer.cornerRadius = self.frame.size.height/2;
   _textField.layer.masksToBounds = YES;
   /*! 字体其他 */
   _textField.font = KweixinFont(14);
   _textField.tintColor = ZDGreenColor;
   _textField.keyboardType = UIKeyboardTypeDefault;
   _textField.delegate =self;
   /*! 设置键盘return样式为搜索样式 */
   _textField.returnKeyType = UIReturnKeySearch;
   /*! 设置为无文字就灰色不可点 */
   _textField.enablesReturnKeyAutomatically = YES;
   /*! 开启系统清除样式 */
   _textField.clearButtonMode = UITextFieldViewModeAlways;
   /*! 添加左边遮盖 */
   [_textField setTextOffsetWithLeftViewRect:CGRectMake(0, 0, leftViewWidth, self.frame.size.height) WithMode:UITextFieldViewModeAlways];
   /*! 编辑事件观察 */
   [_textField addTarget:self action:@selector(textFieldDidEditing:) forControlEvents:UIControlEventEditingChanged];
}

2 中间默认文字为UILabel,居中,搜索图片在文字左边15的位置
3 实现的textField代理协议和监听文字改变

/*! 当输入框开始编辑的时候 */
- (void)textFieldDidBeginEditing:(UITextField *)textField{
   /*! _placeholderLabel移动到关标右边*/
   [_placeholderLabel mas_updateConstraints:^(MASConstraintMaker *make) {
       make.centerX.mas_equalTo(_textField).offset(-_textField.frame.size.width/2+leftViewWidth+_size.width/2+5);
   }];
   /*! _searchImage移动到关标左边 */
   [_searchImage mas_updateConstraints:^(MASConstraintMaker *make) {
       make.centerX.mas_equalTo(_textField).offset(-_textField.frame.size.width/2-space+leftViewWidth);
   }];
   [UIView animateWithDuration:0.25 animations:^{
//        执行更新
       [self layoutIfNeeded];
   }];
   
}

/*! 输入框结束编辑 因为项目里用了IQKeyboardManager 上面有工具栏 如果没成 这个代理方法可以不添加 */
- (void)textFieldDidEndEditing:(UITextField *)textField{
   if (textField.text.length>0) {
       NSLog(@"进行搜索");
       [_SearchDelegate searchWithStr:textField.text];
   }
}

/*! 点击键盘搜索按钮的回调 */
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
   [_textField resignFirstResponder];
   [_SearchDelegate searchWithStr:textField.text];
   NSLog(@"点击了搜索");
   return YES;
}

这些简单的动画都是通过mas_updateConstraints配合[self layoutIfNeeded],简单又好用的。

2 历史搜索的实现

  1. 这里主要是UICollectionView的使用 ,主要是UICollectionViewFlowLayout的写法。图中文字阴影部分这时label的背景颜色,其实两个item之间的距离固定只有5 。实现方法
//设置两个item之间的最小距离固定为5
self.minimumInteritemSpacing = 5;
//自己声明两个item之间的最大距离属性maximumInteritemSpacing 通过下面方法设置。

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    //使用系统帮我们计算好的结果。
    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
    
    //第0个cell没有上一个cell,所以从1开始
    for(int i = 1; i < [attributes count]; ++i) {
        //这里 UICollectionViewLayoutAttributes 的排列总是按照 indexPath的顺序来的。
        UICollectionViewLayoutAttributes *curAttr = attributes[i];
        UICollectionViewLayoutAttributes *preAttr = attributes[i-1];
        
        NSInteger origin = CGRectGetMaxX(preAttr.frame);
        //根据  maximumInteritemSpacing 计算出的新的 x 位置
        CGFloat targetX = origin + _maximumInteritemSpacing;
        // 只有系统计算的间距大于  maximumInteritemSpacing 时才进行调整
        if (CGRectGetMinX(curAttr.frame) > targetX) {
            // 换行时不用调整
            if (targetX + CGRectGetWidth(curAttr.frame) < self.collectionViewContentSize.width) {
                CGRect frame = curAttr.frame;
                frame.origin.x = targetX;
                curAttr.frame = frame;
            }
        }
    }
    return attributes;
}

2 通过上面方法固定左右item间距为5,第二步:根据本地历史搜索的字符串数组计算UICollectionView有多少行。 如果累加的长度大于屏幕宽度,则行数+1

/*! 历史搜索高度 */
- (NSInteger)rowForCollection :(NSArray *)array{
    CGFloat width = 0;
    NSInteger row = 1;
    /*! 55为cell额外宽度 +5的边距 */
    for (NSString *str in array) {
        CGSize size = [str boundingRectWithSize:CGSizeMake(1000, 30) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName :KweixinFont(14)} context:nil].size;
        width = width +size.width+55;
        NSLog(@"width = %f",width);
        /*! 减5 时因为最后一个item不需要 + 5的边距 */
        if ((width-5)/(kScreenWidth)>1) {
            row = row+1;
            width =size.width+55 ;
        }
    }
    return row>4?4:row;
}

我上面的方法可以不好,你也可以通过上面第一个代理里面计算,实现下面方法

-(CGSize)collectionViewContentSize{
}

直接计算contentsize 。

3 cell的删除
我想通过下面的方法添加一个抖动的cell,不过效果不是很好,希望有人能告诉我更好的实现方法

/*! 添加抖动动画 */

- (void)addShake : (SearchCollectionViewCell *)cell{
    [UIView animateKeyframesWithDuration:0.3 delay:0 options:UIViewKeyframeAnimationOptionRepeat animations:^{
        [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.075 animations:^{
            cell.transform = CGAffineTransformMakeRotation(-8/ 180.0 * M_PI);
        }];
        [UIView addKeyframeWithRelativeStartTime:0.1 relativeDuration:0.15 animations:^{
            cell.transform = CGAffineTransformRotate(cell.transform,16 /180.0 * M_PI);
        }];
        [UIView addKeyframeWithRelativeStartTime:0.2 relativeDuration:0.1 animations:^{
            cell.transform = CGAffineTransformRotate(cell.transform, -8 / 180.0 * M_PI);
        }];
    } completion:nil];
}

结束啦 这个demo地址 fighting

上一篇下一篇

猜你喜欢

热点阅读