自动滚动时如何使用 iCarousel 设置每个项目的显示时间

Posted

技术标签:

【中文标题】自动滚动时如何使用 iCarousel 设置每个项目的显示时间【英文标题】:How to set display time for each item using iCarousel when auto-scroll 【发布时间】:2017-01-12 02:41:44 【问题描述】:

正如我的标题所示,我想知道是否有一个 iCarousel 委托方法以及属性,我可以使用它来设置自动滚动时横幅视图的每个项目的显示时间。

以前,我使用 SDCycleScrollView 作为横幅视图,并在下面这样做:

- (void)cycleScrollView:(SDCycleScrollView *)cycleScrollView didScrollToIndex:(NSInteger)index 

    BannerData *data = self.bannerDatas[index];
    NSLog(@"***************cycleScrollView************************");
    NSLog(@"index --> %ld", (long)index);
    NSLog(@"banner data --> %@", data);
    NSLog(@"banner data duration --> %d", data.duration);
    cycleScrollView.autoScrollTimeInterval = data.duration;


data.duration 是每个项目保持静止的持续时间。 如何使用 iCarousel 实现这一目标?提前致谢。

到目前为止,以下是我的 iCarousel 方法:

- (NSInteger)numberOfItemsInCarousel:(__unused iCarousel *)carousel

    NSLog(@">>>>>>>>>number of items in Carousel --> %lu", (unsigned long)[self.bannerDatas count]);
    return (NSInteger)[self.bannerDatas count];


- (UIView *)carousel:(__unused iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view


    view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 520, 375)];

    NSLog(@"url --> %@", [NSURL URLWithString:[self.netImages objectAtIndex:index]]);

    [((UIImageView *)view)sd_setImageWithURL:[NSURL URLWithString:[self.netImages objectAtIndex:index]] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    view.contentMode = UIViewContentModeCenter;

    return view;


- (void)scrollToItemAtIndex:(NSInteger)index duration:(NSTimeInterval)duration

    BannerData *data = self.bannerDatas[index];
    NSLog(@"***************cycleScrollView************************");
    NSLog(@"index --> %ld", (long)index);
    NSLog(@"banner data --> %@", data);
    NSLog(@"banner data duration --> %d", data.duration);


- (CGFloat)carousel:(__unused iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value

    //customize carousel display
    switch (option)
    
        case iCarouselOptionWrap:
        
            //normally you would hard-code this to YES or NO
            return YES;
        
        case iCarouselOptionSpacing:
        
            //add a bit of spacing between the item views
            //return value * 1.05;
        
        case iCarouselOptionFadeMax:
        
//            if (self.carousel.type == iCarouselTypeCustom)
//            
//                //set opacity based on distance from camera
//                return 0.0;
//            
//            return value;
        
        case iCarouselOptionShowBackfaces:
        case iCarouselOptionRadius:
        case iCarouselOptionAngle:
        case iCarouselOptionArc:
        case iCarouselOptionTilt:
        case iCarouselOptionCount:
        case iCarouselOptionFadeMin:
        case iCarouselOptionFadeMinAlpha:
        case iCarouselOptionFadeRange:
        case iCarouselOptionOffsetMultiplier:
        case iCarouselOptionVisibleItems:
        
            return value;
        
    



#pragma mark -
#pragma mark iCarousel taps

- (void)carousel:(__unused iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index


    BannerData *data = self.bannerDatas[index];

    if (![data.playlistId isEqualToString:@""])  //Play Playlist

        CategoryDetailData *detailData = [[CategoryDetailData alloc]init];
        detailData.categoryId = data.playlistId;

        RandomSecondVC *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"RandomSecondVC"];

        vc.detailData = detailData;

        NSLog(@"vc.detailData.categoryId  --> %@", vc.detailData.categoryId );
        vc.hidesBottomBarWhenPushed = YES; //????sanit
        [self.navigationController pushViewController:vc animated:YES];

     else if (![data.url isEqualToString:@""])  //Show webview

        WebViewVC *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"WebViewVC"];
        vc.hidesBottomBarWhenPushed = YES;

        vc.navTitle = @"";
        vc.urlString = data.url;
        [self.navigationController pushViewController:vc animated:YES];

    else if (![data.videoId isEqualToString:@""])  //Play video

        VideoDetailVC *detailView = [self.storyboard instantiateViewControllerWithIdentifier:@"VideoDetailVC"];

        detailView.videoId = data.videoId;
        detailView.hidesBottomBarWhenPushed = YES; //????sanit
        [self.navigationController pushViewController:detailView animated:YES];

    

下面是我放置轮播视图的方式:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    UITableViewCell *tableCell = nil;

    if (indexPath.section == 0)  //for banner

        //++++++++++++++++++++??sanit iCarousel ver.1++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        NSLog(@"first section!!!!!!!!");
        static NSString *BannerCellIdentifier = @"BannerTableViewCell"; //original

        BannerTableViewCell *bannerCell = [tableView dequeueReusableCellWithIdentifier:BannerCellIdentifier]; //original
        //BannerTableViewCell *bannerCell = [[BannerTableViewCell alloc]init];

        [self setUpNetImages];
        bannerCell.carouselView.type = iCarouselTypeCoverFlow2;
        //bannerCell.carouselView.type = iCarouselTypeLinear;

        //bannerCell.carouselView.autoscroll = 1; //?????sanit set autoscroll

        bannerCell.carouselView.delegate = self;
        bannerCell.carouselView.dataSource =self;

        //??????sanit to fix banner timing issue first banner
        //BannerData *data0 = self.bannerDatas[1]; //???santi
        //self.cycleScrollView.autoScrollTimeInterval = data0.duration; // use this to fix timing issue of first slide
        //[bannerCell.carouselView scrollToItemAtIndex:0 duration:data0.duration];

        //bannerCell.carouselView.autoscroll = 0.8;
        //[bannerCell.carouselView scrollToItemAtIndex:0 duration:5];
        //[bannerCell.carouselView scrollToItemAtIndex:1 animated:YES];

        [bannerCell.carouselView reloadData];

        tableCell = bannerCell;

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=//

     else  //for collection cell below

        NSLog(@"not first section!!!!!!!! %d",(int)indexPath.section);

        static NSString *MainHeaderCellIdentifier = @"MainHeaderTableViewCell";

        MainHeaderTableViewCell *mainHeaderCell = (MainHeaderTableViewCell *)[tableView dequeueReusableCellWithIdentifier:MainHeaderCellIdentifier]; //original

        mainHeaderCell.collectionView = (UICollectionView *)[mainHeaderCell viewWithTag:100];
        mainHeaderCell.collectionView.delegate = self;
        mainHeaderCell.collectionView.dataSource = self;

        //NSLog(@"mainHeaderCell.index = %d",(int)mainHeaderCell.index);

        //original
        if (mainHeaderCell.collectionView == nil) 
            NSLog(@"CollectionView Nil!!!!!!!");
        

        tableCell = mainHeaderCell;
    

    return tableCell;

【问题讨论】:

【参考方案1】:

好像 iCarousel 没有这个选项,不过幸运的是,你可以自己实现这样的功能:

@property (nonatomic, strong) NSMutableDictionary *operations;
@property (nonatomic) BOOL isDragging;

- (void) carouselDidEndScrollingAnimation:(iCarousel *)carousel
    
    if (!self.isDragging)
        NSNumber *tag = @(carousel.tag);
        [self.operations[tag] cancel];
        self.operations[tag] = [NSBlockOperation blockOperationWithBlock:^
            double duration = [self durationForItemAtIndex:carousel.currentItemIndex inCarousel:carousel];
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^
                NSInteger i = carousel.currentItemIndex + 1;
                NSInteger next = i < carousel.numberOfItems ? i : 0;
                [carousel scrollToItemAtIndex:next animated:YES];
            );
        ];
        [(NSOperation*)(self.operations[tag]) start];
    


