123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572 |
- //
- // SPPageMenu.m
- // SPPageMenu
- //
- // Created by 乐升平 on 17/10/26.
- // Copyright © 2017年 iDress. All rights reserved.
- //
- #import "SPPageMenu.h"
- #define tagBaseValue 100
- #define scrollViewContentOffset @"contentOffset"
- @interface SPPageMenuScrollView : UIScrollView
- @end
- @implementation SPPageMenuScrollView
- // 重写这个方法的目的是:当手指长按按钮时无法滑动scrollView的问题
- - (BOOL)touchesShouldCancelInContentView:(UIView *)view {
- return YES;
- }
- @end
- @interface SPPageMenuLine : UIImageView
- @property (nonatomic, copy) void(^hideBlock)(void);
- @end
- @implementation SPPageMenuLine
- // 当外界设置隐藏和alpha值时,让pageMenu重新布局
- - (void)setHidden:(BOOL)hidden {
- [super setHidden:hidden];
- if (self.hideBlock) {
- self.hideBlock();
- }
- }
- - (void)setAlpha:(CGFloat)alpha {
- [super setAlpha:alpha];
- if (self.hideBlock) {
- self.hideBlock();
- }
- }
- @end
- @interface SPPageMenuItem : UIButton
- - (instancetype)initWithImageRatio:(CGFloat)ratio;
- // 图片的高度所占按钮的高度比例,注意要浮点数,如果传分数比如三分之二,要写2.0/3.0,不能写2/3
- @property (nonatomic, assign) CGFloat imageRatio;
- // 图片的位置
- @property (nonatomic, assign) SPItemImagePosition imagePosition;
- // 图片与标题之间的间距
- @property (nonatomic, assign) CGFloat imageTitleSpace;
- @end
- @implementation SPPageMenuItem
- - (instancetype)initWithImageRatio:(CGFloat)ratio {
- if (self = [super init]) {
- _imageRatio = ratio;
- }
- return self;
- }
- - (instancetype)initWithFrame:(CGRect)frame
- {
- if (self = [super initWithFrame:frame]) {
- [self initialize];
- }
- return self;
- }
- - (instancetype)initWithCoder:(NSCoder *)aDecoder {
- if (self = [super initWithCoder:aDecoder]) {
- [self initialize];
- }
- return self;
- }
- - (void)initialize {
- _imageRatio = 0.5;
- _imagePosition = SPItemImagePositionDefault;
- self.imageView.contentMode = UIViewContentModeScaleAspectFit;
- self.titleLabel.textAlignment = NSTextAlignmentCenter;
- }
- - (void)setHighlighted:(BOOL)highlighted {}
- - (CGRect)imageRectForContentRect:(CGRect)contentRect {
- if (!self.currentTitle) { // 如果没有文字,则图片占据整个button,空格算一个文字
- return [super imageRectForContentRect:contentRect];
- }
- switch (self.imagePosition) {
- case SPItemImagePositionDefault:
- case SPItemImagePositionLeft: { // 图片在左
- _imageRatio = _imageRatio == 0.0 ? 0.5 : _imageRatio;
- CGFloat imageW = (contentRect.size.width-_imageTitleSpace) * _imageRatio;
- CGFloat imageH = contentRect.size.height;
- //自定义修改 - 图片在左时,固定图片大小为21
- imageW = 18;
- return CGRectMake(12, self.contentEdgeInsets.top, imageW, imageH);
- // return CGRectMake(self.contentEdgeInsets.left, self.contentEdgeInsets.top, imageW, imageH);
- }
- break;
- case SPItemImagePositionTop: {
- _imageRatio = _imageRatio == 0.0 ? 2.0/3.0 : _imageRatio;
- CGFloat imageW = contentRect.size.width;
- CGFloat imageH = (contentRect.size.height-_imageTitleSpace) * _imageRatio;
- return CGRectMake(self.contentEdgeInsets.left, self.contentEdgeInsets.top, imageW, imageH);
- }
- break;
- case SPItemImagePositionRight: {
- _imageRatio = _imageRatio == 0.0 ? 0.5 : _imageRatio;
- CGFloat imageW = (contentRect.size.width-_imageTitleSpace) * _imageRatio;
- CGFloat imageH = contentRect.size.height;
- CGFloat imageX = contentRect.size.width - imageW;
- return CGRectMake(imageX+self.contentEdgeInsets.left, self.contentEdgeInsets.top, imageW, imageH);
- }
- break;
- case SPItemImagePositionBottom: {
- _imageRatio = _imageRatio == 0.0 ? 2.0/3.0 : _imageRatio;
- CGFloat imageW = contentRect.size.width;
- CGFloat imageH = (contentRect.size.height - _imageTitleSpace) * _imageRatio;
- CGFloat imageY = contentRect.size.height-imageH;
- return CGRectMake(self.contentEdgeInsets.left, imageY+self.contentEdgeInsets.top, imageW, imageH);
- }
- break;
- default:
- break;
- }
- return CGRectZero;
- }
- - (CGRect)titleRectForContentRect:(CGRect)contentRect {
- if (!self.currentImage) { // 如果没有图片
- return [super titleRectForContentRect:contentRect];
- }
- switch (self.imagePosition) {
- case SPItemImagePositionDefault:
- case SPItemImagePositionLeft: {
- _imageRatio = _imageRatio == 0.0 ? 0.5 : _imageRatio;
- CGFloat titleX = (contentRect.size.width-_imageTitleSpace) * _imageRatio + _imageTitleSpace;
- CGFloat titleW = contentRect.size.width - titleX;
- CGFloat titleH = contentRect.size.height;
- return CGRectMake(titleX+self.contentEdgeInsets.left, self.contentEdgeInsets.top, titleW, titleH);
- }
- break;
- case SPItemImagePositionTop: {
- _imageRatio = _imageRatio == 0.0 ? 2.0/3.0 : _imageRatio;
- CGFloat titleY = (contentRect.size.height-_imageTitleSpace) * _imageRatio + _imageTitleSpace;
- CGFloat titleW = contentRect.size.width;
- CGFloat titleH = contentRect.size.height - titleY;
- return CGRectMake(self.contentEdgeInsets.left, titleY+self.contentEdgeInsets.top, titleW, titleH);
- }
- break;
- case SPItemImagePositionRight: {
- _imageRatio = _imageRatio == 0.0 ? 0.5 : _imageRatio;
- CGFloat titleW = (contentRect.size.width - _imageTitleSpace) * (1-_imageRatio);
- CGFloat titleH = contentRect.size.height;
- return CGRectMake(self.contentEdgeInsets.left, self.contentEdgeInsets.top, titleW, titleH);
- }
- break;
- case SPItemImagePositionBottom: {
- _imageRatio = _imageRatio == 0.0 ? 2.0/3.0 : _imageRatio;
- CGFloat titleW = contentRect.size.width;
- CGFloat titleH = (contentRect.size.height-_imageTitleSpace) * (1 - _imageRatio);
- return CGRectMake(self.contentEdgeInsets.left, self.contentEdgeInsets.top, titleW, titleH);
- }
- break;
- default:
- break;
- }
- return CGRectZero;
- }
- - (void)setImagePosition:(SPItemImagePosition)imagePosition {
- _imagePosition = imagePosition;
- [self setNeedsDisplay];
- }
- - (void)setImageRatio:(CGFloat)imageRatio {
- _imageRatio = imageRatio;
- [self setNeedsDisplay];
- }
- - (void)setImageTitleSpace:(CGFloat)imageTitleSpace {
- _imageTitleSpace = imageTitleSpace;
- [self setNeedsDisplay];
- }
- - (void)setContentEdgeInsets:(UIEdgeInsets)contentEdgeInsets {
- [super setContentEdgeInsets:contentEdgeInsets];
- [self setNeedsDisplay];
- }
- @end
- @interface SPPageMenu()
- @property (nonatomic, assign) SPPageMenuTrackerStyle trackerStyle;
- @property (nonatomic, strong) NSArray *items; // 里面装的是字符串或者图片
- @property (nonatomic, strong) UIImageView *tracker;
- @property (nonatomic, assign) CGFloat trackerHeight;
- @property (nonatomic, weak) UIView *backgroundView;
- @property (nonatomic, weak) UIImageView *backgroundImageView;
- @property (nonatomic, strong) UIImageView *dividingLine;
- @property (nonatomic, weak) SPPageMenuScrollView *itemScrollView;
- @property (nonatomic, weak) SPPageMenuItem *functionButton;
- @property (nonatomic, strong) NSMutableArray *buttons;
- @property (nonatomic, strong) NSMutableArray *hLineArray;
- @property (nonatomic, strong) SPPageMenuItem *selectedButton;
- @property (nonatomic, strong) NSMutableDictionary *setupWidths;
- @property (nonatomic, assign) BOOL insert;
- // 起始偏移量,为了判断滑动方向
- @property (nonatomic, assign) CGFloat beginOffsetX;
- /// 开始颜色, 取值范围 0~1
- @property (nonatomic, assign) CGFloat startR;
- @property (nonatomic, assign) CGFloat startG;
- @property (nonatomic, assign) CGFloat startB;
- /// 完成颜色, 取值范围 0~1
- @property (nonatomic, assign) CGFloat endR;
- @property (nonatomic, assign) CGFloat endG;
- @property (nonatomic, assign) CGFloat endB;
- // 这个高度,是存储itemScrollView的高度
- @property (nonatomic, assign) CGFloat itemScrollViewH;
- @end
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- @implementation SPPageMenu
- #pragma mark - public
- + (instancetype)pageMenuWithFrame:(CGRect)frame trackerStyle:(SPPageMenuTrackerStyle)trackerStyle {
- SPPageMenu *pageMenu = [[SPPageMenu alloc] initWithFrame:frame trackerStyle:trackerStyle];
- return pageMenu;
- }
- - (instancetype)initWithFrame:(CGRect)frame trackerStyle:(SPPageMenuTrackerStyle)trackerStyle {
- if (self = [super init]) {
- self.frame = frame;
- self.backgroundColor = [UIColor whiteColor];
- self.trackerStyle = trackerStyle;
- [self setupStartColor:_selectedItemTitleColor];
- [self setupEndColor:_unSelectedItemTitleColor];
- }
- return self;
- }
- - (void)setItems:(NSArray *)items selectedItemIndex:(NSInteger)selectedItemIndex {
- if (selectedItemIndex < 0) selectedItemIndex = 0;
- NSAssert(selectedItemIndex <= items.count-1, @"selectedItemIndex 大于了 %ld",items.count-1);
- _items = items.copy;
- _selectedItemIndex = selectedItemIndex;
-
- self.insert = NO;
- if (self.buttons.count) {
- for (SPPageMenuItem *button in self.buttons) {
- [button removeFromSuperview];
- }
- }
- [self.buttons removeAllObjects];
-
- for (int i = 0; i < items.count; i++) {
- id object = items[i];
- NSAssert([object isKindOfClass:[NSString class]] || [object isKindOfClass:[UIImage class]], @"items中的元素只能是NSString或UIImage类型");
- [self addButton:i object:object animated:NO];
- }
- [self setNeedsLayout];
- [self layoutIfNeeded];
-
- if (self.buttons.count) {
- // 默认选中selectedItemIndex对应的按钮
- SPPageMenuItem *selectedButton = [self.buttons objectAtIndex:selectedItemIndex];
- [self buttonInPageMenuClicked:selectedButton];
- // SPPageMenuTrackerStyleTextZoom和SPPageMenuTrackerStyleNothing样式跟tracker没有关联
- if ([self haveOrNeedsTracker]) {
- [self.itemScrollView insertSubview:self.tracker atIndex:0];
- // 这里千万不能再去调用setNeedsLayout和layoutIfNeeded,因为如果外界在此之前对selectedButton进行了缩放,调用了layoutSubViews后会重新对selectedButton设置frame,先缩放再重设置frame会导致文字显示不全,所以我们直接跳过layoutSubViews调用resetSetupTrackerFrameWithSelectedButton:只设置tracker的frame
- [self resetSetupTrackerFrameWithSelectedButton:selectedButton];
- }
- }
- }
- - (void)insertItemWithTitle:(NSString *)title atIndex:(NSUInteger)itemIndex animated:(BOOL)animated {
- self.insert = YES;
- NSAssert(itemIndex <= self.items.count, @"itemIndex超过了items的总个数“%ld”",self.items.count);
- NSMutableArray *titleArr = self.items.mutableCopy;
- [titleArr insertObject:title atIndex:itemIndex];
- self.items = titleArr;
- [self addButton:itemIndex object:title animated:animated];
- if (itemIndex <= self.selectedItemIndex) {
- _selectedItemIndex += 1;
- }
- }
- - (void)insertItemWithImage:(UIImage *)image atIndex:(NSUInteger)itemIndex animated:(BOOL)animated {
- self.insert = YES;
- NSAssert(itemIndex <= self.items.count, @"itemIndex超过了items的总个数“%ld”",self.items.count);
- NSMutableArray *objects = self.items.mutableCopy;
- [objects insertObject:image atIndex:itemIndex];
- self.items = objects.copy;
- [self addButton:itemIndex object:image animated:animated];
- if (itemIndex <= self.selectedItemIndex) {
- _selectedItemIndex += 1;
- }
- }
- - (void)removeItemAtIndex:(NSUInteger)itemIndex animated:(BOOL)animated {
- NSAssert(itemIndex <= self.items.count, @"itemIndex超过了items的总个数“%ld”",self.items.count);
- // 被删除的按钮之后的按钮需要修改tag值
- for (SPPageMenuItem *button in self.buttons) {
- if (button.tag-tagBaseValue > itemIndex) {
- button.tag = button.tag - 1;
- }
- }
- if (self.items.count) {
- NSMutableArray *objects = self.items.mutableCopy;
- // 特别注意的是:不能先通过itemIndex取出对象,然后再将对象删除,因为这样会删除所有相同的对象
- [objects removeObjectAtIndex:itemIndex];
- self.items = objects.copy;
- }
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- if (button == self.selectedButton) { // 如果删除的正是选中的item,删除之后,选中的按钮切换为上一个item
- self.selectedItemIndex = itemIndex > 0 ? itemIndex-1 : itemIndex;
- }
- [self.buttons removeObjectAtIndex:itemIndex];
- [button removeFromSuperview];
- if (self.buttons.count == 0) { // 说明移除了所有
- [self.tracker removeFromSuperview];
- self.selectedButton = nil;
- self.selectedItemIndex = 0;
- }
- }
- if (animated) {
- [UIView animateWithDuration:0.5 animations:^{
- [self setNeedsLayout];
- [self layoutIfNeeded];
- }];
- } else {
- [self setNeedsLayout];
- }
-
- }
- - (void)removeAllItems {
- NSMutableArray *objects = self.items.mutableCopy;
- [objects removeAllObjects];
- self.items = objects.copy;
- self.items = nil;
-
- for (int i = 0; i < self.buttons.count; i++) {
- SPPageMenuItem *button = self.buttons[i];
- [button removeFromSuperview];
- }
-
- [self.buttons removeAllObjects];
-
- [self.tracker removeFromSuperview];
-
- self.selectedButton = nil;
- self.selectedItemIndex = 0;
-
- [self setNeedsLayout];
- }
- - (void)setTitle:(NSString *)title forItemAtIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- [button setImage:nil forState:UIControlStateNormal];
- [button setTitle:title forState:UIControlStateNormal];
- NSMutableArray *items = self.items.mutableCopy;
- [items replaceObjectAtIndex:itemIndex withObject:title];
- self.items = items.copy;
- }
- [self setNeedsLayout];
- }
- - (nullable NSString *)titleForItemAtIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *item = [self.buttons objectAtIndex:itemIndex];
- return item.currentTitle;
- }
- return nil;
- }
- - (void)setImage:(UIImage *)image forItemAtIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- [button setTitle:nil forState:UIControlStateNormal];
- [button setImage:image forState:UIControlStateNormal];
- NSMutableArray *items = self.items.mutableCopy;
- [items replaceObjectAtIndex:itemIndex withObject:image];
- self.items = items.copy;
- }
- [self setNeedsLayout];
- }
- - (nullable UIImage *)imageForItemAtIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *item = [self.buttons objectAtIndex:itemIndex];
- return item.currentImage;
- }
- return nil;
- }
- - (void)setEnabled:(BOOL)enaled forItemAtIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- [button setEnabled:enaled];
- }
- }
- - (BOOL)enabledForItemAtIndex:(NSUInteger)itemIndex {
- if (self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- return button.enabled;
- }
- return YES;
- }
- - (void)setWidth:(CGFloat)width forItemAtIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- [self.setupWidths setObject:@(width) forKey:[NSString stringWithFormat:@"%lu",(unsigned long)itemIndex]];
- }
- }
- - (CGFloat)widthForItemAtIndex:(NSUInteger)itemIndex {
- CGFloat setupWidth = [[self.setupWidths objectForKey:[NSString stringWithFormat:@"%lu",(unsigned long)itemIndex]] floatValue];
- if (setupWidth) {
- return setupWidth;
- } else {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- return button.bounds.size.width;
- }
- }
- return 0;
- }
- - (void)setContentEdgeInsets:(UIEdgeInsets)contentInset forForItemAtIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- button.contentEdgeInsets = contentInset;
- }
- }
- - (void)setContentEdgeInsets:(UIEdgeInsets)contentInset forItemAtIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- button.contentEdgeInsets = contentInset;
- }
- }
- - (UIEdgeInsets)contentEdgeInsetsForItemAtIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- return button.contentEdgeInsets;
- }
- return UIEdgeInsetsZero;
- }
- - (void)setBackgroundImage:(UIImage *)backgroundImage barMetrics:(UIBarMetrics)barMetrics {
- if (barMetrics == UIBarMetricsDefault) {
- if (UIEdgeInsetsEqualToEdgeInsets(backgroundImage.capInsets, UIEdgeInsetsZero)) {
- CGFloat imageWidth = CGImageGetWidth(backgroundImage.CGImage);
- CGFloat imageHeight = CGImageGetHeight(backgroundImage.CGImage);
- [self.backgroundImageView setImage:[backgroundImage resizableImageWithCapInsets:UIEdgeInsetsMake(imageHeight*0.5, imageWidth*0.5, imageHeight*0.5, imageWidth*0.5) resizingMode:backgroundImage.resizingMode]];
- } else {
- [self.backgroundImageView setImage:backgroundImage];
- }
- }
- }
- - (UIImage *)backgroundImageForBarMetrics:(UIBarMetrics)barMetrics {
- return self.backgroundImageView.image;
- }
- - (void)setTrackerHeight:(CGFloat)trackerHeight cornerRadius:(CGFloat)cornerRadius {
- _trackerHeight = trackerHeight;
- self.tracker.layer.cornerRadius = cornerRadius;
- [self setNeedsLayout];
- [self layoutIfNeeded];
- }
- - (void)setTitle:(nullable NSString *)title image:(nullable UIImage *)image imagePosition:(SPItemImagePosition)imagePosition imageRatio:(CGFloat)ratio imageTitleSpace:(CGFloat)imageTitleSpace forItemIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- [button setTitle:title forState:UIControlStateNormal];
- [button setImage:image forState:UIControlStateNormal];
- button.imagePosition = imagePosition;
- button.imageRatio = ratio;
- button.imageTitleSpace = imageTitleSpace;
-
- // 文字和图片只能替换其一,因为items数组里不能同时装文字和图片。当文字和图片同时设置时,items里只更新文字
- if (title == nil || title.length == 0 || [title isKindOfClass:[NSNull class]]) {
- NSMutableArray *items = self.items.mutableCopy;
- [items replaceObjectAtIndex:itemIndex withObject:image];
- self.items = items.copy;
- } else if (image == nil) {
- NSMutableArray *items = self.items.mutableCopy;
- [items replaceObjectAtIndex:itemIndex withObject:title];
- self.items = items.copy;
- } else {
- NSMutableArray *items = self.items.mutableCopy;
- [items replaceObjectAtIndex:itemIndex withObject:image];
- self.items = items.copy;
- }
-
- [self setNeedsLayout];
- [self layoutIfNeeded];
- }
- }
- - (void)setFunctionButtonTitle:(nullable NSString *)title image:(nullable UIImage *)image imagePosition:(SPItemImagePosition)imagePosition imageRatio:(CGFloat)ratio imageTitleSpace:(CGFloat)imageTitleSpace forState:(UIControlState)state {
- [self.functionButton setTitle:title forState:state];
- [self.functionButton setImage:image forState:state];
- self.functionButton.imagePosition = imagePosition;
- self.functionButton.imageRatio = ratio;
- self.functionButton.imageTitleSpace = imageTitleSpace;
- }
- // 以下2个方法在3.0版本上有升级,可以使用但不推荐
- - (void)setTitle:(nullable NSString *)title image:(nullable UIImage *)image imagePosition:(SPItemImagePosition)imagePosition imageRatio:(CGFloat)ratio forItemIndex:(NSUInteger)itemIndex {
- if (itemIndex < self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:itemIndex];
- [button setTitle:title forState:UIControlStateNormal];
- [button setImage:image forState:UIControlStateNormal];
- button.imagePosition = imagePosition;
- button.imageRatio = ratio;
-
- // 文字和图片只能替换其一,因为items数组里不能同时装文字和图片。当文字和图片同时设置时,items里只更新文字
- if (title == nil || title.length == 0 || [title isKindOfClass:[NSNull class]]) {
- NSMutableArray *items = self.items.mutableCopy;
- [items replaceObjectAtIndex:itemIndex withObject:image];
- self.items = items.copy;
- } else if (image == nil) {
- NSMutableArray *items = self.items.mutableCopy;
- [items replaceObjectAtIndex:itemIndex withObject:title];
- self.items = items.copy;
- } else {
- NSMutableArray *items = self.items.mutableCopy;
- [items replaceObjectAtIndex:itemIndex withObject:image];
- self.items = items.copy;
- }
-
- [self setNeedsLayout];
- [self layoutIfNeeded];
- }
- }
- - (void)setFunctionButtonTitle:(nullable NSString *)title image:(nullable UIImage *)image imagePosition:(SPItemImagePosition)imagePosition imageRatio:(CGFloat)ratio forState:(UIControlState)state {
- [self.functionButton setTitle:title forState:state];
- [self.functionButton setImage:image forState:state];
- self.functionButton.imagePosition = imagePosition;
- self.functionButton.imageRatio = ratio;
- }
- - (void)setFunctionButtonTitleTextAttributes:(nullable NSDictionary *)attributes forState:(UIControlState)state {
- if (attributes[NSFontAttributeName]) {
- self.functionButton.titleLabel.font = attributes[NSFontAttributeName];
- }
- if (attributes[NSForegroundColorAttributeName]) {
- [self.functionButton setTitleColor:attributes[NSForegroundColorAttributeName] forState:state];
- }
- if (attributes[NSBackgroundColorAttributeName]) {
- self.functionButton.backgroundColor = attributes[NSBackgroundColorAttributeName];
- }
- }
- - (void)moveTrackerFollowScrollView:(UIScrollView *)scrollView {
-
- // 说明外界传进来了一个scrollView,如果外界传进来了,pageMenu会观察该scrollView的contentOffset自动处理跟踪器的跟踪
- if (self.bridgeScrollView == scrollView) { return; }
-
- [self prepareMoveTrackerFollowScrollView:scrollView];
- }
-
- #pragma mark - private
- - (void)addButton:(NSInteger)index object:(id)object animated:(BOOL)animated {
-
- // 如果是插入,需要改变已有button的tag值
- for (SPPageMenuItem *button in self.buttons) {
- if (button.tag-tagBaseValue >= index) {
- button.tag = button.tag + 1; // 由于有新button的加入,新button后面的button的tag值得+1
- }
- }
-
- //wcl - 自定义添加按钮分割线
- UIView *hLineView = [[UIView alloc] init];
- hLineView.backgroundColor = RGB(232, 231, 231);
-
- SPPageMenuItem *button = [SPPageMenuItem buttonWithType:UIButtonTypeCustom];
- [button setTitleColor:_unSelectedItemTitleColor forState:UIControlStateNormal];
- button.titleLabel.font = _itemTitleFont;
- [button addTarget:self action:@selector(buttonInPageMenuClicked:) forControlEvents:UIControlEventTouchUpInside];
- button.tag = tagBaseValue + index;
- if ([object isKindOfClass:[NSString class]]) {
- [button setTitle:object forState:UIControlStateNormal];
- } else {
- [button setImage:object forState:UIControlStateNormal];
- }
- if (self.insert) {
- if ([self haveOrNeedsTracker]) {
- if (self.buttons.count == 0) { // 如果是第一个插入,需要将跟踪器加上,第一个插入说明itemScrollView上没有任何子控件
- [self.itemScrollView insertSubview:self.tracker atIndex:0];
- [self.itemScrollView insertSubview:button atIndex:index+1];
- [self.itemScrollView insertSubview:hLineView atIndex:index+1];
- } else { // 已经有跟踪器
- [self.itemScrollView insertSubview:button atIndex:index+1]; // +1是因为跟踪器
- [self.itemScrollView insertSubview:hLineView atIndex:index+1];
- }
- } else {
- [self.itemScrollView insertSubview:button atIndex:index];
- [self.itemScrollView insertSubview:hLineView atIndex:index];
- }
- if (!self.buttons.count) {
- [self buttonInPageMenuClicked:button];
- }
- } else {
- [self.itemScrollView insertSubview:button atIndex:index];
- [self.itemScrollView insertSubview:hLineView atIndex:index];
- }
- [self.buttons insertObject:button atIndex:index];
- [self.hLineArray addObject:hLineView];
-
-
- // setNeedsLayout会标记为需要刷新,layoutIfNeeded只有在有标记的情况下才会立即调用layoutSubViews,当然标记为刷新并非只有调用setNeedsLayout,如frame改变,addSubView等都会标记为刷新
-
- if (self.insert && animated) { // 是插入的新按钮,且需要动画
- // 取出上一个按钮
- SPPageMenuItem *lastButton;
- if (index > 0) {
- lastButton = self.buttons[index-1];
- }
- // 先给初始的origin,按钮将会从这个origin开始动画
- button.frame = CGRectMake(CGRectGetMaxX(lastButton.frame)+_itemPadding*0.5, 0, 0, 0);
- button.titleLabel.frame = button.bounds;
- [UIView animateWithDuration:.5 animations:^{
- [self setNeedsLayout];
- [self layoutIfNeeded];
- }];
- }
- }
- // 是否已经或者即将有跟踪器
- - (BOOL)haveOrNeedsTracker {
- if (self.trackerStyle != SPPageMenuTrackerStyleTextZoom && self.trackerStyle != SPPageMenuTrackerStyleNothing) {
- return YES;
- }
- return NO;
- }
- - (instancetype)initWithFrame:(CGRect)frame {
- if (self = [super initWithFrame:frame]) {
- [self initialize];
- }
- return self;
- }
- - (instancetype)initWithCoder:(NSCoder *)aDecoder {
- if (self = [super initWithCoder:aDecoder]) {
- [self initialize];
- }
- return self;
- }
- - (void)initialize {
-
- _itemPadding = 30.0;
- _selectedItemTitleColor = [UIColor redColor];
- _unSelectedItemTitleColor = [UIColor blackColor];
- _selectedItemTitleFont = [UIFont systemFontOfSize:16];
- _unSelectedItemTitleFont = [UIFont systemFontOfSize:16];
- _itemTitleFont = [UIFont systemFontOfSize:16];
- _trackerHeight = 3.0;
- _dividingLineHeight = 1.0 / [UIScreen mainScreen].scale; // 适配屏幕分辨率
- _contentInset = UIEdgeInsetsZero;
- _selectedItemIndex = 0;
- _showFuntionButton = NO;
- _funtionButtonshadowOpacity = 0.5;
- _selectedItemZoomScale = 1;
- _needTextColorGradients = YES;
-
- [self setupSubViews];
- }
- - (void)setupSubViews {
- // 必须先添加分割线,再添加backgroundView;假如先添加backgroundView,那也就意味着backgroundView是SPPageMenu的第一个子控件,而scrollView又是backgroundView的第一个子控件,当外界在由导航控制器管理的控制器中将SPPageMenu添加为第一个子控件时,控制器会不断的往下遍历第一个子控件的第一个子控件,直到找到为scrollView为止,一旦发现某子控件的第一个子控件为scrollView,会将scrollView的内容往下偏移64;这时控制器中必须设置self.automaticallyAdjustsScrollViewInsets = NO;为了避免这样做,这里将分割线作为第一个子控件
- SPPageMenuLine *dividingLine = [[SPPageMenuLine alloc] init];
- dividingLine.backgroundColor = RGB(236, 236, 236);
- __weak typeof(self) weakSelf = self;
- dividingLine.hideBlock = ^() {
- [weakSelf setNeedsLayout];
- };
- [self addSubview:dividingLine];
- _dividingLine = dividingLine;
-
- UIView *backgroundView = [[UIView alloc] init];
- backgroundView.layer.masksToBounds = YES;
- [self addSubview:backgroundView];
- _backgroundView = backgroundView;
-
- UIImageView *backgroundImageView = [[UIImageView alloc] init];
- [backgroundView addSubview:backgroundImageView];
- _backgroundImageView = backgroundImageView;
-
- SPPageMenuScrollView *itemScrollView = [[SPPageMenuScrollView alloc] init];
- itemScrollView.showsVerticalScrollIndicator = NO;
- itemScrollView.showsHorizontalScrollIndicator = NO;
- itemScrollView.scrollsToTop = NO; // 目的是不要影响到外界的scrollView置顶功能
- itemScrollView.bouncesZoom = NO;
- itemScrollView.bounces = YES;
- if (@available(iOS 11.0, *)) {
- itemScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
- }
- [backgroundView addSubview:itemScrollView];
- _itemScrollView = itemScrollView;
-
- SPPageMenuItem *functionButton = [SPPageMenuItem buttonWithType:UIButtonTypeCustom];
- functionButton.backgroundColor = [UIColor whiteColor];
- // [functionButton setTitle:@"+" forState:UIControlStateNormal];
- [functionButton setImage:[UIImage imageNamed:@"common_bottomArrow_icon"] forState:UIControlStateNormal];
- [functionButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
- [functionButton addTarget:self action:@selector(functionButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
- functionButton.layer.shadowColor = [UIColor blackColor].CGColor;
- functionButton.layer.shadowOffset = CGSizeMake(0, 0);
- functionButton.layer.shadowRadius = 2;
- functionButton.layer.shadowOpacity = _funtionButtonshadowOpacity; // 默认是0,为0的话不会显示阴影
- functionButton.hidden = !_showFuntionButton;
- [backgroundView addSubview:functionButton];
- _functionButton = functionButton;
- }
- // 按钮点击方法
- - (void)buttonInPageMenuClicked:(SPPageMenuItem *)sender {
- NSInteger fromIndex = self.selectedButton ? self.selectedButton.tag-tagBaseValue : sender.tag - tagBaseValue;
- NSInteger toIndex = sender.tag - tagBaseValue;
- // 更新下item对应的下标,必须在代理之前,否则外界在代理方法中拿到的不是最新的,必须用下划线,用self.会造成死循环
- _selectedItemIndex = toIndex;
- // 如果sender是新的选中的按钮,则上一次的按钮颜色为非选中颜色,当前选中的颜色为选中颜色
- if (self.selectedButton != sender) {
- [self.selectedButton setTitleColor:_unSelectedItemTitleColor forState:UIControlStateNormal];
- [sender setTitleColor:_selectedItemTitleColor forState:UIControlStateNormal];
- self.selectedButton.titleLabel.font = _unSelectedItemTitleFont;
- sender.titleLabel.font = _selectedItemTitleFont;
-
- // 让itemScrollView发生偏移
- [self moveItemScrollViewWithSelectedButton:sender];
-
- if (self.trackerStyle == SPPageMenuTrackerStyleTextZoom || _selectedItemZoomScale != 1) {
- if (labs(toIndex-fromIndex) >= 2) { // 该条件意思是当外界滑动scrollView连续的滑动了超过2页
- for (SPPageMenuItem *button in self.buttons) { // 必须遍历将非选中按钮还原缩放,而不是仅仅只让上一个选中的按钮还原缩放。因为当用户快速滑动外界scrollView时,会频繁的调用-zoomForTitleWithProgress:fromButton:toButton:方法,有可能经过的某一个button还没彻底还原缩放就直接过去了,从而可能会导致该按钮文字会显示不全,所以在这里,将所有非选中的按钮还原缩放
- if (button != sender && !CGAffineTransformEqualToTransform(button.transform, CGAffineTransformIdentity)) {
- button.transform = CGAffineTransformIdentity;
- }
- }
- } else {
- self.selectedButton.transform = CGAffineTransformIdentity;
- }
- sender.transform = CGAffineTransformMakeScale(_selectedItemZoomScale, _selectedItemZoomScale);
- }
- if (fromIndex != toIndex) { // 如果相等,说明是第1次进来或者2次点了同一个,此时不需要动画
- [self moveTrackerWithSelectedButton:sender];
- }
- self.selectedButton = sender;
- if (_selectedItemTitleFont != _unSelectedItemTitleFont) {
- [self setNeedsLayout];
- [self layoutIfNeeded];
- }
- } else { // 如果选中的按钮没有发生变化,比如用户往左边滑scrollView,还没滑动结束又开始往右滑动,此时选中的按钮就没变。如果设置了颜色渐变,而且当未选中的颜色带了不等于1的alpha值,如果用户往一边滑动还未结束又往另一边滑,则未选中的按钮颜色不是很准确。这个else就是去除这种不准确现象
- // 获取RGB和Alpha
- CGFloat red = 0.0;
- CGFloat green = 0.0;
- CGFloat blue = 0.0;
- CGFloat alpha = 0.0;
- [_unSelectedItemTitleColor getRed:&red green:&green blue:&blue alpha:&alpha];
- // 此时alpha已经获取到了
- if (alpha < 1) { // 因为相信alpha=1的情况还是占多数的,如果不做判断,apha=1时也for循环设置未选中按钮的颜色有点浪费.alpha=1时不会产生颜色不准确问题
- for (SPPageMenuItem *button in self.buttons) {
- if (button == sender) {
- [button setTitleColor:_selectedItemTitleColor forState:UIControlStateNormal];
- } else {
- [button setTitleColor:_unSelectedItemTitleColor forState:UIControlStateNormal];
- }
- }
- } else {
- [sender setTitleColor:_selectedItemTitleColor forState:UIControlStateNormal];
- }
- }
- [self delegatePerformMethodWithFromIndex:fromIndex toIndex:toIndex];
- }
- // 点击button让itemScrollView发生偏移
- - (void)moveItemScrollViewWithSelectedButton:(SPPageMenuItem *)selectedButton {
- if (CGRectEqualToRect(self.backgroundView.frame, CGRectZero)) {
- return;
- }
- // 转换点的坐标位置
- CGPoint centerInPageMenu = [self.backgroundView convertPoint:selectedButton.center toView:self];
- // CGRectGetMidX(self.backgroundView.frame)指的是屏幕水平中心位置,它的值是固定不变的
- CGFloat offSetX = centerInPageMenu.x - CGRectGetMidX(self.backgroundView.frame);
-
- // itemScrollView的容量宽与自身宽之差(难点)
- CGFloat maxOffsetX = self.itemScrollView.contentSize.width - self.itemScrollView.frame.size.width;
- // 如果选中的button中心x值小于或者等于itemScrollView的中心x值,或者itemScrollView的容量宽度小于itemScrollView本身,此时点击button时不发生任何偏移,置offSetX为0
- if (offSetX <= 0 || maxOffsetX <= 0) {
- offSetX = 0;
- }
- // 如果offSetX大于maxOffsetX,说明itemScrollView已经滑到尽头,此时button也发生任何偏移了
- else if (offSetX > maxOffsetX){
- offSetX = maxOffsetX;
- }
- [self.itemScrollView setContentOffset:CGPointMake(offSetX, 0) animated:YES];
-
- }
- // 移动跟踪器
- - (void)moveTrackerWithSelectedButton:(SPPageMenuItem *)selectedButton {
- [UIView animateWithDuration:0.25 animations:^{
- [self resetSetupTrackerFrameWithSelectedButton:selectedButton];
- }];
- }
- // 执行代理方法
- - (void)delegatePerformMethodWithFromIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex {
- if (self.delegate && [self.delegate respondsToSelector:@selector(pageMenu:itemSelectedFromIndex:toIndex:)]) {
- [self.delegate pageMenu:self itemSelectedFromIndex:fromIndex toIndex:toIndex];
- } else if (self.delegate && [self.delegate respondsToSelector:@selector(pageMenu:itemSelectedAtIndex:)]) {
- [self.delegate pageMenu:self itemSelectedAtIndex:toIndex];
- }
- }
- // 功能按钮的点击方法
- - (void)functionButtonClicked:(SPPageMenuItem *)sender {
- if (self.delegate && [self.delegate respondsToSelector:@selector(pageMenu:functionButtonClicked:)]) {
- [self.delegate pageMenu:self functionButtonClicked:sender];
- }
- }
- - (void)prepareMoveTrackerFollowScrollView:(UIScrollView *)scrollView {
- // 这个if条件的意思是scrollView的滑动不是由手指拖拽产生
- if (!scrollView.isDragging && !scrollView.isDecelerating) {return;}
- // 当滑到边界时,继续通过scrollView的bouces效果滑动时,直接return
- if (scrollView.contentOffset.x < 0 || scrollView.contentOffset.x > scrollView.contentSize.width-scrollView.bounds.size.width) {
- return;
- }
- // 当前偏移量
- CGFloat currentOffSetX = scrollView.contentOffset.x;
- // 偏移进度
- CGFloat offsetProgress = currentOffSetX / scrollView.bounds.size.width;
- CGFloat progress = offsetProgress - floor(offsetProgress);
- NSInteger fromIndex = 0;
- NSInteger toIndex = 0;
- // 初始值不要等于scrollView.contentOffset.x,因为第一次进入此方法时,scrollView.contentOffset.x的值已经有一点点偏移了,不是很准确
- _beginOffsetX = scrollView.bounds.size.width * self.selectedItemIndex;
- // 以下注释的“拖拽”一词很准确,不可说成滑动,例如:当手指向右拖拽,还未拖到一半时就松开手,接下来scrollView则会往回滑动,这个往回,就是向左滑动,这也是_beginOffsetX不可时刻纪录的原因,如果时刻纪录,那么往回(向左)滑动时会被视为“向左拖拽”,然而,这个往回却是由“向右拖拽”而导致的
- if (currentOffSetX - _beginOffsetX > 0) { // 向左拖拽了
- // 求商,获取上一个item的下标
- fromIndex = currentOffSetX / scrollView.bounds.size.width;
- // 当前item的下标等于上一个item的下标加1
- toIndex = fromIndex + 1;
- if (toIndex >= self.buttons.count) {
- toIndex = fromIndex;
- }
- } else if (currentOffSetX - _beginOffsetX < 0) { // 向右拖拽了
- toIndex = currentOffSetX / scrollView.bounds.size.width;
- fromIndex = toIndex + 1;
- progress = 1.0 - progress;
- } else {
- progress = 1.0;
- fromIndex = self.selectedItemIndex;
- toIndex = fromIndex;
- }
- if (currentOffSetX == scrollView.bounds.size.width * fromIndex) {// 滚动停止了
- progress = 1.0;
- toIndex = fromIndex;
- }
- // 如果滚动停止,直接通过点击按钮选中toIndex对应的item
- if (currentOffSetX == scrollView.bounds.size.width*toIndex) { // 这里toIndex==fromIndex
- // 这一次赋值起到2个作用,一是点击toIndex对应的按钮,走一遍代理方法,二是弥补跟踪器的结束跟踪,因为本方法是在scrollViewDidScroll中调用,可能离滚动结束还有一丁点的距离,本方法就不调了,最终导致外界还要在scrollView滚动结束的方法里self.selectedItemIndex进行赋值,直接在这里赋值可以让外界不用做此操作
- if (_selectedItemIndex != toIndex) {
- self.selectedItemIndex = toIndex;
- }
- // 要return,点击了按钮,跟踪器自然会跟着被点击的按钮走
- return;
- }
- if (self.trackerFollowingMode == SPPageMenuTrackerFollowingModeAlways) {
- // 这个方法才开始移动跟踪器
- [self moveTrackerWithProgress:progress fromIndex:fromIndex toIndex:toIndex currentOffsetX:currentOffSetX beginOffsetX:_beginOffsetX];
- } else if (self.trackerFollowingMode == SPPageMenuTrackerFollowingModeHalf) {
- SPPageMenuItem *fromButton;
- SPPageMenuItem *toButton;
- if (progress > 0.5) {
- if (toIndex >= 0 && toIndex < self.buttons.count) {
- toButton = self.buttons[toIndex];
- fromButton = self.buttons[fromIndex];
- if (_selectedItemIndex != toIndex) {
- self.selectedItemIndex = toIndex;
- }
- }
- } else {
- if (fromIndex >= 0 && fromIndex < self.buttons.count) {
- toButton = self.buttons[fromIndex];
- fromButton = self.buttons[toIndex];
- if (_selectedItemIndex != fromIndex) {
- self.selectedItemIndex = fromIndex;
- }
- }
- }
- } else { // self.trackerFollowingMode = SPPageMenuTrackerFollowingModeEnd
- // 什么都不用做
- }
- }
- // 这个方法才开始真正滑动跟踪器,上面都是做铺垫
- - (void)moveTrackerWithProgress:(CGFloat)progress fromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex currentOffsetX:(CGFloat)currentOffsetX beginOffsetX:(CGFloat)beginOffsetX {
- UIButton *fromButton = self.buttons[fromIndex];
- UIButton *toButton = self.buttons[toIndex];
-
- // 2个按钮之间的距离
- CGFloat xDistance = toButton.center.x - fromButton.center.x;
- // 2个按钮宽度的差值
- CGFloat wDistance = toButton.frame.size.width - fromButton.frame.size.width;
-
- CGRect newFrame = self.tracker.frame;
- CGPoint newCenter = self.tracker.center;
- if (self.trackerStyle == SPPageMenuTrackerStyleLine) {
- newCenter.x = fromButton.center.x + xDistance * progress;
- newFrame.size.width = _trackerWidth ? _trackerWidth : (fromButton.frame.size.width + wDistance * progress);
- self.tracker.frame = newFrame;
- self.tracker.center = newCenter;
- if (_selectedItemZoomScale != 1) {
- [self zoomForTitleWithProgress:progress fromButton:fromButton toButton:toButton];
- }
- } else if (self.trackerStyle == SPPageMenuTrackerStyleLineAttachment) {
- // 这种样式的计算比较复杂,有个很关键的技巧,就是参考progress分别为0、0.5、1时的临界值
- // 原先的x值
- CGFloat originX = fromButton.frame.origin.x+(fromButton.frame.size.width-(_trackerWidth ? _trackerWidth : fromButton.titleLabel.font.pointSize))*0.5;
- // 原先的宽度
- CGFloat originW = _trackerWidth ? _trackerWidth : fromButton.titleLabel.font.pointSize;
- if (currentOffsetX - _beginOffsetX >= 0) { // 向左拖拽了
- if (progress < 0.5) {
- newFrame.origin.x = originX; // x值保持不变
- newFrame.size.width = originW + xDistance * progress * 2;
- } else {
- newFrame.origin.x = originX + xDistance * (progress-0.5) * 2;
- newFrame.size.width = originW + xDistance - xDistance * (progress-0.5) * 2;
- }
- } else { // 向右拖拽了
- // 此时xDistance为负
- if (progress < 0.5) {
- newFrame.origin.x = originX + xDistance * progress * 2;
- newFrame.size.width = originW - xDistance * progress * 2;
- } else {
- newFrame.origin.x = originX + xDistance;
- newFrame.size.width = originW - xDistance + xDistance * (progress-0.5) * 2;
- }
- }
- self.tracker.frame = newFrame;
- if (_selectedItemZoomScale != 1) {
- [self zoomForTitleWithProgress:progress fromButton:fromButton toButton:toButton];
- }
-
- } else if (self.trackerStyle == SPPageMenuTrackerStyleTextZoom || self.trackerStyle == SPPageMenuTrackerStyleNothing) {
- // 缩放文字
- if (_selectedItemZoomScale != 1) {
- [self zoomForTitleWithProgress:progress fromButton:fromButton toButton:toButton];
- }
- } else if (self.trackerStyle == SPPageMenuTrackerStyleRoundedRect) {
- newCenter.x = fromButton.center.x + xDistance * progress;
- newFrame.size.width = _trackerWidth ? _trackerWidth : (fromButton.frame.size.width + wDistance * progress + _itemPadding);
- self.tracker.frame = newFrame;
- self.tracker.center = newCenter;
- if (_selectedItemZoomScale != 1) {
- [self zoomForTitleWithProgress:progress fromButton:fromButton toButton:toButton];
- }
- } else {
- newCenter.x = fromButton.center.x + xDistance * progress;
- newFrame.size.width = _trackerWidth ? _trackerWidth : (fromButton.frame.size.width + wDistance * progress + _itemPadding);
- self.tracker.frame = newFrame;
- self.tracker.center = newCenter;
- if (_selectedItemZoomScale != 1) {
- [self zoomForTitleWithProgress:progress fromButton:fromButton toButton:toButton];
- }
- }
- // 文字颜色渐变
- if (self.needTextColorGradients) {
- [self colorGradientForTitleWithProgress:progress fromButton:fromButton toButton:toButton];
- }
- }
- // 颜色渐变方法
- - (void)colorGradientForTitleWithProgress:(CGFloat)progress fromButton:(UIButton *)fromButton toButton:(UIButton *)toButton {
- // 获取 targetProgress
- CGFloat fromProgress = progress;
- // 获取 originalProgress
- CGFloat toProgress = 1 - fromProgress;
-
- CGFloat r = self.endR - self.startR;
- CGFloat g = self.endG - self.startG;
- CGFloat b = self.endB - self.startB;
- UIColor *fromColor = [UIColor colorWithRed:self.startR + r * fromProgress green:self.startG + g * fromProgress blue:self.startB + b * fromProgress alpha:1];
- UIColor *toColor = [UIColor colorWithRed:self.startR + r * toProgress green:self.startG + g * toProgress blue:self.startB + b * toProgress alpha:1];
-
- // 设置文字颜色渐变
- [fromButton setTitleColor:fromColor forState:UIControlStateNormal];
- [toButton setTitleColor:toColor forState:UIControlStateNormal];
- }
- // 获取颜色的RGB值
- - (void)getRGBComponents:(CGFloat [3])components forColor:(UIColor *)color {
- CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
- unsigned char resultingPixel[4];
- CGContextRef context = CGBitmapContextCreate(&resultingPixel, 1, 1, 8, 4, rgbColorSpace, 1);
- CGContextSetFillColorWithColor(context, [color CGColor]);
- CGContextFillRect(context, CGRectMake(0, 0, 1, 1));
- CGContextRelease(context);
- CGColorSpaceRelease(rgbColorSpace);
- for (int component = 0; component < 3; component++) {
- components[component] = resultingPixel[component] / 255.0f;
- }
- }
- /// 开始颜色设置
- - (void)setupStartColor:(UIColor *)color {
- CGFloat components[3];
- [self getRGBComponents:components forColor:color];
- self.startR = components[0];
- self.startG = components[1];
- self.startB = components[2];
- }
- /// 结束颜色设置
- - (void)setupEndColor:(UIColor *)color {
- CGFloat components[3];
- [self getRGBComponents:components forColor:color];
- self.endR = components[0];
- self.endG = components[1];
- self.endB = components[2];
- }
- - (void)zoomForTitleWithProgress:(CGFloat)progress fromButton:(UIButton *)fromButton toButton:(UIButton *)toButton {
- CGFloat diff = _selectedItemZoomScale - 1;
- fromButton.transform = CGAffineTransformMakeScale((1 - progress) * diff + 1, (1 - progress) * diff + 1);
- toButton.transform = CGAffineTransformMakeScale(progress * diff + 1, progress * diff + 1);
- }
- #pragma mark - KVO
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
- if (object == self.bridgeScrollView) {
- if ([keyPath isEqualToString:scrollViewContentOffset]) {
- // 当scrolllView滚动时,让跟踪器跟随scrollView滑动
- [self prepareMoveTrackerFollowScrollView:self.bridgeScrollView];
- }
- } else {
- [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
- }
- }
- #pragma mark - setter
- - (void)setBridgeScrollView:(UIScrollView *)bridgeScrollView {
- _bridgeScrollView = bridgeScrollView;
- if (bridgeScrollView) {
-
- [bridgeScrollView addObserver:self forKeyPath:scrollViewContentOffset options:NSKeyValueObservingOptionNew context:nil];
- } else {
- NSLog(@"你传了一个空的scrollView");
- }
- }
- - (void)setTrackerStyle:(SPPageMenuTrackerStyle)trackerStyle {
- _trackerStyle = trackerStyle;
- switch (trackerStyle) {
- case SPPageMenuTrackerStyleLine:
- case SPPageMenuTrackerStyleLineLongerThanItem:
- case SPPageMenuTrackerStyleLineAttachment:
- self.tracker.backgroundColor = _selectedItemTitleColor;
- break;
- case SPPageMenuTrackerStyleRoundedRect:
- case SPPageMenuTrackerStyleRect:
- self.tracker.backgroundColor = [UIColor redColor];
- _selectedItemTitleColor = [UIColor whiteColor];
- // _trackerHeight是默认有值的,所有样式都会按照事先询问_trackerHeight有没有值,如果有值则采用_trackerHeight,如果矩形或圆角矩形样式下也用_trackerHeight高度太小了,除非外界用户自己设置了_trackerHeight
- _trackerHeight = 0;
- break;
- case SPPageMenuTrackerStyleTextZoom:
- // 此样式下默认1.3
- self.selectedItemZoomScale = 1.3;
- break;
- default:
- break;
- }
- }
- - (void)setBounces:(BOOL)bounces {
- _bounces = bounces;
- self.itemScrollView.bounces = bounces;
- }
- - (void)setAlwaysBounceHorizontal:(BOOL)alwaysBounceHorizontal {
- _alwaysBounceHorizontal = alwaysBounceHorizontal;
- self.itemScrollView.alwaysBounceHorizontal = alwaysBounceHorizontal;
- }
- - (void)setTrackerWidth:(CGFloat)trackerWidth {
- _trackerWidth = trackerWidth;
- CGRect trackerRect = self.tracker.frame;
- trackerRect.size.width = trackerWidth;
- self.tracker.frame = trackerRect;
- CGPoint trackerCenter = self.tracker.center;
- trackerCenter.x = _selectedButton.center.x;
- self.tracker.center = trackerCenter;
- }
- - (void)setDividingLineHeight:(CGFloat)dividingLineHeight {
- _dividingLineHeight = dividingLineHeight;
- [self setNeedsLayout];
- [self layoutIfNeeded];
- }
- - (void)setSelectedItemZoomScale:(CGFloat)selectedItemZoomScale {
- _selectedItemZoomScale = selectedItemZoomScale;
- if (selectedItemZoomScale != 1) {
- _selectedButton.transform = CGAffineTransformMakeScale(_selectedItemZoomScale, _selectedItemZoomScale);
- self.tracker.transform = CGAffineTransformMakeScale(_selectedItemZoomScale, 1);
- } else {
- _selectedButton.transform = CGAffineTransformIdentity;
- self.tracker.transform = CGAffineTransformIdentity;
- }
- }
- - (void)setShowFuntionButton:(BOOL)showFuntionButton {
- _showFuntionButton = showFuntionButton;
- self.functionButton.hidden = !showFuntionButton;
- [self setNeedsLayout];
- [self layoutIfNeeded];
- // 修正scrollView偏移
- [self moveItemScrollViewWithSelectedButton:self.selectedButton];
- }
- - (void)setFuntionButtonshadowOpacity:(CGFloat)funtionButtonshadowOpacity {
- _funtionButtonshadowOpacity = funtionButtonshadowOpacity;
- self.functionButton.layer.shadowOpacity = funtionButtonshadowOpacity;
- }
- - (void)setItemPadding:(CGFloat)itemPadding {
- _itemPadding = itemPadding;
- [self setNeedsLayout];
- [self layoutIfNeeded];
- // 修正scrollView偏移
- [self moveItemScrollViewWithSelectedButton:self.selectedButton];
- }
- - (void)setItemTitleFont:(UIFont *)itemTitleFont {
- _itemTitleFont = itemTitleFont;
- _selectedItemTitleFont = itemTitleFont;
- _unSelectedItemTitleFont = itemTitleFont;
- for (SPPageMenuItem *button in self.buttons) {
- button.titleLabel.font = itemTitleFont;
- }
- [self setNeedsLayout];
- [self layoutIfNeeded];
- // 修正scrollView偏移
- [self moveItemScrollViewWithSelectedButton:self.selectedButton];
- }
- - (void)setUnSelectedItemTitleFont:(UIFont *)unSelectedItemTitleFont {
- _unSelectedItemTitleFont = unSelectedItemTitleFont;
- for (SPPageMenuItem *button in self.buttons) {
- if (button == _selectedButton) {
- continue;
- }
- button.titleLabel.font = unSelectedItemTitleFont;
- }
- [self setNeedsLayout];
- [self layoutIfNeeded];
- // 修正scrollView偏移
- [self moveItemScrollViewWithSelectedButton:self.selectedButton];
- }
- - (void)setSelectedItemTitleFont:(UIFont *)selectedItemTitleFont {
- _selectedItemTitleFont = selectedItemTitleFont;
- self.selectedButton.titleLabel.font = selectedItemTitleFont;
- [self setNeedsLayout];
- [self layoutIfNeeded];
- // 修正scrollView偏移
- [self moveItemScrollViewWithSelectedButton:self.selectedButton];
- }
- - (void)setSelectedItemTitleColor:(UIColor *)selectedItemTitleColor {
- _selectedItemTitleColor = selectedItemTitleColor;
- [self setupStartColor:selectedItemTitleColor];
- [self.selectedButton setTitleColor:selectedItemTitleColor forState:UIControlStateNormal];
- }
- - (void)setUnSelectedItemTitleColor:(UIColor *)unSelectedItemTitleColor {
- _unSelectedItemTitleColor = unSelectedItemTitleColor;
- [self setupEndColor:unSelectedItemTitleColor];
- for (SPPageMenuItem *button in self.buttons) {
- if (button == _selectedButton) {
- continue; // 跳过选中的那个button
- }
- [button setTitleColor:unSelectedItemTitleColor forState:UIControlStateNormal];
- }
- }
- - (void)setSelectedItemIndex:(NSInteger)selectedItemIndex {
- _selectedItemIndex = selectedItemIndex;
- if (self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:selectedItemIndex];
- [self buttonInPageMenuClicked:button];
- }
- }
- - (void)setDelegate:(id<SPPageMenuDelegate>)delegate {
- if (delegate == _delegate) {return;}
- _delegate = delegate;
- if (self.buttons.count) {
- SPPageMenuItem *button = [self.buttons objectAtIndex:_selectedItemIndex];
- [self delegatePerformMethodWithFromIndex:button.tag-tagBaseValue toIndex:button.tag-tagBaseValue];
- [self moveItemScrollViewWithSelectedButton:button];
- }
- }
- - (void)setContentInset:(UIEdgeInsets)contentInset {
- _contentInset = contentInset;
- [self setNeedsLayout];
- [self layoutIfNeeded];
- // 修正scrollView偏移
- [self moveItemScrollViewWithSelectedButton:self.selectedButton];
- }
- - (void)setPermutationWay:(SPPageMenuPermutationWay)permutationWay {
- _permutationWay = permutationWay;
- [self setNeedsLayout];
- [self layoutIfNeeded];
- // 修正scrollView偏移
- [self moveItemScrollViewWithSelectedButton:self.selectedButton];
- }
- - (void)setCloseTrackerFollowingMode:(BOOL)closeTrackerFollowingMode {
- _closeTrackerFollowingMode = closeTrackerFollowingMode;
- if (closeTrackerFollowingMode) {
- self.trackerFollowingMode = SPPageMenuTrackerFollowingModeEnd;
- } else {
- self.trackerFollowingMode = SPPageMenuTrackerFollowingModeAlways;
- }
- }
- #pragma mark - getter
- - (NSArray *)items {
- if (!_items) {
- _items = [NSMutableArray array];
- }
- return _items;
- }
- - (NSMutableArray *)buttons {
-
- if (!_buttons) {
- _buttons = [NSMutableArray array];
-
- }
- return _buttons;
- }
- //竖起的line,分隔每个按钮
- - (NSMutableArray *)hLineArray {
-
- if (!_hLineArray) {
- _hLineArray = [NSMutableArray array];
-
- }
- return _hLineArray;
- }
- - (NSMutableDictionary *)setupWidths {
-
- if (!_setupWidths) {
- _setupWidths = [NSMutableDictionary dictionary];
- }
- return _setupWidths;
- }
- - (UIImageView *)tracker {
-
- if (!_tracker) {
- _tracker = [[UIImageView alloc] init];
- _tracker.layer.cornerRadius = _trackerHeight * 0.5;
- _tracker.layer.masksToBounds = YES;
- }
- return _tracker;
- }
- - (NSUInteger)numberOfItems {
- return self.items.count;
- }
- #pragma mark - 布局
- - (void)layoutSubviews {
- [super layoutSubviews];
-
- CGFloat backgroundViewX = self.bounds.origin.x+_contentInset.left;
- CGFloat backgroundViewY = self.bounds.origin.y+_contentInset.top;
- CGFloat backgroundViewW = self.bounds.size.width-(_contentInset.left+_contentInset.right);
- CGFloat backgroundViewH = self.bounds.size.height-(_contentInset.top+_contentInset.bottom);
- self.backgroundView.frame = CGRectMake(backgroundViewX, backgroundViewY, backgroundViewW, backgroundViewH);
- self.backgroundImageView.frame = self.backgroundView.bounds;
-
- CGFloat dividingLineW = self.bounds.size.width;
- CGFloat dividingLineH = (self.dividingLine.hidden || self.dividingLine.alpha < 0.01) ? 0 : _dividingLineHeight;
- CGFloat dividingLineX = 0;
- CGFloat dividingLineY = self.bounds.size.height-dividingLineH;
- self.dividingLine.frame = CGRectMake(dividingLineX, dividingLineY, dividingLineW, dividingLineH);
- CGFloat functionButtonH = backgroundViewH-dividingLineH;
- CGFloat functionButtonW = functionButtonH;
- CGFloat functionButtonX = backgroundViewW-functionButtonW;
- CGFloat functionButtonY = 0;
- self.functionButton.frame = CGRectMake(functionButtonX, functionButtonY, functionButtonW, functionButtonH);
- // 通过shadowPath设置功能按钮的单边阴影
- if (self.funtionButtonshadowOpacity > 0) {
- self.functionButton.layer.shadowPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 2.5, 2, functionButtonH-5)].CGPath;
- }
- CGFloat itemScrollViewX = 0;
- CGFloat itemScrollViewY = 0;
- CGFloat itemScrollViewW = self.showFuntionButton ? backgroundViewW-functionButtonW : backgroundViewW;
- CGFloat itemScrollViewH = backgroundViewH-dividingLineH;
- self.itemScrollView.frame = CGRectMake(itemScrollViewX, itemScrollViewY, itemScrollViewW, itemScrollViewH);
-
- // 存储itemScrollViewH,目的是解决选中按钮缩放后高度变化了的问题,我们要让选中的按钮缩放之后,依然保持原始高度
- _itemScrollViewH = itemScrollViewH;
- __block CGFloat buttonW = 0.0;
- __block CGFloat lastButtonMaxX = 0.0;
-
- CGFloat contentW = 0.0; // 内容宽
- CGFloat contentW_sum = 0.0; // 所有文字宽度之和
- NSMutableArray *buttonWidths = [NSMutableArray array];
- // 提前计算每个按钮的宽度,目的是为了计算间距
- for (int i= 0 ; i < self.buttons.count; i++) {
- SPPageMenuItem *button = self.buttons[i];
- CGFloat textW;
- CGFloat setupButtonW = [[self.setupWidths objectForKey:[NSString stringWithFormat:@"%d",i]] floatValue];
- if (button == _selectedButton) {
- textW = [button.titleLabel.text boundingRectWithSize:CGSizeMake(MAXFLOAT, itemScrollViewH) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:_selectedItemTitleFont} context:nil].size.width;
- } else {
- textW = [button.titleLabel.text boundingRectWithSize:CGSizeMake(MAXFLOAT, itemScrollViewH) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:_unSelectedItemTitleFont} context:nil].size.width;
- }
- // CGImageGetWidth获取的图片宽度是图片在@1x、@2x、@3x的位置上的实际宽度
- // button.currentImage.size.width获取的宽度永远是@1x位置上的宽度,比如一张图片在@3x上的位置为300,那么button.currentImage.size.width就为100
- CGFloat imageW = CGImageGetWidth(button.currentImage.CGImage);
- CGFloat imageH = CGImageGetHeight(button.currentImage.CGImage);
- CGFloat ratio = imageW / imageH;
- if (ratio >= 1) { // 宽大于高
- if (imageH > itemScrollViewH) { // 按比例适应在button中
- imageH = itemScrollViewH;
- imageW = imageH * ratio;
- }
- }
- if (button.currentTitle && !button.currentImage) {
- contentW = textW;
- } else if(button.currentImage && !button.currentTitle) {
- contentW = imageW;
- } else if (button.currentTitle && button.currentImage && (button.imagePosition == SPItemImagePositionRight || button.imagePosition == SPItemImagePositionLeft)) {
- contentW = textW + imageW;
- } else if (button.currentTitle && button.currentImage && (button.imagePosition == SPItemImagePositionTop || button.imagePosition == SPItemImagePositionBottom)) {
- contentW = MAX(textW, imageW);
- }
- if (setupButtonW) {
- contentW_sum += setupButtonW;
- [buttonWidths addObject:@(setupButtonW)];
- } else {
- contentW_sum += contentW;
- [buttonWidths addObject:@(contentW)];
- }
- }
- CGFloat diff = itemScrollViewW - contentW_sum;
-
- [self.buttons enumerateObjectsUsingBlock:^(SPPageMenuItem *button, NSUInteger idx, BOOL * _Nonnull stop) {
-
- CGFloat setupButtonW = [[self.setupWidths objectForKey:[NSString stringWithFormat:@"%lu",(unsigned long)idx]] floatValue];
- if (self.permutationWay == SPPageMenuPermutationWayScrollAdaptContent) {
- buttonW = [buttonWidths[idx] floatValue];
- if (idx == 0) {
- button.frame = CGRectMake(self->_itemPadding*0.5+lastButtonMaxX, 0, buttonW, itemScrollViewH);
- } else {
- button.frame = CGRectMake(self->_itemPadding+lastButtonMaxX, 0, buttonW, itemScrollViewH);
- }
- } else if (self.permutationWay == SPPageMenuPermutationWayNotScrollEqualWidths) {
- // 求出外界设置的按钮宽度之和
- CGFloat totalSetupButtonW = [[self.setupWidths.allValues valueForKeyPath:@"@sum.floatValue"] floatValue];
- // 如果该按钮外界设置了宽,则取外界设置的,如果外界没设置,则其余按钮等宽
- buttonW = setupButtonW ? setupButtonW : (itemScrollViewW-self->_itemPadding*(self.buttons.count)-totalSetupButtonW)/(self.buttons.count-self.setupWidths.count);
- if (buttonW < 0) { // 按钮过多时,有可能会为负数
- buttonW = 0;
- }
- if (idx == 0) {
- button.frame = CGRectMake(self->_itemPadding*0.5+lastButtonMaxX, 0, buttonW, itemScrollViewH);
- } else {
- button.frame = CGRectMake(self->_itemPadding+lastButtonMaxX, 0, buttonW, itemScrollViewH);
- }
-
- } else {
- self->_itemPadding = diff/self.buttons.count;
- buttonW = [buttonWidths[idx] floatValue];
- if (idx == 0) {
- button.frame = CGRectMake(self->_itemPadding*0.5+lastButtonMaxX, 0, buttonW, itemScrollViewH);
- } else {
- button.frame = CGRectMake(self->_itemPadding+lastButtonMaxX, 0, buttonW, itemScrollViewH);
- }
- }
- lastButtonMaxX = CGRectGetMaxX(button.frame);
- if(button.imagePosition == SPItemImagePositionLeft){
- //wcl - 自定义按钮分割线
- if(idx != self.hLineArray.count - 1){
- UIView *hLineView = [self.hLineArray objectAtIndex:idx];
- hLineView.frame = CGRectMake(lastButtonMaxX - 1, 15, 1, 20);
- }
- }
- }];
-
- // 如果selectedButton有缩放,走完上面代码selectedButton的frame会还原,这会导致文字显示不全问题,为了解决这个问题,这里将selectedButton的frame强制缩放
- if (!CGAffineTransformEqualToTransform(self.selectedButton.transform, CGAffineTransformIdentity)) {
- CGRect selectedButtonRect = self.selectedButton.frame;
- selectedButtonRect.origin.y = selectedButtonRect.origin.y-(selectedButtonRect.size.height*_selectedItemZoomScale - selectedButtonRect.size.height)/2;
- selectedButtonRect.origin.x = selectedButtonRect.origin.x-((selectedButtonRect.size.width*_selectedItemZoomScale - selectedButtonRect.size.width)/2);
- selectedButtonRect.size = CGSizeMake(selectedButtonRect.size.width * _selectedItemZoomScale, selectedButtonRect.size.height*_selectedItemZoomScale);
- self.selectedButton.frame = selectedButtonRect;
- }
- [self resetSetupTrackerFrameWithSelectedButton:self.selectedButton];
-
- self.itemScrollView.contentSize = CGSizeMake(lastButtonMaxX+_itemPadding*0.5, 0);
-
- if (self.translatesAutoresizingMaskIntoConstraints == NO) {
-
- [self moveItemScrollViewWithSelectedButton:self.selectedButton];
- }
-
-
- }
- - (void)resetSetupTrackerFrameWithSelectedButton:(SPPageMenuItem *)selectedButton {
-
- CGFloat trackerX;
- CGFloat trackerY;
- CGFloat trackerW;
- CGFloat trackerH;
-
- CGFloat selectedButtonWidth = selectedButton.frame.size.width;
-
- switch (self.trackerStyle) {
- case SPPageMenuTrackerStyleLine:
- {
- trackerW = _trackerWidth ? _trackerWidth : selectedButtonWidth;
- trackerH = _trackerHeight;
- trackerX = selectedButton.frame.origin.x;
- trackerY = self.itemScrollView.bounds.size.height - trackerH;
- self.tracker.frame = CGRectMake(trackerX, trackerY, trackerW, trackerH);
- }
- break;
- case SPPageMenuTrackerStyleLineLongerThanItem:
- {
- trackerW = _trackerWidth ? _trackerWidth : (selectedButtonWidth+(selectedButtonWidth ? _itemPadding : 0));
- trackerH = _trackerHeight;
- trackerX = selectedButton.frame.origin.x;
- trackerY = self.itemScrollView.bounds.size.height - trackerH;
- self.tracker.frame = CGRectMake(trackerX, trackerY, trackerW, trackerH);
- }
- break;
- case SPPageMenuTrackerStyleLineAttachment:
- {
- trackerW = _trackerWidth ? _trackerWidth : (selectedButtonWidth ? selectedButton.titleLabel.font.pointSize : 0); // 没有自定义宽度就固定宽度为字体大小
- trackerH = _trackerHeight;
- trackerX = selectedButton.frame.origin.x;
- trackerY = self.itemScrollView.bounds.size.height - trackerH;
- self.tracker.frame = CGRectMake(trackerX, trackerY, trackerW, trackerH);
- }
- break;
- case SPPageMenuTrackerStyleRect:
- {
- trackerW = _trackerWidth ? _trackerWidth : (selectedButtonWidth+(selectedButtonWidth ? _itemPadding : 0));
- trackerH = _trackerHeight ? _trackerHeight : (selectedButton.frame.size.height);
- trackerX = selectedButton.frame.origin.x;
- trackerY = (_itemScrollViewH-trackerH)*0.5;
- self.tracker.frame = CGRectMake(trackerX, trackerY, trackerW, trackerH);
- self.tracker.layer.cornerRadius = 0;
- }
- break;
- case SPPageMenuTrackerStyleRoundedRect:
- {
- trackerH = _trackerHeight ? _trackerHeight : (_itemTitleFont.lineHeight+10);
- trackerW = _trackerWidth ? _trackerWidth : (selectedButtonWidth+_itemPadding);
- trackerX = selectedButton.frame.origin.x;
- trackerY = (_itemScrollViewH-trackerH)*0.5;
- self.tracker.frame = CGRectMake(trackerX, trackerY, trackerW, trackerH);
- self.tracker.layer.cornerRadius = MIN(trackerW, trackerH)*0.5;
- self.tracker.layer.masksToBounds = YES;
- }
- break;
- default:
- break;
- }
-
- CGPoint trackerCenter = self.tracker.center;
- trackerCenter.x = selectedButton.center.x;
- self.tracker.center = trackerCenter;
- }
- - (void)dealloc {
- [self.bridgeScrollView removeObserver:self forKeyPath:scrollViewContentOffset];
- }
- @end
- #pragma clang diagnostic pop
|