口袋优选

SGPageTitleView.m 40KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. //
  2. // 如遇到问题或有更好方案,请通过以下方式进行联系
  3. // QQ群:429899752
  4. // Email:kingsic@126.com
  5. // GitHub:https://github.com/kingsic/SGPagingView
  6. //
  7. // SGPageTitleView.m
  8. // SGPagingViewExample
  9. //
  10. // Created by kingsic on 17/4/10.
  11. // Copyright © 2017年 kingsic. All rights reserved.
  12. //
  13. #import "SGPageTitleView.h"
  14. #import "UIView+SGPagingView.h"
  15. #import "SGPageTitleViewConfigure.h"
  16. #define SGPageTitleViewWidth self.frame.size.width
  17. #define SGPageTitleViewHeight self.frame.size.height
  18. #pragma mark - - - SGPageTitleButton
  19. @interface SGPageTitleButton : UIButton
  20. @end
  21. @implementation SGPageTitleButton
  22. - (void)setHighlighted:(BOOL)highlighted {
  23. }
  24. @end
  25. #pragma mark - - - SGPageTitleView
  26. @interface SGPageTitleView ()
  27. /// SGPageTitleViewDelegate
  28. @property (nonatomic, weak) id<SGPageTitleViewDelegate> delegatePageTitleView;
  29. /// SGPageTitleView 配置信息
  30. @property (nonatomic, readwrite, strong) SGPageTitleViewConfigure *configure;
  31. /// scrollView
  32. @property (nonatomic, strong) UIScrollView *scrollView;
  33. /// 指示器
  34. @property (nonatomic, strong) UIView *indicatorView;
  35. /// 底部分割线
  36. @property (nonatomic, strong) UIView *bottomSeparator;
  37. /// 保存外界传递过来的标题数组
  38. @property (nonatomic, strong) NSArray *titleArr;
  39. /// 存储标题按钮的数组
  40. @property (nonatomic, strong) NSMutableArray *btnMArr;
  41. /// tempBtn
  42. @property (nonatomic, strong) UIButton *tempBtn;
  43. /// 记录所有按钮文字宽度
  44. @property (nonatomic, assign) CGFloat allBtnTextWidth;
  45. /// 记录所有子控件的宽度
  46. @property (nonatomic, assign) CGFloat allBtnWidth;
  47. /// 标记按钮下标
  48. @property (nonatomic, assign) NSInteger signBtnIndex;
  49. /// 开始颜色, 取值范围 0~1
  50. @property (nonatomic, assign) CGFloat startR;
  51. @property (nonatomic, assign) CGFloat startG;
  52. @property (nonatomic, assign) CGFloat startB;
  53. /// 完成颜色, 取值范围 0~1
  54. @property (nonatomic, assign) CGFloat endR;
  55. @property (nonatomic, assign) CGFloat endG;
  56. @property (nonatomic, assign) CGFloat endB;
  57. @end
  58. @implementation SGPageTitleView
  59. - (instancetype)initWithFrame:(CGRect)frame delegate:(id<SGPageTitleViewDelegate>)delegate titleNames:(NSArray *)titleNames configure:(SGPageTitleViewConfigure *)configure {
  60. if (self = [super initWithFrame:frame]) {
  61. self.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.77];
  62. if (delegate == nil) {
  63. @throw [NSException exceptionWithName:@"SGPagingView" reason:@"SGPageTitleView 的代理方法必须设置" userInfo:nil];
  64. }
  65. self.delegatePageTitleView = delegate;
  66. if (titleNames == nil) {
  67. @throw [NSException exceptionWithName:@"SGPagingView" reason:@"SGPageTitleView 的标题数组必须设置" userInfo:nil];
  68. }
  69. self.titleArr = titleNames;
  70. if (configure == nil) {
  71. @throw [NSException exceptionWithName:@"SGPagingView" reason:@"SGPageTitleView 的配置属性必须设置" userInfo:nil];
  72. }
  73. self.configure = configure;
  74. [self initialization];
  75. [self setupSubviews];
  76. }
  77. return self;
  78. }
  79. + (instancetype)pageTitleViewWithFrame:(CGRect)frame delegate:(id<SGPageTitleViewDelegate>)delegate titleNames:(NSArray *)titleNames configure:(SGPageTitleViewConfigure *)configure {
  80. return [[self alloc] initWithFrame:frame delegate:delegate titleNames:titleNames configure:configure];
  81. }
  82. - (void)initialization {
  83. _isTitleGradientEffect = YES;
  84. _isOpenTitleTextZoom = NO;
  85. _isShowIndicator = YES;
  86. _isNeedBounces = YES;
  87. _isShowBottomSeparator = YES;
  88. _selectedIndex = 0;
  89. _titleTextScaling = 0.1;
  90. }
  91. - (void)setupSubviews {
  92. // 0、处理偏移量
  93. UIView *tempView = [[UIView alloc] initWithFrame:CGRectZero];
  94. [self addSubview:tempView];
  95. // 1、添加 UIScrollView
  96. [self addSubview:self.scrollView];
  97. // 2、添加标题按钮
  98. [self setupTitleButtons];
  99. // 3、添加底部分割线
  100. [self addSubview:self.bottomSeparator];
  101. // 4、添加指示器
  102. [self.scrollView insertSubview:self.indicatorView atIndex:0];
  103. }
  104. #pragma mark - - - layoutSubviews
  105. - (void)layoutSubviews {
  106. [super layoutSubviews];
  107. // 选中按钮下标初始值
  108. UIButton *lastBtn = self.btnMArr.lastObject;
  109. if (lastBtn.tag >= _selectedIndex && _selectedIndex >= 0) {
  110. [self P_btn_action:self.btnMArr[_selectedIndex]];
  111. } else {
  112. return;
  113. }
  114. }
  115. #pragma mark - - - 懒加载
  116. - (NSArray *)titleArr {
  117. if (!_titleArr) {
  118. _titleArr = [NSArray array];
  119. }
  120. return _titleArr;
  121. }
  122. - (NSMutableArray *)btnMArr {
  123. if (!_btnMArr) {
  124. _btnMArr = [NSMutableArray array];
  125. }
  126. return _btnMArr;
  127. }
  128. - (UIScrollView *)scrollView {
  129. if (!_scrollView) {
  130. _scrollView = [[UIScrollView alloc] init];
  131. _scrollView.showsVerticalScrollIndicator = NO;
  132. _scrollView.showsHorizontalScrollIndicator = NO;
  133. _scrollView.alwaysBounceHorizontal = YES;
  134. _scrollView.frame = CGRectMake(0, 0, SGPageTitleViewWidth, SGPageTitleViewHeight);
  135. }
  136. return _scrollView;
  137. }
  138. - (UIView *)indicatorView {
  139. if (!_indicatorView) {
  140. _indicatorView = [[UIView alloc] init];
  141. if (self.configure.indicatorStyle == SGIndicatorStyleCover) {
  142. CGFloat tempIndicatorViewH = [self SG_heightWithString:[self.btnMArr[0] currentTitle] font:self.configure.titleFont];
  143. if (self.configure.indicatorHeight > self.SG_height) {
  144. _indicatorView.SG_y = 0;
  145. _indicatorView.SG_height = self.SG_height;
  146. } else if (self.configure.indicatorHeight < tempIndicatorViewH) {
  147. _indicatorView.SG_y = 0.5 * (self.SG_height - tempIndicatorViewH);
  148. _indicatorView.SG_height = tempIndicatorViewH;
  149. } else {
  150. _indicatorView.SG_y = 0.5 * (self.SG_height - self.configure.indicatorHeight);
  151. _indicatorView.SG_height = self.configure.indicatorHeight;
  152. }
  153. // 圆角处理
  154. if (self.configure.indicatorCornerRadius > 0.5 * _indicatorView.SG_height) {
  155. _indicatorView.layer.cornerRadius = 0.5 * _indicatorView.SG_height;
  156. } else {
  157. _indicatorView.layer.cornerRadius = self.configure.indicatorCornerRadius;
  158. }
  159. // 边框宽度及边框颜色
  160. _indicatorView.layer.borderWidth = self.configure.indicatorBorderWidth;
  161. _indicatorView.layer.borderColor = self.configure.indicatorBorderColor.CGColor;
  162. } else {
  163. CGFloat indicatorViewH = self.configure.indicatorHeight;
  164. _indicatorView.SG_height = indicatorViewH;
  165. _indicatorView.SG_y = self.SG_height - indicatorViewH;
  166. }
  167. _indicatorView.backgroundColor = self.configure.indicatorColor;
  168. }
  169. return _indicatorView;
  170. }
  171. - (UIView *)bottomSeparator {
  172. if (!_bottomSeparator) {
  173. _bottomSeparator = [[UIView alloc] init];
  174. CGFloat bottomSeparatorW = self.SG_width;
  175. CGFloat bottomSeparatorH = 0.5;
  176. CGFloat bottomSeparatorX = 0;
  177. CGFloat bottomSeparatorY = self.SG_height - bottomSeparatorH;
  178. _bottomSeparator.frame = CGRectMake(bottomSeparatorX, bottomSeparatorY, bottomSeparatorW, bottomSeparatorH);
  179. _bottomSeparator.backgroundColor = [UIColor lightGrayColor];
  180. }
  181. return _bottomSeparator;
  182. }
  183. #pragma mark - - - 计算字符串宽度
  184. - (CGFloat)SG_widthWithString:(NSString *)string font:(UIFont *)font {
  185. NSDictionary *attrs = @{NSFontAttributeName : font};
  186. return [string boundingRectWithSize:CGSizeMake(0, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width;
  187. }
  188. #pragma mark - - - 计算字符串高度
  189. - (CGFloat)SG_heightWithString:(NSString *)string font:(UIFont *)font {
  190. NSDictionary *attrs = @{NSFontAttributeName : font};
  191. return [string boundingRectWithSize:CGSizeMake(0, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.height;
  192. }
  193. #pragma mark - - - 添加标题按钮
  194. - (void)setupTitleButtons {
  195. // 计算所有按钮的文字宽度
  196. [self.titleArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  197. CGFloat tempWidth = [self SG_widthWithString:obj font:self.configure.titleFont];
  198. self.allBtnTextWidth += tempWidth;
  199. }];
  200. // 所有按钮文字宽度 + 按钮之间的间隔
  201. self.allBtnWidth = self.configure.spacingBetweenButtons * (self.titleArr.count + 1) + self.allBtnTextWidth;
  202. self.allBtnWidth = ceilf(self.allBtnWidth);
  203. NSInteger titleCount = self.titleArr.count;
  204. if (self.allBtnWidth <= self.bounds.size.width) { // SGPageTitleView 静止样式
  205. CGFloat btnY = 0;
  206. CGFloat btnW = SGPageTitleViewWidth / self.titleArr.count;
  207. CGFloat btnH = 0;
  208. if (self.configure.indicatorStyle == SGIndicatorStyleDefault) {
  209. btnH = SGPageTitleViewHeight - self.configure.indicatorHeight;
  210. } else {
  211. btnH = SGPageTitleViewHeight;
  212. }
  213. for (NSInteger index = 0; index < titleCount; index++) {
  214. SGPageTitleButton *btn = [[SGPageTitleButton alloc] init];
  215. CGFloat btnX = btnW * index;
  216. btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
  217. btn.tag = index;
  218. btn.titleLabel.font = self.configure.titleFont;
  219. [btn setTitle:self.titleArr[index] forState:(UIControlStateNormal)];
  220. [btn setTitleColor:self.configure.titleColor forState:(UIControlStateNormal)];
  221. [btn setTitleColor:self.configure.titleSelectedColor forState:(UIControlStateSelected)];
  222. [btn addTarget:self action:@selector(P_btn_action:) forControlEvents:(UIControlEventTouchUpInside)];
  223. [self.btnMArr addObject:btn];
  224. [self.scrollView addSubview:btn];
  225. [self setupStartColor:self.configure.titleColor];
  226. [self setupEndColor:self.configure.titleSelectedColor];
  227. }
  228. self.scrollView.contentSize = CGSizeMake(SGPageTitleViewWidth, SGPageTitleViewHeight);
  229. } else { // SGPageTitleView 滚动样式
  230. CGFloat btnX = 0;
  231. CGFloat btnY = 0;
  232. CGFloat btnH = 0;
  233. if (self.configure.indicatorStyle == SGIndicatorStyleDefault) {
  234. btnH = SGPageTitleViewHeight - self.configure.indicatorHeight;
  235. } else {
  236. btnH = SGPageTitleViewHeight;
  237. }
  238. for (NSInteger index = 0; index < titleCount; index++) {
  239. SGPageTitleButton *btn = [[SGPageTitleButton alloc] init];
  240. CGFloat btnW = [self SG_widthWithString:self.titleArr[index] font:self.configure.titleFont] + self.configure.spacingBetweenButtons;
  241. btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
  242. btnX = btnX + btnW;
  243. btn.tag = index;
  244. btn.titleLabel.font = self.configure.titleFont;
  245. [btn setTitle:self.titleArr[index] forState:(UIControlStateNormal)];
  246. [btn setTitleColor:self.configure.titleColor forState:(UIControlStateNormal)];
  247. [btn setTitleColor:self.configure.titleSelectedColor forState:(UIControlStateSelected)];
  248. [btn addTarget:self action:@selector(P_btn_action:) forControlEvents:(UIControlEventTouchUpInside)];
  249. [self.btnMArr addObject:btn];
  250. [self.scrollView addSubview:btn];
  251. [self setupStartColor:self.configure.titleColor];
  252. [self setupEndColor:self.configure.titleSelectedColor];
  253. }
  254. CGFloat scrollViewWidth = CGRectGetMaxX(self.scrollView.subviews.lastObject.frame);
  255. self.scrollView.contentSize = CGSizeMake(scrollViewWidth, SGPageTitleViewHeight);
  256. }
  257. }
  258. #pragma mark - - - 标题按钮的点击事件
  259. - (void)P_btn_action:(UIButton *)button {
  260. // 1、改变按钮的选择状态
  261. [self P_changeSelectedButton:button];
  262. // 2、滚动标题选中按钮居中
  263. if (self.allBtnWidth > SGPageTitleViewWidth) {
  264. [self P_selectedBtnCenter:button];
  265. }
  266. // 3、改变指示器的位置以及指示器宽度样式
  267. [self P_changeIndicatorViewLocationWithButton:button];
  268. // 4、pageTitleViewDelegate
  269. if ([self.delegatePageTitleView respondsToSelector:@selector(pageTitleView:selectedIndex:)]) {
  270. [self.delegatePageTitleView pageTitleView:self selectedIndex:button.tag];
  271. }
  272. // 5、标记按钮下标
  273. self.signBtnIndex = button.tag;
  274. }
  275. - (void)c_btn_action:(UIButton *)button {
  276. // 1、改变按钮的选择状态
  277. [self P_changeSelectedButton:button];
  278. // 2、滚动标题选中按钮居中
  279. if (self.allBtnWidth > SGPageTitleViewWidth) {
  280. [self P_selectedBtnCenter:button];
  281. }
  282. // 3、改变指示器的位置以及指示器宽度样式
  283. [self P_changeIndicatorViewLocationWithButton:button];
  284. // 4、pageTitleViewDelegate
  285. // 5、标记按钮下标
  286. self.signBtnIndex = button.tag;
  287. }
  288. #pragma mark - - - 改变按钮的选择状态
  289. - (void)P_changeSelectedButton:(UIButton *)button {
  290. if (self.tempBtn == nil) {
  291. button.selected = YES;
  292. self.tempBtn = button;
  293. } else if (self.tempBtn != nil && self.tempBtn == button){
  294. button.selected = YES;
  295. } else if (self.tempBtn != button && self.tempBtn != nil){
  296. self.tempBtn.selected = NO;
  297. button.selected = YES;
  298. self.tempBtn = button;
  299. }
  300. // 标题文字缩放属性
  301. if (self.isOpenTitleTextZoom) {
  302. [self.btnMArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  303. UIButton *btn = obj;
  304. btn.transform = CGAffineTransformMakeScale(1, 1);
  305. }];
  306. button.transform = CGAffineTransformMakeScale(1 + self.titleTextScaling, 1 + self.titleTextScaling);
  307. }
  308. }
  309. #pragma mark - - - 滚动标题选中按钮居中
  310. - (void)P_selectedBtnCenter:(UIButton *)centerBtn {
  311. // 计算偏移量
  312. CGFloat offsetX = centerBtn.center.x - SGPageTitleViewWidth * 0.5;
  313. if (offsetX < 0) offsetX = 0;
  314. // 获取最大滚动范围
  315. CGFloat maxOffsetX = self.scrollView.contentSize.width - SGPageTitleViewWidth;
  316. if (offsetX > maxOffsetX) offsetX = maxOffsetX;
  317. // 滚动标题滚动条
  318. [self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
  319. }
  320. #pragma mark - - - 改变指示器的位置以及指示器宽度样式
  321. - (void)P_changeIndicatorViewLocationWithButton:(UIButton *)button {
  322. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  323. if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
  324. self.indicatorView.SG_width = self.configure.indicatorFixedWidth;
  325. self.indicatorView.SG_centerX = button.SG_centerX;
  326. } else if (self.configure.indicatorStyle == SGIndicatorStyleDynamic) {
  327. self.indicatorView.SG_width = self.configure.indicatorDynamicWidth;
  328. self.indicatorView.SG_centerX = button.SG_centerX;
  329. } else {
  330. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:button.currentTitle font:self.configure.titleFont];
  331. if (tempIndicatorWidth > button.SG_width) {
  332. tempIndicatorWidth = button.SG_width;
  333. }
  334. self.indicatorView.SG_width = tempIndicatorWidth;
  335. self.indicatorView.SG_centerX = button.SG_centerX;
  336. }
  337. }];
  338. }
  339. #pragma mark - - - 给外界提供的方法
  340. - (void)setPageTitleViewWithProgress:(CGFloat)progress originalIndex:(NSInteger)originalIndex targetIndex:(NSInteger)targetIndex {
  341. // 1、取出 originalBtn/targetBtn
  342. UIButton *originalBtn = self.btnMArr[originalIndex];
  343. UIButton *targetBtn = self.btnMArr[targetIndex];
  344. self.signBtnIndex = targetBtn.tag;
  345. // 2、 滚动标题选中居中
  346. [self P_selectedBtnCenter:targetBtn];
  347. // 3、处理指示器的逻辑
  348. if (self.allBtnWidth <= self.bounds.size.width) { /// SGPageTitleView 不可滚动
  349. if (self.configure.indicatorScrollStyle == SGIndicatorScrollStyleDefault) {
  350. [self P_smallIndicatorScrollStyleDefaultWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
  351. } else {
  352. [self P_smallIndicatorScrollStyleHalfEndWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
  353. }
  354. } else { /// SGPageTitleView 可滚动
  355. if (self.configure.indicatorScrollStyle == SGIndicatorScrollStyleDefault) {
  356. [self P_indicatorScrollStyleDefaultWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
  357. } else {
  358. [self P_indicatorScrollStyleHalfEndWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
  359. }
  360. }
  361. // 4、颜色的渐变(复杂)
  362. if (self.isTitleGradientEffect) {
  363. [self P_isTitleGradientEffectWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
  364. }
  365. // 5 、标题文字缩放属性
  366. if (self.isOpenTitleTextZoom) {
  367. // 左边缩放
  368. originalBtn.transform = CGAffineTransformMakeScale((1 - progress) * self.titleTextScaling + 1, (1 - progress) * self.titleTextScaling + 1);
  369. // 右边缩放
  370. targetBtn.transform = CGAffineTransformMakeScale(progress * self.titleTextScaling + 1, progress * self.titleTextScaling + 1);
  371. }
  372. }
  373. /**
  374. * 根据下标重置标题文字
  375. *
  376. * @param index 标题所对应的下标
  377. * @param title 新标题名
  378. */
  379. - (void)resetTitleWithIndex:(NSInteger)index newTitle:(NSString *)title {
  380. if (index < self.btnMArr.count) {
  381. UIButton *button = (UIButton *)self.btnMArr[index];
  382. [button setTitle:title forState:UIControlStateNormal];
  383. if (self.signBtnIndex == index) {
  384. if (self.configure.indicatorStyle == SGIndicatorStyleDefault || self.configure.indicatorStyle == SGIndicatorStyleCover) {
  385. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:button.currentTitle font:self.configure.titleFont];
  386. if (tempIndicatorWidth > button.SG_width) {
  387. tempIndicatorWidth = button.SG_width;
  388. }
  389. self.indicatorView.SG_width = tempIndicatorWidth;
  390. self.indicatorView.SG_centerX = button.SG_centerX;
  391. }
  392. }
  393. }
  394. }
  395. #pragma mark - - - SGPageTitleView 静止样式下指示器默认滚动样式(SGIndicatorScrollStyleDefault)
  396. - (void)P_smallIndicatorScrollStyleDefaultWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
  397. // 1、改变按钮的选择状态
  398. if (progress >= 0.8) { /// 此处取 >= 0.8 而不是 1.0 为的是防止用户滚动过快而按钮的选中状态并没有改变
  399. [self P_changeSelectedButton:targetBtn];
  400. }
  401. if (self.configure.indicatorStyle == SGIndicatorStyleDynamic) {
  402. NSInteger originalBtnTag = originalBtn.tag;
  403. NSInteger targetBtnTag = targetBtn.tag;
  404. // 按钮之间的距离
  405. CGFloat distance = self.SG_width / self.titleArr.count;
  406. if (originalBtnTag <= targetBtnTag) { // 往左滑
  407. if (progress <= 0.5) {
  408. self.indicatorView.SG_width = self.configure.indicatorDynamicWidth + 2 * progress * distance;
  409. } else {
  410. CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - 0.5 * (distance - self.configure.indicatorDynamicWidth) - self.configure.indicatorDynamicWidth;
  411. self.indicatorView.SG_x = targetBtnIndicatorX + 2 * (progress - 1) * distance;
  412. self.indicatorView.SG_width = self.configure.indicatorDynamicWidth + 2 * (1 - progress) * distance;
  413. }
  414. } else {
  415. if (progress <= 0.5) {
  416. CGFloat originalBtnIndicatorX = CGRectGetMaxX(originalBtn.frame) - 0.5 * (distance - self.configure.indicatorDynamicWidth) - self.configure.indicatorDynamicWidth;
  417. self.indicatorView.SG_x = originalBtnIndicatorX - 2 * progress * distance;
  418. self.indicatorView.SG_width = self.configure.indicatorDynamicWidth + 2 * progress * distance;
  419. } else {
  420. CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - self.configure.indicatorDynamicWidth - 0.5 * (distance - self.configure.indicatorDynamicWidth);
  421. self.indicatorView.SG_x = targetBtnIndicatorX; // 这句代码必须写,防止滚动结束之后指示器位置存在偏差,这里的偏差是由于 progress >= 0.8 导致的
  422. self.indicatorView.SG_width = self.configure.indicatorDynamicWidth + 2 * (1 - progress) * distance;
  423. }
  424. }
  425. } else if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
  426. CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - 0.5 * (self.SG_width / self.titleArr.count - self.configure.indicatorFixedWidth) - self.configure.indicatorFixedWidth;
  427. CGFloat originalBtnIndicatorX = CGRectGetMaxX(originalBtn.frame) - 0.5 * (self.SG_width / self.titleArr.count - self.configure.indicatorFixedWidth) - self.configure.indicatorFixedWidth;
  428. CGFloat totalOffsetX = targetBtnIndicatorX - originalBtnIndicatorX;
  429. self.indicatorView.SG_x = originalBtnIndicatorX + progress * totalOffsetX;
  430. } else {
  431. /// 1、计算 indicator 偏移量
  432. // targetBtn 文字宽度
  433. CGFloat targetBtnTextWidth = [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
  434. CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - targetBtnTextWidth - 0.5 * (self.SG_width / self.titleArr.count - targetBtnTextWidth + self.configure.indicatorAdditionalWidth);
  435. // originalBtn 文字宽度
  436. CGFloat originalBtnTextWidth = [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
  437. CGFloat originalBtnIndicatorX = CGRectGetMaxX(originalBtn.frame) - originalBtnTextWidth - 0.5 * (self.SG_width / self.titleArr.count - originalBtnTextWidth + self.configure.indicatorAdditionalWidth);
  438. CGFloat totalOffsetX = targetBtnIndicatorX - originalBtnIndicatorX;
  439. /// 2、计算文字之间差值
  440. // 按钮宽度的距离
  441. CGFloat btnWidth = self.SG_width / self.titleArr.count;
  442. // targetBtn 文字右边的 x 值
  443. CGFloat targetBtnRightTextX = CGRectGetMaxX(targetBtn.frame) - 0.5 * (btnWidth - targetBtnTextWidth);
  444. // originalBtn 文字右边的 x 值
  445. CGFloat originalBtnRightTextX = CGRectGetMaxX(originalBtn.frame) - 0.5 * (btnWidth - originalBtnTextWidth);
  446. CGFloat totalRightTextDistance = targetBtnRightTextX - originalBtnRightTextX;
  447. // 计算 indicatorView 滚动时 x 的偏移量
  448. CGFloat offsetX = totalOffsetX * progress;
  449. // 计算 indicatorView 滚动时文字宽度的偏移量
  450. CGFloat distance = progress * (totalRightTextDistance - totalOffsetX);
  451. /// 3、计算 indicatorView 新的 frame
  452. self.indicatorView.SG_x = originalBtnIndicatorX + offsetX;
  453. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + originalBtnTextWidth + distance;
  454. if (tempIndicatorWidth >= targetBtn.SG_width) {
  455. CGFloat moveTotalX = targetBtn.SG_origin.x - originalBtn.SG_origin.x;
  456. CGFloat moveX = moveTotalX * progress;
  457. self.indicatorView.SG_centerX = originalBtn.SG_centerX + moveX;
  458. } else {
  459. self.indicatorView.SG_width = tempIndicatorWidth;
  460. }
  461. }
  462. }
  463. #pragma mark - - - SGPageTitleView 滚动样式下指示器默认滚动样式(SGIndicatorScrollStyleDefault)
  464. - (void)P_indicatorScrollStyleDefaultWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
  465. /// 改变按钮的选择状态
  466. if (progress >= 0.8) { /// 此处取 >= 0.8 而不是 1.0 为的是防止用户滚动过快而按钮的选中状态并没有改变
  467. [self P_changeSelectedButton:targetBtn];
  468. }
  469. if (self.configure.indicatorStyle == SGIndicatorStyleDynamic) {
  470. NSInteger originalBtnTag = originalBtn.tag;
  471. NSInteger targetBtnTag = targetBtn.tag;
  472. if (originalBtnTag <= targetBtnTag) { // 往左滑
  473. // targetBtn 与 originalBtn 中心点之间的距离
  474. CGFloat btnCenterXDistance = targetBtn.SG_centerX - originalBtn.SG_centerX;
  475. if (progress <= 0.5) {
  476. self.indicatorView.SG_width = 2 * progress * btnCenterXDistance + self.configure.indicatorDynamicWidth;
  477. } else {
  478. CGFloat targetBtnX = CGRectGetMaxX(targetBtn.frame) - self.configure.indicatorDynamicWidth - 0.5 * (targetBtn.SG_width - self.configure.indicatorDynamicWidth);
  479. self.indicatorView.SG_x = targetBtnX + 2 * (progress - 1) * btnCenterXDistance;
  480. self.indicatorView.SG_width = 2 * (1 - progress) * btnCenterXDistance + self.configure.indicatorDynamicWidth;
  481. }
  482. } else {
  483. // originalBtn 与 targetBtn 中心点之间的距离
  484. CGFloat btnCenterXDistance = originalBtn.SG_centerX - targetBtn.SG_centerX;
  485. if (progress <= 0.5) {
  486. CGFloat originalBtnX = CGRectGetMaxX(originalBtn.frame) - self.configure.indicatorDynamicWidth - 0.5 * (originalBtn.SG_width - self.configure.indicatorDynamicWidth);
  487. self.indicatorView.SG_x = originalBtnX - 2 * progress * btnCenterXDistance;
  488. self.indicatorView.SG_width = 2 * progress * btnCenterXDistance + self.configure.indicatorDynamicWidth;
  489. } else {
  490. CGFloat targetBtnX = CGRectGetMaxX(targetBtn.frame) - self.configure.indicatorDynamicWidth - 0.5 * (targetBtn.SG_width - self.configure.indicatorDynamicWidth);
  491. self.indicatorView.SG_x = targetBtnX; // 这句代码必须写,防止滚动结束之后指示器位置存在偏差,这里的偏差是由于 progress >= 0.8 导致的
  492. self.indicatorView.SG_width = 2 * (1 - progress) * btnCenterXDistance + self.configure.indicatorDynamicWidth;
  493. }
  494. }
  495. } else if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
  496. CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - 0.5 * (targetBtn.SG_width - self.configure.indicatorFixedWidth) - self.configure.indicatorFixedWidth;
  497. CGFloat originalBtnIndicatorX = CGRectGetMaxX(originalBtn.frame) - self.configure.indicatorFixedWidth - 0.5 * (originalBtn.SG_width - self.configure.indicatorFixedWidth);
  498. CGFloat totalOffsetX = targetBtnIndicatorX - originalBtnIndicatorX;
  499. CGFloat offsetX = totalOffsetX * progress;
  500. self.indicatorView.SG_x = originalBtnIndicatorX + offsetX;
  501. } else {
  502. // 1、计算 targetBtn/originalBtn 之间的 x 差值
  503. CGFloat totalOffsetX = targetBtn.SG_origin.x - originalBtn.SG_origin.x;
  504. // 2、计算 targetBtn/originalBtn 之间的差值
  505. CGFloat totalDistance = CGRectGetMaxX(targetBtn.frame) - CGRectGetMaxX(originalBtn.frame);
  506. /// 计算 indicatorView 滚动时 x 的偏移量
  507. CGFloat offsetX = 0.0;
  508. /// 计算 indicatorView 滚动时宽度的偏移量
  509. CGFloat distance = 0.0;
  510. CGFloat targetBtnTextWidth = [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
  511. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + targetBtnTextWidth;
  512. if (tempIndicatorWidth >= targetBtn.SG_width) {
  513. offsetX = totalOffsetX * progress;
  514. distance = progress * (totalDistance - totalOffsetX);
  515. self.indicatorView.SG_x = originalBtn.SG_origin.x + offsetX;
  516. self.indicatorView.SG_width = originalBtn.SG_width + distance;
  517. } else {
  518. offsetX = totalOffsetX * progress + 0.5 * self.configure.spacingBetweenButtons - 0.5 * self.configure.indicatorAdditionalWidth;
  519. distance = progress * (totalDistance - totalOffsetX) - self.configure.spacingBetweenButtons;
  520. /// 计算 indicatorView 新的 frame
  521. self.indicatorView.SG_x = originalBtn.SG_origin.x + offsetX;
  522. self.indicatorView.SG_width = originalBtn.SG_width + distance + self.configure.indicatorAdditionalWidth;
  523. }
  524. }
  525. }
  526. #pragma mark - - - SGPageTitleView 静止样式下指示器 SGIndicatorScrollStyleHalf 和 SGIndicatorScrollStyleEnd 滚动样式
  527. - (void)P_smallIndicatorScrollStyleHalfEndWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
  528. if (self.configure.indicatorScrollStyle == SGIndicatorScrollStyleHalf) {
  529. if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
  530. if (progress >= 0.5) {
  531. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  532. self.indicatorView.SG_centerX = targetBtn.SG_centerX;
  533. [self P_changeSelectedButton:targetBtn];
  534. }];
  535. } else {
  536. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  537. self.indicatorView.SG_centerX = originalBtn.SG_centerX;
  538. [self P_changeSelectedButton:originalBtn];
  539. }];
  540. }
  541. return;
  542. }
  543. /// 指示器默认样式以及遮盖样式处理
  544. if (progress >= 0.5) {
  545. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
  546. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  547. if (tempIndicatorWidth >= targetBtn.SG_width) {
  548. self.indicatorView.SG_width = targetBtn.SG_width;
  549. } else {
  550. self.indicatorView.SG_width = tempIndicatorWidth;
  551. }
  552. self.indicatorView.SG_centerX = targetBtn.SG_centerX;
  553. [self P_changeSelectedButton:targetBtn];
  554. }];
  555. } else {
  556. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
  557. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  558. if (tempIndicatorWidth >= targetBtn.SG_width) {
  559. self.indicatorView.SG_width = originalBtn.SG_width;
  560. } else {
  561. self.indicatorView.SG_width = tempIndicatorWidth;
  562. }
  563. self.indicatorView.SG_centerX = originalBtn.SG_centerX;
  564. [self P_changeSelectedButton:originalBtn];
  565. }];
  566. }
  567. return;
  568. }
  569. /// 滚动内容结束指示器处理 ____ 指示器默认样式以及遮盖样式处理
  570. if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
  571. if (progress == 1.0) {
  572. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  573. self.indicatorView.SG_centerX = targetBtn.SG_centerX;
  574. [self P_changeSelectedButton:targetBtn];
  575. }];
  576. } else {
  577. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  578. self.indicatorView.SG_centerX = originalBtn.SG_centerX;
  579. [self P_changeSelectedButton:originalBtn];
  580. }];
  581. }
  582. return;
  583. }
  584. if (progress == 1.0) {
  585. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
  586. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  587. if (tempIndicatorWidth >= targetBtn.SG_width) {
  588. self.indicatorView.SG_width = targetBtn.SG_width;
  589. } else {
  590. self.indicatorView.SG_width = tempIndicatorWidth;
  591. }
  592. self.indicatorView.SG_centerX = targetBtn.SG_centerX;
  593. [self P_changeSelectedButton:targetBtn];
  594. }];
  595. } else {
  596. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
  597. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  598. if (tempIndicatorWidth >= targetBtn.SG_width) {
  599. self.indicatorView.SG_width = originalBtn.SG_width;
  600. } else {
  601. self.indicatorView.SG_width = tempIndicatorWidth;
  602. }
  603. self.indicatorView.SG_centerX = originalBtn.SG_centerX;
  604. [self P_changeSelectedButton:originalBtn];
  605. }];
  606. }
  607. }
  608. #pragma mark - - - SGPageTitleView 滚动样式下指示器 SGIndicatorScrollStyleHalf 和 SGIndicatorScrollStyleEnd 滚动样式
  609. - (void)P_indicatorScrollStyleHalfEndWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
  610. if (self.configure.indicatorScrollStyle == SGIndicatorScrollStyleHalf) {
  611. if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
  612. if (progress >= 0.5) {
  613. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  614. self.indicatorView.SG_centerX = targetBtn.SG_centerX;
  615. [self P_changeSelectedButton:targetBtn];
  616. }];
  617. } else {
  618. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  619. self.indicatorView.SG_centerX = originalBtn.SG_centerX;
  620. [self P_changeSelectedButton:originalBtn];
  621. }];
  622. }
  623. return;
  624. }
  625. /// 指示器默认样式以及遮盖样式处理
  626. if (progress >= 0.5) {
  627. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
  628. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  629. if (tempIndicatorWidth >= targetBtn.SG_width) {
  630. self.indicatorView.SG_width = targetBtn.SG_width;
  631. } else {
  632. self.indicatorView.SG_width = tempIndicatorWidth;
  633. }
  634. self.indicatorView.SG_centerX = targetBtn.SG_centerX;
  635. [self P_changeSelectedButton:targetBtn];
  636. }];
  637. } else {
  638. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
  639. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  640. if (tempIndicatorWidth >= originalBtn.SG_width) {
  641. self.indicatorView.SG_width = originalBtn.SG_width;
  642. } else {
  643. self.indicatorView.SG_width = tempIndicatorWidth;
  644. }
  645. self.indicatorView.SG_centerX = originalBtn.SG_centerX;
  646. [self P_changeSelectedButton:originalBtn];
  647. }];
  648. }
  649. return;
  650. }
  651. /// 滚动内容结束指示器处理 ____ 指示器默认样式以及遮盖样式处理
  652. if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
  653. if (progress == 1.0) {
  654. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  655. self.indicatorView.SG_centerX = targetBtn.SG_centerX;
  656. [self P_changeSelectedButton:targetBtn];
  657. }];
  658. } else {
  659. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  660. self.indicatorView.SG_centerX = originalBtn.SG_centerX;
  661. [self P_changeSelectedButton:originalBtn];
  662. }];
  663. }
  664. return;
  665. }
  666. if (progress == 1.0) {
  667. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
  668. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  669. if (tempIndicatorWidth >= targetBtn.SG_width) {
  670. self.indicatorView.SG_width = targetBtn.SG_width;
  671. } else {
  672. self.indicatorView.SG_width = tempIndicatorWidth;
  673. }
  674. self.indicatorView.SG_centerX = targetBtn.SG_centerX;
  675. [self P_changeSelectedButton:targetBtn];
  676. }];
  677. } else {
  678. CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
  679. [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
  680. if (tempIndicatorWidth >= originalBtn.SG_width) {
  681. self.indicatorView.SG_width = originalBtn.SG_width;
  682. } else {
  683. self.indicatorView.SG_width = tempIndicatorWidth;
  684. }
  685. self.indicatorView.SG_centerX = originalBtn.SG_centerX;
  686. [self P_changeSelectedButton:originalBtn];
  687. }];
  688. }
  689. }
  690. #pragma mark - - - 颜色渐变方法抽取
  691. - (void)P_isTitleGradientEffectWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
  692. // 获取 targetProgress
  693. CGFloat targetProgress = progress;
  694. // 获取 originalProgress
  695. CGFloat originalProgress = 1 - targetProgress;
  696. CGFloat r = self.endR - self.startR;
  697. CGFloat g = self.endG - self.startG;
  698. CGFloat b = self.endB - self.startB;
  699. UIColor *originalColor = [UIColor colorWithRed:self.startR + r * originalProgress green:self.startG + g * originalProgress blue:self.startB + b * originalProgress alpha:1];
  700. UIColor *targetColor = [UIColor colorWithRed:self.startR + r * targetProgress green:self.startG + g * targetProgress blue:self.startB + b * targetProgress alpha:1];
  701. // 设置文字颜色渐变
  702. originalBtn.titleLabel.textColor = originalColor;
  703. targetBtn.titleLabel.textColor = targetColor;
  704. }
  705. #pragma mark - - - set
  706. - (void)setIsNeedBounces:(BOOL)isNeedBounces {
  707. _isNeedBounces = isNeedBounces;
  708. if (isNeedBounces == NO) {
  709. self.scrollView.bounces = NO;
  710. }
  711. }
  712. - (void)setSelectedIndex:(NSInteger)selectedIndex {
  713. _selectedIndex = selectedIndex;
  714. if (selectedIndex) {
  715. _selectedIndex = selectedIndex;
  716. }
  717. }
  718. - (void)setResetSelectedIndex:(NSInteger)resetSelectedIndex {
  719. _resetSelectedIndex = resetSelectedIndex;
  720. [self P_btn_action:self.btnMArr[resetSelectedIndex]];
  721. }
  722. - (void)setNewSelectedIndex:(NSInteger)newSelectedIndex {
  723. _newSelectedIndex = newSelectedIndex;
  724. [self c_btn_action:self.btnMArr[newSelectedIndex]];
  725. }
  726. - (void)setIsTitleGradientEffect:(BOOL)isTitleGradientEffect {
  727. _isTitleGradientEffect = isTitleGradientEffect;
  728. }
  729. - (void)setIsOpenTitleTextZoom:(BOOL)isOpenTitleTextZoom {
  730. _isOpenTitleTextZoom = isOpenTitleTextZoom;
  731. }
  732. - (void)setTitleTextScaling:(CGFloat)titleTextScaling {
  733. _titleTextScaling = titleTextScaling;
  734. if (titleTextScaling) {
  735. if (titleTextScaling >= 0.3) {
  736. _titleTextScaling = 0.3;
  737. } else {
  738. _titleTextScaling = 0.1;
  739. }
  740. }
  741. }
  742. - (void)setIsShowIndicator:(BOOL)isShowIndicator {
  743. _isShowIndicator = isShowIndicator;
  744. if (isShowIndicator == NO) {
  745. [self.indicatorView removeFromSuperview];
  746. self.indicatorView = nil;
  747. }
  748. }
  749. - (void)setIsShowBottomSeparator:(BOOL)isShowBottomSeparator {
  750. _isShowBottomSeparator = isShowBottomSeparator;
  751. if (isShowBottomSeparator) {
  752. } else {
  753. [self.bottomSeparator removeFromSuperview];
  754. self.bottomSeparator = nil;
  755. }
  756. }
  757. #pragma mark - - - 颜色设置的计算
  758. /// 开始颜色设置
  759. - (void)setupStartColor:(UIColor *)color {
  760. CGFloat components[3];
  761. [self getRGBComponents:components forColor:color];
  762. self.startR = components[0];
  763. self.startG = components[1];
  764. self.startB = components[2];
  765. }
  766. /// 结束颜色设置
  767. - (void)setupEndColor:(UIColor *)color {
  768. CGFloat components[3];
  769. [self getRGBComponents:components forColor:color];
  770. self.endR = components[0];
  771. self.endG = components[1];
  772. self.endB = components[2];
  773. }
  774. /**
  775. * 指定颜色,获取颜色的RGB值
  776. *
  777. * @param components RGB数组
  778. * @param color 颜色
  779. */
  780. - (void)getRGBComponents:(CGFloat [3])components forColor:(UIColor *)color {
  781. CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
  782. unsigned char resultingPixel[4];
  783. CGContextRef context = CGBitmapContextCreate(&resultingPixel, 1, 1, 8, 4, rgbColorSpace, 1);
  784. CGContextSetFillColorWithColor(context, [color CGColor]);
  785. CGContextFillRect(context, CGRectMake(0, 0, 1, 1));
  786. CGContextRelease(context);
  787. CGColorSpaceRelease(rgbColorSpace);
  788. for (int component = 0; component < 3; component++) {
  789. components[component] = resultingPixel[component] / 255.0f;
  790. }
  791. }
  792. @end