- (void) carouselWillBeginDragging:(iCarousel *)carousel

    [self.operations[@(carousel.tag)] cancel];
    self.isDragging = YES;


- (void) carouselDidEndDragging:(iCarousel *)carousel willDecelerate:   (BOOL)decelerate
    
    self.isDragging = NO;


- (double) durationForItemAtIndex:(NSInteger)index inCarousel:(iCarousel*)carousel
    
    return <appropriate_duration_for_particular_carousel_and_item_index_in_it>;


- (void) startCarousel:(iCarousel*)carousel

    [self carouselDidEndScrollingAnimation:carousel];

更新-[tableView:cellForRowAtIndexPath:]方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    <...>

    if (indexPath.section == 0) 
        <...>

        bannerCell.carouselView.tag = indexPath.row;
        [self startCarousel:bannerCell.carouselView];
     else 
        <...>
    

    return tableCell;

并且不要忘记在使用前在某处初始化operations 字典:

self.operations = [NSMutableDictionary new];

但是,所有这些都是草稿 - 您可能需要根据需要调整和升级这些 sn-ps。

【讨论】:

谢谢,但我一直不知道如何引用我的 Carousel 视图,因为它是我的 tableview 单元格的属性。有关更多详细信息,请参阅我的 tableView cellForRowAtIndexPath。所以我不能只使用 self.carousel。 非常感谢。几乎解决了我的问题,因为我想做的一件事是获取每个项目的持续时间数据并用该值替换&lt;appropriate_duration_for_particular_carousel_and_item_index_in_it&gt;。这就是我在 durationForItemAtIndex 中所做的。 BannerData *data = self.bannerDatas[index]; return data.duration; 但它崩溃了。 崩溃是这样 *** 由于未捕获的异常 'NSRangeException' 导致应用程序终止,原因:'*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]' 那里'是 5 个项目,所以它是 0 到 4,但似乎超出了这个范围。 但我已经有了这个- (NSInteger)numberOfItemsInCarousel:(__unused iCarousel *)carousel NSLog(@"&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;number of items in Carousel --&gt; %lu", (unsigned long)[self.bannerDatas count]); return (NSInteger)[self.bannerDatas count]; ,所以它应该知道 Carousel 应该有多少项目,对吧? @SanitLee 你确定你不会同时在任何地方改变bannerDatas 吗? setUpNetImages 是做什么的?此外,对于每个轮播,您是否有单独的 bannerDatas 数组,或者它是唯一的?在这种情况下,所有轮播应具有相同数量的项目。

以上是关于自动滚动时如何使用 iCarousel 设置每个项目的显示时间的主要内容,如果未能解决你的问题,请参考以下文章

旋转后的错误,使用 iCarousel 作为滚动视图

iCarousel 自动滚动效果

线性 iCarousel 中的页面在水平滚动时向上移动?

如何在点击/选择时替换 iCarousel 中的特定视图?

iCarousel 配置任务

iCarousel 滚动