I am trying to achieve a iCarousel of Video URLS to allow users to see others posts.
Now i have to say i love iCarousel and this has been my only issue with it.
I have the right number of carousel objects showing up and the play button is on all of them though i'm only receiving one video at a time and the controls are not playing the video properly.
I have an NSMutableArray in place holding the _videoURLS, this is where i provide the number of carousel objects that need to be via [_videoURLS count];
In my .m file this is how i am preparing the video player with the carousel object
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
if (view == nil)
{
UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 370.0f)];
view = mainView;
CGFloat mainViewWidth = mainView.bounds.size.width;
//Video Player View
_videoView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, mainViewWidth, 220)];
_videoView.backgroundColor = [UIColor colorWithRed:123/255.0 green:123/255.0 blue:123/255.0 alpha:1.0];
_videoView.center = CGPointMake(100, 170);
_videoView.tag = 7;
[view addSubview:_videoView];
//video
_player = [[MPMoviePlayerController alloc] init];
[_player.view setFrame:_videoView.bounds];
[_player prepareToPlay];
[_player setShouldAutoplay:NO];
_player.scalingMode = MPMovieScalingModeAspectFit;
_player.controlStyle = MPMovieControlStyleNone;
[_videoView addSubview:_player.view];
//Play Button
_playButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 60.0f, 60.0f)];
[_playButton setBackgroundImage:[UIImage imageNamed:#"play-icon-grey.png"] forState:UIControlStateNormal];
[_playButton addTarget:self.view.superview action:#selector(postThread:) forControlEvents:UIControlEventTouchUpInside];
_playButton.center = CGPointMake(100, 160);
_playButton.tag = 3;
[view addSubview:_playButton];
}
else
{
//get a reference to the label in the recycled view
_playButton = (UIButton *) [view viewWithTag:3];
_videoView = (UIView *) [view viewWithTag:7];
}
//Setting Video For Each Carousel
for (int i = 0; i < 9; i++) {
[_player setContentURL:[NSURL URLWithString:[_videoURLS objectAtIndex:index]]];
NSLog(#"Object Link: %#",[_videoURLS objectAtIndex:index]);
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didFinishPlaying:) name:MPMoviePlayerPlaybackDidFinishNotification object:_player];
return view;
}
It works very well if i have one object in the carousel and can handle just one video, i have to be able to handle 10 videos on the carousel and if possible have them load when its focused.
From Personal experience i feel it would be the way each item is being drawn to the screen, i just cant get my finger on the issue.
Any help is greatly appreciated!!
Per the apple documentation I found out this is not capable of being done, I have chose to use the AVFoundation Framework
Related
I am using a UICollectionView with paging feature and adding AVPlayer on each cell to play video with URL, but my collection view is giving a strange behavior. When it loads the first cell and video starts playing then it is fine but when I slide and load the next cell then both videos are playing together, while I want the previous one to stop playing. I tried many thing to resolve this issue but nothing is working, someone please suggest me something to work with this. My code of custom cell class where I am adding AVPlayer is given below:
[self.avPlayer pause];
self.avPlayer = nil;
[self.avLPlayer removeFromSuperlayer];
CGRect videoRect;
videoRect = CGRectMake(0,0,[[UIScreen mainScreen]bounds].size.width,[[UIScreen mainScreen]bounds].size.height);
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[indicator startAnimating];
[indicator bringSubviewToFront:_viewForShowVideo];
UIWindow* currentWindow = [UIApplication sharedApplication].keyWindow;
indicator.frame = CGRectMake(currentWindow.frame.size.width/2, _viewForShowVideo.frame.size.height/2, 20, 20);
[_viewForShowVideo addSubview:indicator];
self.avPlayerItem = [AVPlayerItem playerItemWithURL:Url];
self.avPlayer = [AVPlayer playerWithPlayerItem:self.avPlayerItem];
self.avLPlayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
[_avLPlayer setFrame:videoRect];
[_avLPlayer setBackgroundColor:[UIColor blackColor].CGColor] ;
[_avLPlayer setVideoGravity:AVLayerVideoGravityResizeAspect];
_avLPlayer.opacity = 1;
_avPlayer.allowsExternalPlayback = NO;
[_avPlayer setMuted:NO];
_avPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[[AVAudioSession sharedInstance]setCategory: AVAudioSessionCategoryPlayback error: nil];
[_viewForShowVideo.layer addSublayer:_avLPlayer];
[_avPlayer play];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnPlayer:)];
[_viewForShowVideo addGestureRecognizer:tgr];
[_viewForShowVideo setBackgroundColor:[UIColor greenColor]];
I know possibly this is duplicate question but the question which is already exist didn't have an solution so , I'm asking again to possibly start bounty question .
Here is my code which is working below iOS 11 :
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
// create a player view controller
avcontroller = [[AVPlayerViewController alloc]init];
avcontroller.player = player;
[player play];
NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
[noteCenter addObserverForName:AVPlayerItemDidPlayToEndTimeNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
NSLog(#"Video end");
self.avcontroller.player = nil;
[self.avcontroller.view removeFromSuperview];
[self.view addSubview:delegate.tabViewControllerObj.tabBarController.view];
}];
_skip =[UIButton buttonWithType:UIButtonTypeCustom];
[_skip addTarget:self action:#selector(btnSkipTapped)
forControlEvents:UIControlEventTouchUpInside];
[_skip setTitle:#"Skip" forState:UIControlStateNormal];
_skip.layer.borderWidth = 2.0f;
_skip.layer.cornerRadius = 12;
_skip.clipsToBounds = YES;
_skip.layer.borderColor = [UIColor whiteColor].CGColor;
// show the view controller
[self addChildViewController:avcontroller];
[avcontroller.view addSubview:_skip];
[avcontroller.view bringSubviewToFront:_skip];
[self.view addSubview:avcontroller.view];
avcontroller.view.frame = self.view.frame;
}
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
_skip.frame = CGRectMake((self.view.frame.size.width-140),(self.view.frame.size.height-150),100.0,35.0);
}
And here is button tapped function:
- (IBAction)btnSkipTapped{
NSLog(#"Skip button clicked");
self.avcontroller.player = nil;
[self.avcontroller.view removeFromSuperview];
[self.view addSubview:delegate.tabViewControllerObj.tabBarController.view];
}
This code will display button perfectly but upon button tap , it didn't call btnSkipTapped function.
Any help would be appreciated !
#DeepShah you have added skip button in avcontroller.view so its display proper but you can't click on it because AVPlayerViewControllerContentView covers that skip button.
see below image :
so you have to add skip button in self.view and its works.
[self.view addSubview:_skip];
[self.view bringSubviewToFront:_skip];
What I am trying to achieve
I would like to display a carousel of videos that play independently. No more than 10 at a time. as well as having their own play button per carousel object to play independently.
What I am getting
After 3 Items display in the carousel it displays the same three over and over again until it reaches the end of the 10 items.
I am assigning the AVAsset like below:
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:[_videoURLS objectAtIndex:index]] options:nil];
_videoURLS is an NSMutableArray of NSStrings it returns a 10 count to populate 10 items in the carousel like below.
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
//return the total number of items in the carousel
return [_videoURLS count];
}
Now to populate the Video View I am doing the below:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:[_videoURLS objectAtIndex:index]] options:nil];
//create new view if no view is available for recycling
if (view == nil)
{
//don't do anything specific to the index within
//this `if (view == nil) {...}` statement because the view will be
//recycled and used with other index values later
UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 370.0f)];
view = mainView;
CGFloat mainViewWidth = mainView.bounds.size.width;
//Video Player View
_videoView = [[UIView alloc] initWithFrame:CGRectMake(0,0, mainViewWidth, 220)];
_videoView.backgroundColor = [UIColor colorWithRed:123/255.0 green:123/255.0 blue:123/255.0 alpha:1.0];
_videoView.center = CGPointMake(100, 170);//170
_videoView.tag = 20;
[view addSubview:_videoView];
//AV Asset Player
AVPlayerItem * playerItem = [[AVPlayerItem alloc] initWithAsset:asset];
_player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
playerLayer.frame = _videoView.bounds;
[_videoView.layer addSublayer:playerLayer];
[_player seekToTime:kCMTimeZero];
//Play Button
_playButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 60.0f, 60.0f)];
[_playButton setBackgroundImage:[UIImage imageNamed:#"play-icon-grey.png"] forState:UIControlStateNormal];
[_playButton addTarget:self action:#selector(playVideo:) forControlEvents:UIControlEventTouchUpInside];
_playButton.center = CGPointMake(100, 160);
_playButton.tag = 1;
[view addSubview:_playButton];
}
else
{
//get a reference to the label in the recycled view
_playButton = (UIButton *) [view viewWithTag:1];
_videoView = (UIView *) [view viewWithTag:20];
}
//set item label
//remember to always set any properties of your carousel item
//views outside of the `if (view == nil) {...}` check otherwise
//you'll get weird issues with carousel item content appearing
//in the wrong place in the carousel
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didFinishPlaying:) name:MPMoviePlayerPlaybackDidFinishNotification object:_player];
return view;
}
I handle the play button like below:
-(IBAction)playVideo:(id)sender {
if (_playButton.isHidden) {
[_playButton setHidden:NO];
}else{
[_playButton setHidden:YES];
[_player play];
}
}
Though when I press the play button it plays the second video in the carousel.
What is the proper way to handle this and have all the videos play single handed?
I have added Google maps sdk for ios to my Iphone app, and i have some custom markers if clicked info window pops up with title, how can i add a button to this info window so if pressed will go to new page? Now i have tryed to use this post to solve this issue Adding Click Event on InfoWindow/Marker in Google Maps SDK for native iOS/objective C it doesnt give me error but it won't work.
this is what i want my result to be:http://www.flickr.com/photos/74719051#N05/6728157477/
The answer for the question you linked shows code for using MapKit, so it wouldn't work with the Google Maps SDK for iOS.
See this question for how to return a custom view with the Google Maps SDK for iOS:
Custom annotation view in Google Maps SDK
However note that according to this question, it looks like what is displayed might be a visual copy of the view not the actual view, which might limit the interaction you can do with the view:
Add buttons to view returned by markerInfoWindow delegate method
Simply detecting a tap on the info window and going to a different page should be possible using didTapWindowOfMarker though.
Note that there's a feature request in Google's issue tracker to add direct support for this:
https://code.google.com/p/gmaps-api-issues/issues/detail?id=4961
This code does exactly what you want. It's inspired by #9 in the link recommended by Saxon Druce but done differently and more complete. It detects tap on buttons added to my custom infoWindow. I create a custom infoWindow with 2 fake buttons (they could actually be replaced by images because they won't trigger any action anyway) and I add a transparent UIView with 2 real but transparent buttons over the infoWindow. These buttons will trigger the actions.
Finally, I use a few delegate methods or KVC in order to move the overlaid UIView when the infoWindow itself moves.
- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
[self.actionOverlayCalloutView removeFromSuperview];
UIView *calloutView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, infoWindowWidth, infoWindowHeight)];
float offset = anchorSize * M_SQRT2;
CGAffineTransform rotateBy45Degrees = CGAffineTransformMakeRotation(M_PI_4);
UIView *arrow = [[UIView alloc] initWithFrame:CGRectMake((infoWindowWidth - anchorSize)/2.0, infoWindowHeight - offset, anchorSize, anchorSize)];
arrow.transform = rotateBy45Degrees;
arrow.backgroundColor = [UIColor lightGrayColor];
[calloutView addSubview:arrow];
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, infoWindowWidth, infoWindowHeight - offset/2)];
[contentView setBackgroundColor:[UIColor whiteColor]];
contentView.layer.cornerRadius = 5;
contentView.layer.masksToBounds = YES;
contentView.layer.borderColor = [UIColor lightGrayColor].CGColor;
contentView.layer.borderWidth = 1.0f;
self.actionOverlayCalloutView =
[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:contentView]]; //hack to copy a view...
self.actionOverlayCalloutView.backgroundColor = [UIColor lightGrayColorWithAlpha:0.5];
self.actionOverlayCalloutView.layer.cornerRadius = 5;
NSMutableArray *falseButtons = [NSMutableArray array];
NSMutableArray *actionButtons = [NSMutableArray array];
PointMapItem *pointAnnotation = marker.userData;
if ([pointAnnotation canPerformSend]) {
UIButton *button = [[UIButton alloc] init];
[button setImage:[UIImage imageNamed:#"imageButton1.png"] forState:UIControlStateNormal];
[falseButtons addObject:button];
UIButton *activableButton = [[UIButton alloc] init];
[activableButton addTarget:self action:#selector(onButton1Clicked) forControlEvents:UIControlEventTouchUpInside];
[actionButtons addObject:activableButton];
}
if ([pointAnnotation canPerformShowDetails]) {
UIButton *button = [[UIButton alloc] init];
[button setImage:[UIImage imageNamed:#"imageButton1.png"] forState:UIControlStateNormal];
[falseButtons addObject:button];
UIButton *activableButton = [[UIButton alloc] init];
[activableButton addTarget:self action:#selector(onButton2Clicked) forControlEvents:UIControlEventTouchUpInside];
[actionButtons addObject:activableButton];
}
int buttonWidth = contentView.frame.size.width / [falseButtons count];
int currentOffset = 0;
for (int i=0; i<falseButtons.count; i++) {
UIButton *falseButton = [falseButtons objectAtIndex:i];
UIButton *activableButton = [actionButtons objectAtIndex:i];
[falseButton setFrame:CGRectMake(currentOffset, 0, buttonWidth, contentView.frame.size.height)];
currentOffset += buttonWidth;
activableButton.frame = falseButton.frame;
[activableButton setTitle:#"" forState:UIControlStateNormal];
[self.actionOverlayCalloutView addSubview:activableButton];
[contentView addSubview:falseButton];
}
[calloutView addSubview:contentView];
CLLocationCoordinate2D anchor = [self.mapView.selectedMarker position];
CGPoint point = [self.mapView.projection pointForCoordinate:anchor];
point.y -= self.mapView.selectedMarker.icon.size.height + offset/2 + (infoWindowHeight - offset/2)/2;
self.actionOverlayCalloutView.center = point;
[self.mapView addSubview:self.actionOverlayCalloutView];
return calloutView;
}
- (void)mapView:(GMSMapView *)pMapView didChangeCameraPosition:(GMSCameraPosition *)position {
if (pMapView.selectedMarker != nil && self.actionOverlayCalloutView.superview) {
CLLocationCoordinate2D anchor = [self.mapView.selectedMarker position];
CGPoint point = [self.mapView.projection pointForCoordinate:anchor];
float offset = anchorSize * M_SQRT2;
point.y -= self.mapView.selectedMarker.icon.size.height + offset/2 + (infoWindowHeight - offset/2)/2;
self.actionOverlayCalloutView.center = point;
} else {
[self.actionOverlayCalloutView removeFromSuperview];
}
}
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
[self.actionOverlayCalloutView removeFromSuperview];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"mapView.selectedMarker"]) {
if (!self.mapView.selectedMarker) {
[self.actionOverlayCalloutView removeFromSuperview];
}
}
}
- (void)onButton2Clicked {
//your code
self.mapView.selectedMarker = nil;
}
- (void)onButton1Clicked {
// your code;
self.mapView.selectedMarker = nil;
}
Swift 3.0 solution for button handling on CustomInfoWindow
https://stackoverflow.com/a/40681031/3933302
More more detail visit this blog
Custom and interactive googlemaps(IOS SDK) infowindow
1)Create one subview which you want to show in infoWindow.
2)Set frame of subview equals to frame of infoWindow view.
subView = [[[NSBundle mainBundle] loadNibNamed:#"viewName" owner:self options:nil] objectAtIndex:0];
[subView setFrame:infoview.frame];
[self.mapview addSubview:subView];
i am using MPMovieplayerController for playing video, while im clicking some other button i.e i want to pause my video wherever its playing again. i click play means i want to play while its pausing.But for me now when i click button means my video was stopped.But i want to pause instead of stop.
My sample code here
- (IBAction) playvideo
{
NSURL *url = [NSURL URLWithString:#"http://xyz/video1.mp4"];
movieplayer = [[[MPMoviePlayerController alloc]initWithContentURL:url] retain];
movieplayer.view.frame=CGRectMake(25,54,658,460);
[self.view addSubview:movieplayer.view];
[movieplayer play];
}
-(void)buttononclick
{
[movieplayer pause];
[movieplayer.view removeFromSuperview];
for (int i = 0; i < 13; i++)
{
CGRect frame;
frame.origin.x = 150 * i;
frame.origin.y = 0;
frame.size = CGSizeMake(140, self.scrollView.frame.size.height);
[scrollView setShowsHorizontalScrollIndicator:NO];
UIImageView *temp1 = [[UIImageView alloc] initWithFrame:CGRectMake(25, 7, 75, 75)];
[temp1 setImage:[UIImage imageNamed:#"sti15.png"]];
[self.scrollView addSubview:temp1];
UIImageView *temp2 = [[UIImageView alloc] initWithFrame:CGRectMake(110, 7, 75, 75)];
[temp2 setImage:[UIImage imageNamed:#"sti16.png"]];
[self.scrollView addSubview:temp2];
UIImageView *temp3 = [[UIImageView alloc] initWithFrame:CGRectMake(195, 7, 75, 75)];
[temp3 setImage:[UIImage imageNamed:#"sti17.png"]];
[self.scrollView addSubview:temp3];
}
self.scrollView.contentSize = CGSizeMake(165 * 10, self.scrollView.frame.size.height);
self.scrollView.pagingEnabled=0;
}
- (void)viewDidDisappear:(BOOL)animated
{
// [self setDescText:nil];
[super viewDidDisappear:animated];
[movieplayer pause];
[movieplayer.view removeFromSuperview];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ((movie.playbackState==MPMoviePlaybackStateStopped)||(movie.playbackState==MPMoviePlaybackStatePaused))
{
[movie play];
}
else
{
[movie pause];
}
}
Try this Code , it will Work
Check out the notifications for MPMoviePlaybackStatePlaying, MPMoviePlaybackStateStopped, MPMoviePlaybackStatePaused, and MPMoviePlaybackStateInterrupted.
Something like:
MPMoviePlayerController *player = notification.object;
/* Playback is currently stopped. */
if (player.playbackState == MPMoviePlaybackStateStopped)
{
NSLog(#"MPMoviePlaybackStateStopped");
}
/* Playback is currently under way. */
else if (player.playbackState == MPMoviePlaybackStatePlaying)
{
NSLog(#"MPMoviePlaybackStatePlaying");
}
/* Playback is currently paused. */
else if (player.playbackState == MPMoviePlaybackStatePaused)
{
NSLog(#"MPMoviePlaybackStatePaused");
}
You can wire up your target action something like this:
if ((_moviePlayer.playbackState == MPMoviePlaybackStateStopped) || (_moviePlayer.playbackState == MPMoviePlaybackStatePaused)) {
[_moviePlayer play];
} else {
[_moviePlayer pause];
}
you can add target to the play/pause button.
but first you need to catch the button of the mpmovieplayerview.
step 1 list the button. method reference from here
call this method from when the button appear(the video is ready).
But remember, this will also catch the full screen button and airplay button.(if available)
- (void)CatchSubviewsOfView:(UIView *)view {
// Get the subviews of the view
NSArray *subviews = [view subviews];
for (UIView *subview in subviews) {
// Do what you want to do with the subview
NSLog(#"%#", subview);
if(subview isKindOfClass:[UIButton class]]){
// add your target here
[subview addTarget:self action:#selector(extraAction:) forControlEvents:UIControlEventTouchUpInside];
}
// List the subviews of subview
[self listSubviewsOfView:subview];
}
}
step 2 implement the action
-(IBAction)extraAction:(id)sender{
NSLog(#"some extraAction");
}
call the catch method sample.
[self CatchSubviewOfView:movieplayer.view];