自定義UISegmentedControl功能實現(使用UIView模擬)
阿新 • • 發佈:2018-12-21
自己做專案的過程中遇到過各種各樣的問題,首先我先說一下實現UI設計的一個解決方案:
- 首先UI設計是這樣的(貼一個做成的圖) 一開始我的想法就是UISegmentedControl來做,但是剛開始做就發現樣式其實跟UI的一點都不一樣,所以我開始思考如何自定義控制元件,所以想到了使用UIView來模擬實現。
- 首先就是建立一個控制元件類
而這個類則是你要顯示在螢幕上的控制元件。
首先肯定是要實現初始化函式,所以我又引申到了需要多少個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來進行響應。
-
這個時候就開始新增你想要的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; } } } } }
-
當然這個控制元件雖然不太複雜,但是還是需要代理來響應切換檢視的方法(類似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出來再上傳吧~