1. 程式人生 > >自定義UISegmentedControl功能實現(使用UIView模擬)

自定義UISegmentedControl功能實現(使用UIView模擬)

自己做專案的過程中遇到過各種各樣的問題,首先我先說一下實現UI設計的一個解決方案:

  1. 首先UI設計是這樣的(貼一個做成的圖) 一開始我的想法就是UISegmentedControl來做,但是剛開始做就發現樣式其實跟UI的一點都不一樣,所以我開始思考如何自定義控制元件,所以想到了使用UIView來模擬實現。
  2. 首先就是建立一個控制元件類 而這個類則是你要顯示在螢幕上的控制元件。 首先肯定是要實現初始化函式,所以我又引申到了需要多少個tab的問題,所以我實現了一個動態管理tab數量的初始化函式
    - (instancetype)initWithFrame:(CGRect)frame andSelectIndex:(NSInteger)index andTitle:(NSArray *)titles andData:(NSArray *)datas{
    
        self = [super initWithFrame:frame];
    
        if(self){
    
            self.titleArray = titles;
    
            dataArray = datas;
    
            [self addObserver:self forKeyPath:@"selectIndex" options:NSKeyValueObservingOptionNew context:NULL];
    
            [self setTitleInit:titles andIndex:index];
    
        }
    
        return self;
    
    }

    上面的title和下面的數字裝在數組裡面一起傳過來,這樣就知道你需要多少個tab了。然後我就開始想怎麼點選一個tab實現響應,使用代理呢還是什麼,最後還是用了KVO來監控點選的index來進行響應。

  3. 這個時候就開始新增你想要的tab  

    - (void)setDialTitleInit:(NSArray *)titleArray andIndex:(NSInteger)index{
        NSInteger titleNumber = titleArray.count;
        for (int i=0; i<titleNumber; i++) {
            HYSegmentedView *view = [[HYSegmentedView alloc]initWithFrame:CGRectMake(i*self.frame.size.width/titleNumber, 0, self.frame.size.width/titleNumber, self.frame.size.height) andTitle:titleArray[i] andData:dataArray[i]];
            view.delegate = self;
            if(dataArray != nil){
                view.dataLabel.text = dataArray[i];
            }
            [view setSelectedColor:colorWithRGBA(59, 193, 108, 1.0) forType:HYIsSelected];
            [view setSelectedColor:colorWithRGBA(51, 51, 51, 1.0) forType:HYNotSelected];
            if(i == index){
                view.type = HYIsSelected;
                view.tipLabel.textColor = colorWithRGBA(59, 193, 108, 1.0);
                view.dataLabel.textColor = colorWithRGBA(59, 193, 108, 1.0);
            }
            view.tag = i + 50;
            [self addSubview:view];
            if(i == index){
                self.indicator = [[UIView alloc]initWithFrame:CGRectMake(i*self.frame.size.width/titleNumber, self.frame.size.height - 2, self.frame.size.width/(titleNumber*3), 2)];
                [self.indicator setCenter:CGPointMake(view.center.x, self.frame.size.height - 2)];
                self.indicator.backgroundColor = colorWithRGBA(59, 193, 108, 1.0);
                [self addSubview:self.indicator];
            }
        }
    }

    這裡我建立了一個view類來顯示tab就是HYSegmentedView,這樣定製起來更加方便,並且以後管理程式碼或者更改UI更為靈活,新增完成後開始寫點選響應的KVO事件  

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
        if([keyPath isEqualToString:@"selectIndex"]){
            for(HYSegmentedView *view in self.subviews){
                if(view.tag == ((HYSegmentedControl *)object).selectIndex + 50){
                    if(view.tag){
                        [view.dataLabel setTextColor:colorWithRGBA(16, 142, 233, 1.0)];
                        [view.tipLabel setTextColor:colorWithRGBA(16, 142, 233, 1.0)];
                        view.type = HYIsSelected;
                    }
                }else{
                    if(view.tag){
                        [view.dataLabel setTextColor:colorWithRGBA(51, 51, 51, 1.0)];
                        [view.tipLabel setTextColor:colorWithRGBA(51, 51, 51, 1.0)];
                        view.type = HYNotSelected;
                    }
                    
                }
            }
        }
    }
  4. 當然這個控制元件雖然不太複雜,但是還是需要代理來響應切換檢視的方法(類似UISegmentedControl的點選響應事件)  

    @protocol HYSegmentedControlDelegate<NSObject>
    
    - (void)clickToChangeView:(NSInteger)index;
    
    @end

    和底部指示器的移動  

    - (void)clickedWithType:(HYSelectedType)type andTag:(NSInteger)tag{
        __weak typeof(self) weakSelf = self;
        [UIView animateWithDuration:0.2 animations:^{
            UIViewController *currentController = [UIApplication sharedApplication].keyWindow.rootViewController;
            [weakSelf.indicator setFrame:CGRectMake((tag - 50)*weakSelf.frame.size.width/self.titleArray.count , weakSelf.frame.size.height - 2, weakSelf.frame.size.width/self.titleArray.count, 2)];
            if([((UITabBarController *)currentController).viewControllers[0] isKindOfClass:[DialViewController class]]){
                UIView *currentView;
                [weakSelf.indicator setFrame:CGRectMake((tag - 50)*weakSelf.frame.size.width/self.titleArray.count , weakSelf.frame.size.height - 2, weakSelf.frame.size.width/(self.titleArray.count*3), 2)];
                for(HYSegmentedView *view in self.subviews){
                    if (view.tag) {
                        if(view.tag == tag){
                            currentView = view;
                        }
                    }
                }
                [weakSelf.indicator setCenter:CGPointMake(currentView.center.x, self.frame.size.height-2)];
            }
        }];
        [self.delegate clickToChangeView:tag-50];
    }

    思路就是這樣,其實工作中很多地方都需要自己去想,如果能靠自己找出解決方案並且能夠根據UI實現高度定製那最好不過了。程式碼沒有上傳到Github哦,過一段事件整理一下做個demo出來再上傳吧~