iOS筆記之實現(xiàn)新聞類客戶端頂部的滾動效果

1.寫在前面:

前段時間項目用到了類似新聞類客戶端頂部的滾動條,雖然網(wǎng)上也有很多,但是本著鍛煉自己的想法,自己動手寫了一個,所幸效果不差,遂分享出來,一方面給大家參考,一方面也給自己記錄。

上效果圖:


效果

2.使用方法:

方法1:

NSArray *titleArray = @[@"推薦",@"熱點",@"視頻",@"體育",@"搞笑"];
NSMutableArray *vcArray = @[].mutableCopy;
for (int i = 0; i<titleArray.count; i++) {
    ViewController *vc = [ViewController new];
    [vcArray addObject:vc];
}
XBYTopTabBarViewController *tabVC = [[XBYTopTabBarViewController alloc] initWithSegmentTitles:titleArray childVcs:vcArray];
[self.navigationController pushViewController:tabVC animated:YES];

方法2:(推薦使用)

//新建ViewController繼承XBYTopTabBarViewController,改寫init方法
- (instancetype)init {
    if (self = [super init]) {
        NSArray *tabNames = @[@"推薦",@"熱點",@"視頻",@"體育",@"搞笑"];

        NSMutableArray *vcs = @[].mutableCopy;
        for (NSString *name in tabNames) {
            ViewController *vc = [[ViewController alloc]init];
            [vcs addObject:vc];
        }
        self = [super initWithSegmentTitles:tabNames childVcs:vcs];
    }

    return self;
}

這里是封裝的是一個ViewController,網(wǎng)上很多封裝的都是view,需要一系列配置,我覺得比較麻煩,還是繼承來的快一些,繼承XBYTopTabBarViewController以后,有多少個子項新建多個vc,調(diào)用

- (instancetype)initWithSegmentTitles:(NSArray *)titles
                             childVcs:(NSArray *)childVcs;

方法,這里繼承的vc和眾多子vc的生命周期都已經(jīng)設(shè)置好了,可以不用管了,只需要繼承(懶一點繼承也不要了,直接調(diào)用上面這個方法),其他的都不用管了。

3.實現(xiàn)思路:

這里用到了兩個scrollView
上面title一欄是一個scrollView(這里也可以用其他view,這個scrollView不需要左右滑動,但是需要響應(yīng)點擊事件),后面用smallScrollView,下面可以左右滑動的部分也是一個scrollView,后面用bigScrollView表示。
有多少個滑動項,就新建多少個label添加到smallScrollView里面:

- (void)setupSmallScrollView {
    CGFloat labelW = kScreenWidth/(self.segmentTitles.count>5?5:self.segmentTitles.count);
    self.smallScrollView.contentSize = CGSizeMake(labelW * self.segmentTitles.count, 44);
    
    CGFloat labelX,labelY = 0, labelH = smallScrollViewH;
    for (int i = 0; i < self.segmentTitles.count; i++) {
        labelX = i * labelW;
        GGSOrderStatusLabel *label = [[GGSOrderStatusLabel alloc]initWithFrame:CGRectMake(labelX, labelY, labelW, labelH)];
        label.text = self.segmentTitles[i];
        label.tag = i;
        label.userInteractionEnabled = YES;
        [label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelTapAction:)]];
        [self.smallScrollView addSubview:label];
    }
}

給label添加手勢,響應(yīng)點擊事件,同時讓bigScrollView跟隨點擊的smallScrollView的子項聯(lián)動:

- (void)labelTapAction:(UITapGestureRecognizer *)gesture {
    GGSOrderStatusLabel *titlelable = (GGSOrderStatusLabel *)gesture.view;
    if (titlelable.tag == _currentIndex) {
        return;
    }
    
    CGFloat offsetX = titlelable.tag * self.bigScrollView.frame.size.width;
    
    CGFloat offsetY = self.bigScrollView.contentOffset.y;
    CGPoint offset = CGPointMake(offsetX, offsetY);
    
    [self.bigScrollView setContentOffset:offset animated:YES];  //點擊smallScrollView的label項,bigScrollView要聯(lián)動,同時滾動。
    
}

實現(xiàn)bigScrollView的代理,讓smallScrollView跟隨它聯(lián)動:

