前言
-
UISlider
控件的常規(guī)使用想必大家在日常iOS開發(fā)中用的肯定是非常熟練了,其使用場(chǎng)景也比較廣泛儒士,比如:音量大小
,字體大小
檩坚,背光亮度
着撩,播放進(jìn)度
,拍照縮放
等等匾委。最近拖叙,筆者在做自定義相機(jī)功能模塊中,就用UISlider
控件來做拍照縮放
的功能赂乐,主要是自定義UISlider
薯鳍,都是利用大家不常用到的API來實(shí)現(xiàn)的,有興趣的童鞋可以看看挨措。 - 本文將著重講解
UISlider
的使用挖滤,希望大家在看完本篇文章后,能夠?qū)?code>UISlider有新的認(rèn)識(shí)浅役,真正運(yùn)用到實(shí)際項(xiàng)目開發(fā)中去斩松,爭(zhēng)取玩轉(zhuǎn)UISlider
。文章僅供大家參考觉既,若有不妥之處惧盹,還望不吝賜教,歡迎批評(píng)指正瞪讼。
效果圖
常規(guī)操作
平常開發(fā)中钧椰,我們可以利用UISlider
提供的相關(guān)屬性和API可以實(shí)現(xiàn)大部分的需求,話不多說符欠,這里筆者先講講各個(gè)屬性和API的使用嫡霞。
- Property & API
這個(gè)值是介于滑塊的最大值和最小值之間的,如果沒有設(shè)置邊界值背亥,默認(rèn)為0-1秒际;
@property(nonatomic) float value;
設(shè)置滑塊最小邊界值(默認(rèn)為0)
@property(nonatomic) float minimumValue;
設(shè)置滑塊最大邊界值(默認(rèn)為1)
@property(nonatomic) float maximumValue;
設(shè)置滑塊最左端顯示的圖片:
@property(nonatomic,retain) UIImage *minimumValueImage;
設(shè)置滑塊最右端顯示的圖片:
@property(nonatomic,retain) UIImage *maximumValueImage;
設(shè)置滑塊值是否連續(xù)變化(默認(rèn)為YES),這個(gè)屬性設(shè)置為YES則在滑動(dòng)時(shí)狡汉,其value就會(huì)隨時(shí)變化娄徊,設(shè)置為NO,則當(dāng)滑動(dòng)結(jié)束時(shí)盾戴,value才會(huì)改變寄锐。
@property(nonatomic,getter=isContinuous) BOOL continuous;
設(shè)置滑塊左邊(小于部分)線條的顏色
@property(nonatomic,retain) UIColor *minimumTrackTintColor;
設(shè)置滑塊右邊(大于部分)線條的顏色
@property(nonatomic,retain) UIColor *maximumTrackTintColor;
設(shè)置滑塊顏色(影響已劃過一端的顏色)
注意這個(gè)屬性:如果你沒有設(shè)置滑塊的圖片橄仆,那個(gè)這個(gè)屬性將只會(huì)改變已劃過一段線條的顏色剩膘,不會(huì)改變滑塊的顏色,如果你設(shè)置了滑塊的圖片盆顾,又設(shè)置了這個(gè)屬性怠褐,那么滑塊的圖片將不顯示,滑塊的顏色會(huì)改變(IOS7)
@property(nonatomic,retain) UIColor *thumbTintColor您宪;
手動(dòng)設(shè)置滑塊的值:
- (void)setValue:(float)value animated:(BOOL)animated;
設(shè)置滑塊的圖片:
- (void)setThumbImage:(UIImage *)image forState:(UIControlState)state;
設(shè)置滑塊劃過部分的線條圖案
- (void)setMinimumTrackImage:(UIImage *)image forState:(UIControlState)state;
設(shè)置滑塊未劃過部分的線條圖案
- (void)setMaximumTrackImage:(UIImage *)image forState:(UIControlState)state;
對(duì)應(yīng)的幾個(gè)get方法
- (UIImage *)thumbImageForState:(UIControlState)state;
- (UIImage *)minimumTrackImageForState:(UIControlState)state;
- (UIImage *)maximumTrackImageForState:(UIControlState)state;
對(duì)應(yīng)的設(shè)置當(dāng)前狀態(tài)的響應(yīng)屬性的方法
@property(nonatomic,readonly) UIImage* currentThumbImage;
@property(nonatomic,readonly) UIImage* currentMinimumTrackImage;
@property(nonatomic,readonly) UIImage* currentMaximumTrackImage;
添加觸發(fā)事件
[slider addTarget:self action:@selector(log:) forControlEvents:UIControlEventValueChanged];
比較常用的屬性以及作用如下圖所示:
- Usage
#pragma mark - 常規(guī)操作
- (void)_generalOperations{
/// 創(chuàng)建Slider 設(shè)置Frame
UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake((MH_SCREEN_WIDTH - 247) * .5f, MH_SCREEN_HEIGHT*.5f- 50*.5f, 247, 50)];
self.slider = slider;
/// 添加Slider
[self.view addSubview:slider];
/// 屬性配置
// minimumValue : 當(dāng)值可以改變時(shí)奈懒,滑塊可以滑動(dòng)到最小位置的值,默認(rèn)為0.0
slider.minimumValue = 0.0;
// maximumValue : 當(dāng)值可以改變時(shí)宪巨,滑塊可以滑動(dòng)到最大位置的值磷杏,默認(rèn)為1.0
slider.maximumValue = 100.0;
// 當(dāng)前值,這個(gè)值是介于滑塊的最大值和最小值之間的捏卓,如果沒有設(shè)置邊界值极祸,默認(rèn)為0-1;
slider.value = 50;
// continuous : 如果設(shè)置YES怠晴,在拖動(dòng)滑塊的任何時(shí)候遥金,滑塊的值都會(huì)改變。默認(rèn)設(shè)置為YES
[slider setContinuous:YES];
UIImage * minimumValueImage = MHImageNamed(@"zoom-");
UIImage * maximumValueImage = MHImageNamed(@"zoom+");
// 滑塊條最小值處設(shè)置的圖片龄寞,默認(rèn)為nil
slider.minimumValueImage = minimumValueImage;
// 滑塊條最大值處設(shè)置的圖片汰规,默認(rèn)為nil
slider.maximumValueImage = maximumValueImage;
// minimumTrackTintColor : 小于滑塊當(dāng)前值滑塊條的顏色,默認(rèn)為藍(lán)色
slider.minimumTrackTintColor = [UIColor redColor];
// maximumTrackTintColor: 大于滑塊當(dāng)前值滑塊條的顏色物邑,默認(rèn)為白色
slider.maximumTrackTintColor = [UIColor blueColor];
// thumbTintColor : 當(dāng)前滑塊的顏色溜哮,默認(rèn)為白色
slider.thumbTintColor = [UIColor yellowColor];
// minimumTrackTintColor : 小于滑塊當(dāng)前值滑塊條的顏色,默認(rèn)為藍(lán)色
slider.minimumTrackTintColor = [UIColor redColor];
// maximumTrackTintColor: 大于滑塊當(dāng)前值滑塊條的顏色色解,默認(rèn)為白色
slider.maximumTrackTintColor = [UIColor blueColor];
// thumbTintColor : 當(dāng)前滑塊的顏色茂嗓,默認(rèn)為白色
slider.thumbTintColor = [UIColor yellowColor];
/** PS: 設(shè)置圖片的優(yōu)先級(jí)高于設(shè)置tintColor
/// 設(shè)置滑塊條最大值處設(shè)置的圖片在不同的狀態(tài)
[slider setMaximumTrackImage:MHImageNamed(@"slider_bg") forState:UIControlStateNormal];
/// 設(shè)置滑塊條最小值處設(shè)置的圖片在不同的狀態(tài)
[slider setMinimumTrackImage:MHImageNamed(@"slider_bg") forState:UIControlStateNormal];
/// 設(shè)置滑塊圖片在不同的狀態(tài)
[slider setThumbImage:MHImageNamed(@"slider_thumb") forState:UIControlStateNormal];
[slider setThumbImage:MHImageNamed(@"slider_thumb") forState:UIControlStateHighlighted];
*/
/// currentMaximumTrackImage : 當(dāng)前(狀態(tài))滑塊條最大值處設(shè)置的圖片
/// currentMinimumTrackImage : 當(dāng)前(狀態(tài))滑塊條最小值處設(shè)置的圖片
/// currentThumbImage: 當(dāng)前(狀態(tài))滑塊的圖片
/// - (nullable UIImage *)thumbImageForState:(UIControlState)state; /// 獲取某個(gè)(狀態(tài))滑塊的圖片
/// - (nullable UIImage *)minimumTrackImageForState:(UIControlState)state; /// 獲取某個(gè)(狀態(tài))滑塊條最小值處設(shè)置的圖片
/// - (nullable UIImage *)maximumTrackImageForState:(UIControlState)state; /// 獲取某個(gè)(狀態(tài))滑塊條最大值處設(shè)置的圖片
/// 事件監(jiān)聽
[slider addTarget:self action:@selector(_sliderValueDidChanged:) forControlEvents:UIControlEventValueChanged];
/// label
UILabel *lb = [UILabel mh_labelWithText:@"常規(guī)操作" fontSize:16 textColor:[UIColor whiteColor]];
lb.textAlignment = NSTextAlignmentRight;
[self.view addSubview:lb];
CGFloat lbX = 0;
CGFloat lbY = CGRectGetMinY(slider.frame);
CGFloat lbW = CGRectGetMinX(slider.frame) - 20;
CGFloat lbH = CGRectGetHeight(slider.frame);
lb.frame = CGRectMake(lbX, lbY, lbW, lbH);
}
效果圖如下:
另類操作
常規(guī)操作想必大家都比較熟練,但是有些時(shí)候我們需要自定義UISlider
內(nèi)部的子控件的大小或位置等科阎。首先我們先看看UISlider
的子控件視圖層級(jí)結(jié)構(gòu)述吸,如下所示:
如果大家對(duì)其層級(jí)不了解的話,就會(huì)手忙腳亂锣笨,不知從何下手蝌矛,以至于會(huì)直接棄用UISlider
控件,自己重新自定義UIView
來實(shí)現(xiàn)错英,很明顯這就是對(duì)UISlider
的使用不夠熟練導(dǎo)致的入撒,因?yàn)?code>UISlider已經(jīng)提供了相關(guān)的API,只要子類重寫相關(guān)API來實(shí)現(xiàn)子控件的Rect
椭岩。
- API
// 子類重寫
/// 設(shè)置minimumValueImage的rect
- (CGRect)minimumValueImageRectForBounds:(CGRect)bounds;
/// 設(shè)置maximumValueImage的rect
- (CGRect)maximumValueImageRectForBounds:(CGRect)bounds;
/// 設(shè)置track(滑條)尺寸
- (CGRect)trackRectForBounds:(CGRect)bounds;
/// 設(shè)置thumb(滑塊)尺寸
- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value;
關(guān)于這幾個(gè)API的作用如下:
- Usage
#pragma mark - 另類操作
- (void)_alternativeOperation{
MHCameraZoomSlider *slider = [[MHCameraZoomSlider alloc] init];
slider.hidden = YES;
[self.view addSubview:slider];
/// 逆時(shí)針旋轉(zhuǎn)90度
slider.transform = CGAffineTransformMakeRotation(-M_PI_2);
/// 事件監(jiān)聽
[slider addTarget:self action:@selector(_sliderValueDidChanged:) forControlEvents:UIControlEventValueChanged];
/// 設(shè)置Frame
CGFloat sliderW = 247;
CGFloat sliderH = 36;
CGFloat sliderX = (self.view.mh_width - sliderH) *.5f;
CGFloat sliderY = CGRectGetMaxY(self.slider.frame) + 100;
slider.frame = CGRectMake(sliderX, sliderY, sliderH, sliderW);
/// label
UILabel *lb = [UILabel mh_labelWithText:@"另類操作" fontSize:16 textColor:[UIColor whiteColor]];
lb.textAlignment = NSTextAlignmentRight;
[self.view addSubview:lb];
CGFloat lbX = 0;
CGFloat lbY = 0;
CGFloat lbW = CGRectGetMinX(self.slider.frame) - 20;
CGFloat lbH = 40;
lb.frame = CGRectMake(lbX, lbY, lbW, lbH);
lb.mh_centerY = slider.mh_centerY;
}
MHCameraZoomSlider.m 內(nèi)容如下:
#import "MHCameraZoomSlider.h"
@interface MHCameraZoomSlider ()
/// 是否設(shè)置過layer
@property (nonatomic , readwrite , assign) BOOL didSetLayer;
@end
@implementation MHCameraZoomSlider
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
// 初始化
[self _setup];
// 創(chuàng)建自控制器
[self _setupSubViews];
// 布局子控件
[self _makeSubViewsConstraints];
}
return self;
}
#pragma mark - 事件處理Or輔助方法
#pragma mark - Private Method
- (void)_setup{
self.minimumValue = 1;
self.maximumValue = 5;
}
#pragma mark - 創(chuàng)建自控制器
- (void)_setupSubViews
{
self.minimumTrackTintColor = [[UIColor whiteColor] colorWithAlphaComponent:.4];
self.maximumTrackTintColor = self.minimumTrackTintColor;
UIImage * minimumValueImage = MHImageNamed(@"zoom-");
self.minimumValueImage = [minimumValueImage imageByRotateRight90];
UIImage * maximumValueImage = MHImageNamed(@"zoom+");
self.maximumValueImage = [maximumValueImage imageByRotateRight90];
UIImage *norImage = MHImageNamed(@"slider_dot");
UIImage *highImage = MHImageNamed(@"slider_dot_pressed");
/// 圖片合成
UIGraphicsBeginImageContextWithOptions(highImage.size , NO, highImage.scale);
[highImage drawInRect:CGRectMake(0, 0, highImage.size.width, highImage.size.height)];
CGFloat w = norImage.size.width;
CGFloat h = norImage.size.height;
CGFloat x = (highImage.size.width - w) * .5f;
CGFloat y = (highImage.size.height - h) * .5f;
[norImage drawInRect:CGRectMake(x, y, w, h) withContentMode:UIViewContentModeScaleAspectFit clipsToBounds:NO];
highImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self setThumbImage:norImage forState:UIControlStateNormal];
[self setThumbImage:highImage forState:UIControlStateHighlighted];
}
#pragma mark - 布局子控件
- (void)_makeSubViewsConstraints{
}
#pragma mark - Override
/// 設(shè)置minimumValueImage的rect
- (CGRect)minimumValueImageRectForBounds:(CGRect)bounds{
CGFloat X = 0;
CGFloat H = 21;
CGFloat Y =( bounds.size.height - H ) *.5f;
CGFloat W = H;
return CGRectMake(X, Y, W, H);
}
/// 設(shè)置maximumValueImage的rect
- (CGRect)maximumValueImageRectForBounds:(CGRect)bounds{
CGFloat H = 21;
CGFloat Y =( bounds.size.height - H ) *.5f;
CGFloat W = H;
CGFloat X = bounds.size.width - W;
return CGRectMake(X, Y, W, H);
}
/// 設(shè)置track(滑條)尺寸
- (CGRect)trackRectForBounds:(CGRect)bounds{
CGRect minimumValueImageRect = [self minimumValueImageRectForBounds:bounds];
CGRect maximumValueImageRect = [self maximumValueImageRectForBounds:bounds];
CGFloat margin = 2;
CGFloat H = 6;
CGFloat Y =( bounds.size.height - H ) *.5f;
CGFloat X = CGRectGetMaxX(minimumValueImageRect) + margin;
CGFloat W = CGRectGetMinX(maximumValueImageRect) - X - margin;
return CGRectMake(X, Y, W, H);
}
/// 設(shè)置thumb(滑塊)尺寸
- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value{
CGFloat WH = 30;
CGFloat margin = WH *.5f - 21 *.5f + 2;
/// 滑塊的滑動(dòng)區(qū)域?qū)挾? CGFloat maxWidth = CGRectGetWidth(rect) + 2 * margin;
/// 每次偏移量
CGFloat offset = (maxWidth - WH)/(self.maximumValue - self.minimumValue);
CGFloat H = WH;
CGFloat Y = (bounds.size.height - H ) *.5f;
CGFloat W = H;
CGFloat X = CGRectGetMinX(rect) - margin + offset *(value-self.minimumValue);
CGRect r = CGRectMake(X, Y, W, H);
return r;
}
#pragma mark - 布局
- (void)layoutSubviews{
[super layoutSubviews];
if (self.didSetLayer) {
return;
}
BOOL didSetLayer = NO;
for (UIView *v in self.subviews) {
if (v.mh_height <= 6 && self.mh_height > 0) {
v.layer.borderWidth = 0.5f;
v.layer.borderColor = MHColorFromHexString(@"#2C2E30").CGColor;
v.layer.cornerRadius = MHConvertToFitPt(6) *.5f;
v.layer.masksToBounds = YES;
didSetLayer = YES;
}
}
self.didSetLayer = didSetLayer;
}
@end
效果圖如下:
以上就是筆者實(shí)際項(xiàng)目中用于拍照放大縮小的小控件(MHCameraZoomSlider
)茅逮,相比于自定義UIView
來實(shí)現(xiàn)的話璃赡,這種重寫的方法是不是會(huì)更加簡(jiǎn)單、高效献雅。其實(shí)平常開發(fā)中我們都可以在系統(tǒng)提供的控件基礎(chǔ)上碉考,去進(jìn)行修改和調(diào)整,而不是一味地去自定義UIView
挺身『钏總之,多多熟練章钾,百煉成鋼良蒸。
期待
- 文章若對(duì)您有些許幫助,請(qǐng)給個(gè)喜歡??伍玖,畢竟碼字不易;若對(duì)您沒啥幫助剿吻,請(qǐng)給點(diǎn)建議??窍箍,切記學(xué)無止境。
- 針對(duì)文章所述內(nèi)容丽旅,閱讀期間任何疑問椰棘;請(qǐng)?jiān)谖恼碌撞吭u(píng)論指出,我會(huì)火速解決和修正問題榄笙。
- GitHub地址:https://github.com/CoderMikeHe