• iOS-关于自定义分段选择器的一些小事(Segmented)


    系统自带的分段选择就是 UISegmentedControl ,也有一些大佬自定义的 Segmented ,比如Git上的 HMSegmentedControl ,我以前最初的项目中,也有用到过,如果自己写,或者想自定义一些UI,该从哪里出发,其实在用过 HMSegmentedControl 之后,大致就有思路了,如果想简单的实现下,可以利用 UICollectionView 来实现,下面是我利用 UICollectionView 写的一个简单的小栗子,效果图

    设计思路

    首先利用 UICollectionView 处理每个item的大小,确切的说是宽度,那么就要每次选中一个item后,重新计算所有的item的宽度,同时计算 UICollectionView 的 contentSize.width;

    计算每个item宽度分为两种情况,一种是选中的字体的显示,一种是未选中的字体显示,比如字体大小,颜色等,然后根据字体大小字符串长度,计算出字体需要展示的宽度,并计算对应的item宽度,最后把每个item的宽度保存起来,用于在 UICollectionView 代理方法中做处理;

    计算 contentSize.width 由上图可知,是由两边的间距,item之间的间距和每个item的总和,目的是利用 contentSize.width 计算下划线的位置;

    具体实现

    #import "XKCollectionView.h"
    
    ///四周边距
    const static CGFloat _margin_left = 5;
    const static CGFloat _margin_right = 5;
    const static CGFloat _margin_top = 0;
    const static CGFloat _margin_bottom = 2;
    const static CGFloat _margin_space = 15;
    
    const static CGFloat _line_width = 30.0;
    const static CGFloat _line_height = 3.0;
    
    @interface XKCollectionView ()<UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
    ///临时数据
    @property (nonatomic,strong) NSArray<NSString *> *titleArray;
    ///每个item的宽度
    @property (nonatomic,strong) NSMutableArray *widthsArray;
    ///底部线条
    @property (nonatomic,strong) UIView *lineView;
    ///选中的item索引
    @property (nonatomic,assign) NSInteger selectIndex;
    ///选中的item string
    @property (nonatomic,strong) NSString *selectString;
    ////计算出来的总宽度,用于设置 UICollectionView.contentSize.width
    @property (nonatomic,assign) CGFloat totalContentWidth;
    @end
    @implementation XKCollectionView
    - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout{
        self = [super initWithFrame:frame collectionViewLayout:layout];
        if (self) {
            [self setup];
        }
        return self;
    }
    - (void)setup{
        _selectIndex = 0;
        self.widthsArray = [NSMutableArray array];
        [self addSubview:self.lineView];
        self.backgroundColor = [UIColor whiteColor];
        self.showsHorizontalScrollIndicator = NO;
        self.delegate = self;
        self.dataSource = self;
        [self registerClass:[XKCollectionViewCell class] forCellWithReuseIdentifier:@"XKCollectionViewCell"];
        
        _titleArray = @[@"一级建造师",@"二级建造师",@"造价工程师",@"咨询工程师",@"注册安全工程师",@"监理工程师",@"注册电气工程师",@"环境影响评价工程师",@"注册城乡规划师",@"注册消防工程师"];
        [self storeSegmentedWidth];
        [self reloadData];
        CGRect lineRext = [self measureLineFrame];
        self.lineView.frame = lineRext;
        ///设置偏移量
        [self setContentOffset:CGPointMake([self measureContentOffsetX], 0)];
    }
    
    
    - (void)updateSelectSeg{
        [self storeSegmentedWidth];
        [self reloadData];
        [UIView animateWithDuration:0.3 animations:^{
            CGRect lineRext = [self measureLineFrame];
            self.lineView.frame = lineRext;
        }];
        
        [self setContentOffset:CGPointMake([self measureContentOffsetX], 0) animated:YES];
    }
    #pragma mark ========== 储存计算好的item宽度 ==========
    ///每次切换时更新
    - (void)storeSegmentedWidth{
        _selectIndex = 0;
        _totalContentWidth = 0;
        [self.widthsArray removeAllObjects];
        
        if (_selectString) {
            for (int i = 0; i < _titleArray.count; i ++) {
                NSString *title = _titleArray[i];
                if ([title isEqualToString:_selectString]) {
                    _selectIndex = i;
                    break;
                }
            }
        }
       
        
        for (int i = 0; i < _titleArray.count; i ++) {
            
            CGSize size = [self measureTitleIndex:i];
            NSNumber *value = [NSNumber numberWithFloat:size.width];
            [self.widthsArray addObject:value];
            
            _totalContentWidth = _totalContentWidth + size.width;
            if (i < _titleArray.count - 1) {
                _totalContentWidth = _totalContentWidth + _margin_space;
            }
        }
        _totalContentWidth = _totalContentWidth + _margin_left + _margin_right;
        
    }
    - (CGSize)measureTitleIndex:(NSUInteger)index {
        if (index >= _titleArray.count) {
            return CGSizeZero;
        }
        
        id title = _titleArray[index];
        CGSize size = CGSizeZero;
        BOOL selected = (index == _selectIndex);
        NSDictionary *titleAttrs = selected ? [self resultingSelectedTitleTextAttributes] : [self resultingTitleTextAttributes];
        size = [(NSString *)title sizeWithAttributes:titleAttrs];
        UIFont *font = titleAttrs[@"NSFont"];
        size = CGSizeMake(ceil(size.width), ceil(size.height - font.descender));
        CGSize resault = CGRectIntegral((CGRect){CGPointZero, size}).size;
        return resault;
    }
    - (NSDictionary *)resultingSelectedTitleTextAttributes {
        NSDictionary *resultingAttrs = @{NSForegroundColorAttributeName : [UIColor blackColor] ,NSFontAttributeName:[UIFont fontWithName:@"Helvetica-Bold" size:18.0]};
        return resultingAttrs;
    }
    - (NSDictionary *)resultingTitleTextAttributes {
        NSDictionary *resultingAttrs = @{NSForegroundColorAttributeName : [UIColor lightGrayColor],NSFontAttributeName:[UIFont systemFontOfSize:14.0]};
        return resultingAttrs;
    }
    #pragma mark ========== 计算下划线位置 ==========
    - (CGRect)measureLineFrame{
        CGRect lineRect = CGRectZero;
        CGFloat lineRectX = 0;
        for (int i = 0; i < _selectIndex; i ++) {
            NSNumber *number = self.widthsArray[i];
            lineRectX = lineRectX + [number floatValue] + _margin_space;
        }
        CGFloat widthSelect = [self.widthsArray[_selectIndex] floatValue];
        CGFloat lastLocation = widthSelect >= _line_width ? (widthSelect - _line_width)/2 : (_line_width - widthSelect)/2;
        lineRectX = lineRectX + _margin_left + lastLocation;
        
        lineRect = CGRectMake(lineRectX, self.bounds.size.height - _line_height - 2, _line_width, _line_height);
        return lineRect;
    }
    #pragma mark ========== 计算偏移量 ==========
    - (CGFloat)measureContentOffsetX{
        CGFloat selfWidth = self.bounds.size.width;
        
        ///先计算点击的item中心点
        CGFloat selectedCenterX = 0;
        for (int i = 0; i < _selectIndex; i ++) {
            NSNumber *number = self.widthsArray[i];
            selectedCenterX = selectedCenterX + [number floatValue] + _margin_space;
        }
        CGFloat widthSelect = [self.widthsArray[_selectIndex] floatValue];
        selectedCenterX = selectedCenterX + widthSelect/2;
        
        if (_totalContentWidth <= selfWidth) {///充满内部不做偏移
            return 0;
        }
        
        if (selectedCenterX <= selfWidth/2) {
            return 0;
        }
        else if (selectedCenterX >= _totalContentWidth - selfWidth/2){
            return _totalContentWidth - selfWidth;
        }
        else{
            return selectedCenterX - selfWidth/2;
        }
    }
    #pragma mark ========== 代理 ==========
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
        return _titleArray.count;
    }
    
    - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
        return _margin_space;
    }
    - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
        return UIEdgeInsetsMake(_margin_top, _margin_left, _margin_bottom, _margin_right);
    }
    //item大小
    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
        NSNumber *number = self.widthsArray[indexPath.row];
        return CGSizeMake([number floatValue],30);
    }
    - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
        XKCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"XKCollectionViewCell" forIndexPath:indexPath];
        NSString *title = _titleArray[indexPath.row];
        cell.title = title;
        if (indexPath.row == _selectIndex) {
            cell.isSelectd = YES;
        }
        else{
            cell.isSelectd = NO;
        }
        return cell;
    }
    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
        _selectString = _titleArray[indexPath.row];
        [self updateSelectSeg];
    }
    #pragma mark ========== 变量 ==========
    
    - (UIView *)lineView{
        if(!_lineView){
            _lineView = [[UIView alloc]init];
            _lineView.backgroundColor = [UIColor purpleColor];
            _lineView.layer.masksToBounds = YES;
            _lineView.layer.cornerRadius = _line_height/2;
        }
        return _lineView;
    }
    
    @end
  • 相关阅读:
    通过SQLServer的数据库邮件来发送邮件
    sql生成数据库的序列号
    存储过程备份数据库
    LED客显的类
    坦克大战java版
    连连看java版
    贪吃蛇java版
    分享插件 javascript
    js实现上传图片及时预览
    json返回date类型转为字符串
  • 原文地址:https://www.cnblogs.com/wangkejia/p/11158051.html
Copyright © 2020-2023  润新知