iOS开发中用到的自定义控件

一、第一个是tableView的透明度渐变效果

1、效果:

很多app用到了这种效果,比如歌词显示、直播间聊天记录等。

大致效果如下:

2、使用方法:

/*

* 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)]。

如下:

WZBGradualTableView *tableView = [WZBGradualTableView gradualTableViewWithFrame:self.view.bounds direction:(WZBTableViewGradualDirectionTop | WZBTableViewGradualDirectionBottom)  gradualValue:@[@(.3), @0.3]];

如果这样写

[WZBGradualTableView gradualTableViewWithFrame:CGRectMake(0, self.view.frame.size.height - 180, self.view.frame.size.width, 140) direction:WZBTableViewGradualDirectionTop  gradualValue:@.3f]


3、实现大致原理:

这种渐变效果主要用到tableView的mask属性,我们首先要创建一个CAGradientLayer,此类的使用网上介绍有很多,在这里不再累述,不懂得私聊我,或者加入我的技术群。

上代码:

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,这时候需要调用的代码为:

- (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];

}

别忘了移除观察者:

- (void)dealloc {

[self removeObserver:self forKeyPath:@"contentOffset"];

}

4、GitHub源码地址:https://github.com/WZBbiao/WZBGradualTableView

二、自定义的开关控件

1、效果:


2、使用方法:

将WZBSwitch.h和WZBSwitch.m拖入工程

在需要使用的地方调用

/** 初始化方法

*  switchValueChange: 开关状态改变回调block

*/

WZBSwitch *switchView = [[WZBSwitch alloc] initWithFrame:CGRectMake(100, 100, 50, 25) switchValueChanged:^(WZBSwitch *swith, BOOL on)    {

// do someing

}];

[self.view addSubview:switchView];

对于开关状态的监听或者您还可以通过代理:

WZBSwitch *switchView = [[WZBSwitch alloc] initWithFrame:CGRectMake(100, 100, 50, 25)];

[self.view addSubview:switchView];

// delegate

switchView.delegate = self;

然后实现代理方法即可

#pragma mark - WZBSwitchDelegate

- (void)switchValueChange:(WZBSwitch *)swith on:(BOOL)on {

// do someing

}

如果您想自定义开关颜色,代码如下:

//设置所有颜色

[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;

}];

或者这样

[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

@property (nonatomic, strong) UIView *topView;

@property (nonatomic, strong) UIView *bottomView;

/** 一个方法设置所有颜色 && block回调

*  switchValueChange: 开关状态改变回调block

*/

- (void)setUpAllColors:(NSDictionary *(^)(UIColor **onTintColor,UIColor **onBackgroundColor, UIColor **offTintColor, UIColor **offBackgroundColor, UIColor **tintColor))allColorBlock switchValueChanged:(SwitchValueChangeBlock)switchValueChange;;

这个方法有两个block参数,第一个可以设置您所需要设置的所有颜色值,第二个block是当开关状态发生改变的时候回调

/** 设置开关状态, animated : 是否有动画 */

- (void)setOn:(BOOL)newOn animated:(BOOL)animated;

此方法用于设置开关状态

@protocol WZBSwitchDelegate

@optional

- (void)switchValueChange:(WZBSwitch *)swith on:(BOOL)on;

@end

如果您不喜欢使用block,我还提供了代理方法监听开关状态的改变

- (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源码地址:https://github.com/WZBbiao/WZBSwitch

三、一个仿网易的Segment

1、效果:


2、使用方法:

将WZBSegmentedControl.h和WZBSegmentedControl.m拖入工程

在需要使用的地方调用

/** 初始化方法

*  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、实现大致原理:

此控件还不是很完善,目前只提供一个初始化方法:

/* 初始化方法

* frame:控件frame

* titleClick:点击title的时候block回调

**/

+ (instancetype)segmentWithFrame:(CGRect)frame titles:(NSArray *)titles titleClick:(void(^)(NSInteger index))titleClick;

- (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源码地址:https://github.com/WZBbiao/WZBSegmentedControl

怎么样,这些您学会怎么用了吗?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • { 11、核心动画 需要签协议,但是系统帮签好 一、CABasicAnimation 1、创建基础动画对象 CAB...
    CYC666阅读 1,526评论 2 4
  • 工作了两年多,一直有个“坏习惯”,就是将工作中遇到的一些问题、技巧或心得记在印象笔记里面,按理来说,作为一个...
    F森阅读 1,981评论 3 26
  • 实现自定义分段控件 相关属性声明 封装初始化类方法。调用初始化方法传入参数:需要设定的整个控件的frame 以及 ...
    WeiHing阅读 6,631评论 0 8
  • 一个人在一线城市拥有十几套房产,是什么感觉?第一反应,土豪啊!这辈子可以不用每天挤地下移动车厢去上班了!还可以随...
    喵喵夏天叫阅读 846评论 0 0
  • 3/30|写手圈30天连续写作训练营| 【读书】早期教育杂志 【读书感悟】幼儿在各种活动中都是以我们意想不到的方式...
    如小茹阅读 152评论 0 1