今天總結了一下平時工作中為那些奇葩的UI設計自定義的控制元件,下面一個個分享給大家。
一、第一個是tableView的透明度漸變效果
1、效果:
很多app用到了這種效果,比如歌詞顯示、直播間聊天記錄等。
大致效果如下:
2、使用方法:
1 2 3 4 5 6 |
/* * frame:tableView的frame * direction:透明漸進的方向 * gradualValue:透明範圍值,如果只有一個方向,此值傳一個NSNumber、NSString即可,值的範圍0—1。如果是兩個方向,則需要傳一個陣列,陣列裡邊傳兩個NSNumber或者NSString ***/ + (instancetype)gradualTableViewWithFrame:(CGRect)frame direction:(WZBTableViewGradualDirection)direction gradualValue:(id)gradualValue; |
引數值說明一下,direction代表方向,是一個位移列舉,如果想讓tableView頂部漸變,則此值為WZBTableViewGradualDirectionTop,如果為底部漸變,則此值為WZBTableViewGradualDirectionBottom,如果上下都要漸變,則需要WZBTableViewGradualDirectionTop | WZBTableViewGradualDirectionBottom。gradualValue代表漸變範圍值,值的範圍為0-1,如果想讓頂部20%漸變,此值為@(0.2)。如果想頂部底部都有20%漸變,此值為@[@(0.2), @(0.2)]。
如下:
1 |
WZBGradualTableView *tableView = [WZBGradualTableView gradualTableViewWithFrame:self.view.bounds direction:(WZBTableViewGradualDirectionTop | WZBTableViewGradualDirectionBottom) gradualValue:@[@(.3), @0.3]]; |
則顯示效果為:
如果這樣寫
1 |
[WZBGradualTableView gradualTableViewWithFrame:CGRectMake(0, self.view.frame.size.height - 180, self.view.frame.size.width, 140) direction:WZBTableViewGradualDirectionTop gradualValue:@.3f] |
效果如下:
3、實現大致原理:
這種漸變效果主要用到tableView的mask屬性,我們首先要建立一個CAGradientLayer,此類的使用網上介紹有很多,在這裡不再累述,不懂得私聊我,或者加入我的技術群。
上程式碼:
1 2 3 4 5 6 7 8 |
if (!self.layer.mask) { CAGradientLayer *maskLayer = [CAGradientLayer layer]; maskLayer.locations = @[@0.0, topValue, @(1-bottomValue.doubleValue), @1.0f]; maskLayer.bounds = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); maskLayer.anchorPoint = CGPointZero; self.layer.mask = maskLayer; } [self addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; |
由於tableView可以滑動,滑動的時候就需要實時的作出改變,因此我這裡使用KVO監聽“contentOffset”屬性,每當contentOffset發生改變,證明使用者滑動了tableView,這時候需要呼叫的程式碼為:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"contentOffset"]) { [self change]; } } - (void)change { UIScrollView *scrollView = (UIScrollView *)self; CGColorRef outerColor = [UIColor colorWithWhite:1.0 alpha:0.0].CGColor; CGColorRef innerColor = [UIColor colorWithWhite:1.0 alpha:1.0].CGColor; NSArray *colors; if (scrollView.contentOffset.y + scrollView.contentInset.top = scrollView.contentSize.height) { //Bottom of tableView colors = @[(__bridge id) outerColor, (__bridge id) innerColor, (__bridge id) innerColor, (__bridge id) innerColor]; } else { //Middle colors = @[(__bridge id) outerColor, (__bridge id) innerColor, (__bridge id) innerColor, (__bridge id) outerColor]; } ((CAGradientLayer *) scrollView.layer.mask).colors = colors; [CATransaction begin]; [CATransaction setDisableActions:YES]; scrollView.layer.mask.position = CGPointMake(0, scrollView.contentOffset.y); [CATransaction commit]; } |
別忘了移除觀察者:
1 2 3 |
- (void)dealloc { [self removeObserver:self forKeyPath:@"contentOffset"]; } |
4、GitHub原始碼地址:WZBGradualTableView
二、自定義的開關控制元件
1、效果:
2、使用方法:
將WZBSwitch.h和WZBSwitch.m拖入工程
在需要使用的地方呼叫
1 2 3 4 5 6 7 |
/** 初始化方法 * switchValueChange: 開關狀態改變回撥block */ WZBSwitch *switchView = [[WZBSwitch alloc] initWithFrame:CGRectMake(100, 100, 50, 25) switchValueChanged:^(WZBSwitch *swith, BOOL on) { // do someing }]; [self.view addSubview:switchView]; |
對於開關狀態的監聽或者您還可以通過代理:
1 2 3 4 |
WZBSwitch *switchView = [[WZBSwitch alloc] initWithFrame:CGRectMake(100, 100, 50, 25)]; [self.view addSubview:switchView]; // delegate switchView.delegate = self; |
然後實現代理方法即可
1 2 3 4 |
#pragma mark - WZBSwitchDelegate - (void)switchValueChange:(WZBSwitch *)swith on:(BOOL)on { // do someing } |
如果您想自定義開關顏色,程式碼如下:
1 2 3 4 5 6 7 8 9 10 |
//設定所有顏色 [switchView setUpAllColors:^NSDictionary *(UIColor *__autoreleasing *onTintColor, UIColor *__autoreleasing *onBackgroundColor, UIColor *__autoreleasing *offTintColor, UIColor *__autoreleasing *offBackgroundColor, UIColor *__autoreleasing *tintColor) { // 可以通過這種方法設定需要設定的顏色 *onTintColor = [UIColor redColor]; *onBackgroundColor = [UIColor blueColor]; *offTintColor = [UIColor greenColor]; *offBackgroundColor = [UIColor grayColor]; *tintColor = [UIColor blackColor]; return nil; }]; |
或者這樣
1 2 3 4 |
[switchView setUpAllColors:^NSDictionary *(UIColor *__autoreleasing *onTintColor, UIColor *__autoreleasing *onBackgroundColor, UIColor *__autoreleasing *offTintColor, UIColor *__autoreleasing *offBackgroundColor, UIColor *__autoreleasing *tintColor) { // 也可以通過這種方法設定需要設定的顏色 return @{OnTintColor : WZBColor(234, 67, 53), OnBackgroundColor : WZBColor(244, 161, 154), OffTintColor : WZBColor(255, 255, 255), OffBackgroundColor : WZBColor(214, 214, 214), TintColor : [UIColor colorWithRed:0.8252 green:0.8252 blue:0.8252 alpha:1.0]}; }]; |
3、實現大致原理:
此控制元件由兩部分組成,頂部View和底部View
1 2 |
@property (nonatomic, strong) UIView *topView; @property (nonatomic, strong) UIView *bottomView; |
1 2 3 4 |
/** 一個方法設定所有顏色 && block回撥 * switchValueChange: 開關狀態改變回撥block */ - (void)setUpAllColors:(NSDictionary *(^)(UIColor **onTintColor,UIColor **onBackgroundColor, UIColor **offTintColor, UIColor **offBackgroundColor, UIColor **tintColor))allColorBlock switchValueChanged:(SwitchValueChangeBlock)switchValueChange;; |
這個方法有兩個block引數,第一個可以設定您所需要設定的所有顏色值,第二個block是當開關狀態發生改變的時候回撥
1 2 |
/** 設定開關狀態, animated : 是否有動畫 */ - (void)setOn:(BOOL)newOn animated:(BOOL)animated; |
此方法用於設定開關狀態
1 2 3 4 |
@protocol WZBSwitchDelegate @optional - (void)switchValueChange:(WZBSwitch *)swith on:(BOOL)on; @end |
如果您不喜歡使用block,我還提供了代理方法監聽開關狀態的改變
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
- (void)setOn:(BOOL)newOn animated:(BOOL)animated { // if (_on == newOn) return; __block CGRect frame = self.topView.frame; CGFloat newX = newOn ? self.frame.size.width - self.topView.frame.size.width : 0; [UIView animateWithDuration:animated ? 0.2 : 0.0 animations:^{ frame.origin.x = newX; self.topView.frame = frame; [self setSwitchColorWithStatus:newOn]; } completion:^(BOOL finished) { if (finished) { // delegate if ([self.delegate respondsToSelector:@selector(switchValueChange:on:)]) { [self.delegate switchValueChange:self on:newOn]; } // block if (self.switchValueChange) { self.switchValueChange(self, newOn); } } }]; _on = newOn; } |
當外界呼叫方法改變開關狀態時,動畫/非動畫,改變上層View的frame即可
4、GitHub原始碼地址:WZBSwitch
三、一個仿網易的Segment
1、效果:
2、使用方法:
將WZBSegmentedControl.h和WZBSegmentedControl.m拖入工程
在需要使用的地方呼叫
1 2 3 4 5 6 7 8 |
/** 初始化方法 * titles: 所有標題 * titleClick: 點選標題的block回撥 */ WZBSegmentedControl *segmentedControl = [WZBSegmentedControl segmentWithFrame:(CGRect){0, 0, 170, 25} titles:[self titles] titleClick:^(NSInteger index) { // do soming }]; self.navigationItem.titleView = segmentedControl; |
3、實現大致原理:
此控制元件還不是很完善,目前只提供一個初始化方法:
1 2 3 4 5 |
/* 初始化方法 * frame:控制元件frame * titleClick:點選title的時候block回撥 **/ + (instancetype)segmentWithFrame:(CGRect)frame titles:(NSArray *)titles titleClick:(void(^)(NSInteger index))titleClick; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
- (void)setContentOffset:(CGPoint)contentOffset { CGRect frame = self.backgroundView.frame; frame.origin.x = contentOffset.x; self.backgroundView.frame = frame; // 找出要操作的兩個button設定顏色(目前先這樣寫,後續改進) for (UIView *v in self.subviews) { if ([v isKindOfClass:[UIButton class]]) { UIButton *button = (UIButton *)v; CGFloat overLapWidth = CGRectIntersection(button.frame, self.backgroundView.frame).size.width; NSInteger gb = 255 - overLapWidth * (255 / (self.frame.size.width / self.titles.count)); [button setTitleColor:WZBColor(255, gb, gb) forState:UIControlStateNormal]; } } } |
核心方法:改變底部白色滑塊的位置,但是如果注意觀察,有個注意點是,在滑動的時候title的文字也會隨著漸變,目前先試用這個方法臨時解決,後續會提供方法設定文字顏色、選中文字顏色、背景顏色以及滑塊顏色等。
4、GitHub原始碼地址:WZBSegmentedControl
怎麼樣,這些您學會怎麼用了嗎?