/** 滾動結(jié)束后調(diào)用 */
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    // 獲得索引
    NSUInteger index = scrollView.contentOffset.x / self.bigScrollView.frame.size.width;
    
    // 滾動標(biāo)題欄
    GGSOrderStatusLabel *titleLable = (GGSOrderStatusLabel *)self.smallScrollView.subviews[index];
    // label居中的offsetx
    CGFloat offsetx = titleLable.center.x - self.smallScrollView.frame.size.width * 0.5;
    CGFloat offsetMax = self.smallScrollView.contentSize.width - self.smallScrollView.frame.size.width;
    if (offsetx < 0) {
        offsetx = 0;
    }else if (offsetx > offsetMax){
        offsetx = offsetMax;
    }
    CGPoint offset = CGPointMake(offsetx, self.smallScrollView.contentOffset.y);
    // 要放在gcd里才有動畫
    dispatch_async(GCD_MAINQUEUE, ^{
        [self.smallScrollView setContentOffset:offset animated:YES];
    });
    
    UIViewController *oldVC = nil;
    if (_currentIndex != -1) {
        oldVC = self.childVcs[_currentIndex];
    }
    
    UIViewController *newsVc = self.childVcs[index];
    self.currentIndex = index;
    // 其他label設(shè)置成初始狀態(tài)
    [self.smallScrollView.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if (idx != index) {
            GGSOrderStatusLabel *temlabel = self.smallScrollView.subviews[idx];
            temlabel.scale = 0.0;
        }
    }];
    
    if (newsVc.view.superview)  {//調(diào)用生命周期函數(shù)(如viewwillappear等)
        if (oldVC) {
            [newsVc beginAppearanceTransition:NO animated:YES];
            [newsVc endAppearanceTransition];
        }
        
        [newsVc beginAppearanceTransition:YES animated:YES];
        [newsVc endAppearanceTransition];
        return;
    }
    
    [self addChildViewController:newsVc];
    newsVc.view.frame = scrollView.bounds;//bounds的x就是scrollView的offsetx
    [self.bigScrollView addSubview:newsVc.view];
    [newsVc didMoveToParentViewController:self];
    
    if ([self.delegate respondsToSelector:@selector(segmentViewController:didAddChildViewController:)]) {
        [self.delegate segmentViewController:self didAddChildViewController:newsVc];
    }
}

3.其他

見下面頭文件描述:

@protocol XBYTopTabBarViewControllerDelegate <NSObject>

@optional
- (void)topTabBarViewController:(XBYTopTabBarViewController *)topTabBarVC
didAddChildViewController:(UIViewController *)childVC;

@end

@interface XBYTopTabBarViewController : UIViewController

/**
上面滑塊的標(biāo)題
*/
@property (nonatomic, strong, readonly) NSArray *segmentTitles;

/**
一個滑塊對應(yīng)一個viewController
*/
@property (nonatomic, strong, readonly) NSMutableArray *childVcs;

/**
當(dāng)前滑塊的index
*/
@property (nonatomic, assign) NSInteger currentIndex;

/**
用于存放滑塊的scrollView
*/
@property (nonatomic, strong) UIScrollView *smallScrollView;

/**
用于存放viewController的scrollView
*/
@property (nonatomic, strong) UIScrollView *bigScrollView;

@property (nonatomic, weak) id<XBYTopTabBarViewControllerDelegate> delegate;

/**
<#Description#>

@param titles 滑塊標(biāo)題數(shù)組
@param childVcs 滑塊對應(yīng)的viewController數(shù)組
@return <#return value description#>
*/
- (instancetype)initWithSegmentTitles:(NSArray *)titles
childVcs:(NSArray *)childVcs;

4.聯(lián)系方式

5.Demo:

XBYTopTabBarViewController

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,366評論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,828評論 4 61
  • 近段時間,我跟隨旅行團(tuán)來到香港,進(jìn)行了為期兩天的游玩。第一天就是過關(guān)和觀光,第二天就是購物了。 過關(guān)時經(jīng)歷了兩個黃...
    未見花閱讀 447評論 2 1
  • 那些我最最親愛的老師們啊,像春蠶,像蠟燭一樣默默奉獻(xiàn)的老師們啊,很開心生命中有你們? 最可愛的你們,節(jié)日快樂啊! ...
    關(guān)雎長樂閱讀 407評論 0 3
  • 好多美麗的成群結(jié)隊的生物 形單影只的它總喜歡默默守在它喜歡的窩和它飛過的蹤跡 我好想飛向它 我們結(jié)伴 美麗的飛
    48abeb462c7b閱讀 228評論 1 0

友情鏈接更多精彩內(nèi)容