17

What I had done :-

I had added the code which plays a video when cell is fully visible and when I scrolls down or up it reload the tableview again and plays video again. But, my requirement is different.

What I actually want :

I want to play a video untill the backward or forward cell fully visible. When user scroll downs or up it doesn’t affect untill the backward or forward cell fully visible.

Design

Table Cell Layout Description
-> Video Table Cell (Fix height 393) 
    -> Content View
    -> Main view - (as per Content view of Table view Cell)
        -> Title View (0, 0, MainView.width, 57)
        -> Video View (0, 57, MainView.width, 200);
        -> Description View (0, 257, MainView.width, 136) 

Coding :

VideoTableCell.h

#import <UIKit/UIKit.h>

#import <AVFoundation/AVFoundation.h>



@interface VideoTableCell : UITableViewCell

@property (strong, nonatomic) IBOutlet UIView *viewForVideo;

@property (strong, nonatomic) IBOutlet UIImageView *imgThumb;

@property (strong, nonatomic) IBOutlet UIButton *btnPlay;

@property (strong, nonatomic) AVPlayerItem* videoItem;

@property (strong, nonatomic) AVPlayer* videoPlayer;

@property (strong, nonatomic) AVPlayerLayer* avLayer;



@end

VideoTableCell.m

#import "VideoTableCell.h"

@implementation VideoTableCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    return self;
}
- (void)layoutSubviews
{
    [super layoutSubviews];
     [self.avLayer setFrame:CGRectMake(self.viewForVideo.frame.origin.x, self.viewForVideo.frame.origin.y, self.viewForVideo.frame.size.width,  self.viewForVideo.frame.size.height)];

}

@end

VideoVC.h

#import <UIKit/UIKit.h>

#import <AVFoundation/AVFoundation.h>

@interface VideoVC : UIViewController <UITableViewDataSource, UITableViewDelegate>

@property (strong, nonatomic) IBOutlet UITableView *tblData;

@end

VideoVC.m

#import "VideoVC.h"

#import "VideoTableCell.h"



@interface VideoVC ()

{
    NSArray *arrVideo ;
    bool isScrolling;
    int index;
BOOL fullvisible ;

}
@end  

@implementation VideoVC

- (void)viewDidLoad {

    [super viewDidLoad];    

    arrVideo = [[NSArray alloc]initWithObjects:@"http://video/1.mp4",@"http://video/2.mp4", @"http://video/3.mp4", @"http://video/4.mp4", @"http://video/5.mp4", nil];

    fullvisible = YES;   
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return arrVideo.count;
}

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    VideoTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"VideoTableCell"];
    if (cell == nil)
    {
        cell = [[[NSBundle mainBundle] loadNibNamed:@"VideoTableCell" owner:self options:nil]objectAtIndex:0];
    }

    int temp =  [self getVisibleIndex];

    if (temp == indexPath.row && fullvisible)
    {
            cell.imgThumb.hidden = YES ;
            //NSLog(@"fullvisible == 1");
            NSURL *url = [NSURL URLWithString:[arrVideo objectAtIndex:indexPath.row]];

            cell.videoItem = [AVPlayerItem playerItemWithURL:url];
            cell.videoPlayer = [AVPlayer playerWithPlayerItem:cell.videoItem];
            cell.avLayer = [AVPlayerLayer playerLayerWithPlayer:cell.videoPlayer];

            [cell.avLayer setBackgroundColor:[UIColor whiteColor].CGColor];
            // [cell.avLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
            [cell.contentView.layer addSublayer:cell.avLayer];
            [cell.videoPlayer play];

            [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
    }
    else
    {
            cell.imgThumb.hidden = NO ;
            cell.videoPlayer = nil;
            [cell.avLayer removeFromSuperlayer];
            cell.videoItem = nil;
            [cell.videoPlayer pause];
    }
    return cell ;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 393 ;
}


-(int)getVisibleIndex

{   
    for (NSIndexPath *indexPath in _tblData.indexPathsForVisibleRows) {

        CGRect cellRect = [_tblData rectForRowAtIndexPath:indexPath];
        BOOL isVisible = CGRectContainsRect(_tblData.bounds, cellRect);

        if (isVisible)

        {
            index = (int)indexPath.row ;
        }
    }
    return index ;
}

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView

{

    NSArray* cells = _tblData.visibleCells;

    for (VideoTableCell* cell in cells)

    {

            NSIndexPath *path = [_tblData indexPathForCell:cell] ;

            index =(int) path.row;

            fullvisible = YES;

            [_tblData reloadData];

    }
}
Aarti Oza
  • 1,104
  • 2
  • 13
  • 31
  • Maybe by setting the `actionAtItemEnd` to pause, checking with KVO the status of pause, checking if `player.currentTime == player.currentItem.duration` (that's what you want), and playing next item if that's the case. In other words, creating a micro-pause between items... – Larme Jan 13 '16 at 16:46
  • Try this answer: [http://stackoverflow.com/questions/9831485/best-way-to-check-if-uitableviewcell-is-completely-visible](http://stackoverflow.com/questions/9831485/best-way-to-check-if-uitableviewcell-is-completely-visible) – Devanshu Saini Jan 25 '16 at 07:11

3 Answers3

16

Every UITableViewCell subclass has a method prepareForReuse: so in your VideoTableCell just add a method:

-(void)prepareForReuse {
   [super prepareForReuse];
   [self.videoPlayer play];
}

And in your controller implement a delegate method: - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

   [cell stopVideo];
}

and in stopVideo just add [self.videoPlayer pause] or [cell.videoPlayer stop]

Jakub
  • 12,851
  • 13
  • 75
  • 130
5

try this methods in UITableView

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    // stop video
}

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    // play video
}

should help you.

If this will not fully work for your requirements try override scrollViewDidScroll more details there

Community
  • 1
  • 1
MaeSTRo
  • 345
  • 2
  • 6
  • 18
-2

Write a category for UITableViewCell to check if the cell is fully visible:

UITableViewCell+FullyVisible

 -(BOOL) isFullyVisible {

UITableView *tableview = (UITableView *)[self parents:[UITableView class]];
CGRect rect = [tableview rectForRowAtIndexPath:[tableview indexPathForCell:self]];
rect = [tableview convertRect:rect toView:tableview.superview];
return CGRectContainsRect(tableview.frame, rect);
}

And in cellForRowAtIndexpath: check if cell is fully visible. If cell is fully visible play video else stop/pause.

Community
  • 1
  • 1