Placing UIPopover correctly next to dynamic buttons - ios

I'm creating a dynamic number of buttons(eventually, these will be placed inside a horizontal scroll view), and I'm displaying a popover when a button is pressed, but I need to set the popover to appear just to the right of the selected button, but at the moment, the popover appears at the same place every time...
This is what I'm trying:
for (int i=0; i < 10; i++) {
childButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
childButton.frame = CGRectMake(100*i, 170, 100, 30);
[childButton setTitle:#"Test" forState:UIControlStateNormal];
[childButton addTarget:self action:#selector(presentPopoverMenu) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:childButton];
}
Ultimately I'm going to create two rows of images, but this is just for testing...
-(void)presentPopoverMenu/*:(id)sender*/
{
MenuPickerController *mp = [[MenuPickerController alloc] init];
popoverMenu = [[UIPopoverController alloc] initWithContentViewController:mp];
popoverMenu.popoverContentSize = CGSizeMake(290, 300);
[popoverMenu presentPopoverFromRect:[childButton bounds]
inView:childButton
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:NO];
}
I'm thinking that it's probably just taking the value from last button, but I'm not sure, how I would do this otherwise...

Of course it uses last button value, because your ivar childButton points on it. Take not childButton but sender. Uncomment it and use. Also selector will be #selector(presentPopoverMenu:).

Related

Custom button in AVPlayerViewController.ContentOverlayView

I need to add a custom button to the AVPlayerViewController that will appear in both fullscreen and non-fullscreen for an app running iOS 8.
Adding a button to the AVPlayerViewController.view or the containing view will work for non-fullscreen but when the player switches to fullscreen the button is no longer visible. I have found that if I add a button to the AVPlayerViewController.ContentOverlayView then it appears in fullscreen and non-fullscreen, but then it doesn't appear that the ContentOverlayView responds to any touches so the button cannot be clicked. Does anyone know of a different place to add the button or a way to make the ContentOverlayView respond to touches?
Example Code
AVPlayerViewController *playerView = [[AVPlayerViewController alloc] init];
playerView.player = [AVPlayer playerWithURL:movieURL];
CGRect viewInsetRect = CGRectInset ([self.view bounds],
kMovieViewOffsetX,
kMovieViewOffsetY );
/* Inset the movie frame in the parent view frame. */
[[playerView view] setFrame:viewInsetRect];
[self.view addSubview: [playerView view]];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.backgroundColor = [UIColor yellowColor];
btn.frame = CGRectMake(50, 50, 200, 75);
[btn addTarget:self action:#selector(didSelectButton:) forControlEvents:UIControlEventTouchUpInside];
[btn setUserInteractionEnabled:YES];
[btn setEnabled:YES];
[playerView.contentOverlayView addSubview:btn];
I managed to get this working by adding the following to my AVPlayerViewController in IB:
An overlay view with a button inside it
Add constraints to center the button in the overlay view
Created an IBOutlet to the view (I called it 'overlay')
Created an action from the button to AVPlayerViewController that prints something so that we can see that tapping the button is working
Dragged the overlay view out of the view hierarchy and onto the top bar of the view controller (appears as a view icon in top bar of the view controller along with the exit icon etc)
and then in the code for the AVPlayerViewController:
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.overlay)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.overlay.frame = self.view.bounds
}
#IBAction func playBtnTapped(sender: AnyObject) {
println("PlayBtnTapped")
}
The button is now centered in fullscreen/normal viewing and the button works
I had the same predicament just now.
Instead of:
[playerView.contentOverlayView addSubview:btn];
use (after you add the playerView)
[self.view addSubview:btn];
This will add the button in the minimised player.
Now for the fullscreen I didn't found any other reliable method of checking if the player went fullscreen or back, so here is a a solution:
self.windowChecker = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(checkIfFullscreen) userInfo:nil repeats:YES];
and this:
-(void)checkIfFullscreen{
NSLog(#"videoBounds\n %f %f ", self.avVideoPlayer.contentOverlayView.frame.size.width,self.avVideoPlayer.contentOverlayView.frame.size.height);
if ([self playerIsFullscreen]) { // check the frame on this
for(UIWindow* tempWindow in [[UIApplication sharedApplication]windows]){
for(UIView* tempView in [tempWindow subviews]){
if ([[tempView description] rangeOfString:#"UIInputSetContainerView"].location != NSNotFound){
UIButton *testB = [[UIButton alloc] initWithFrame: CGRectMake(20, 20, 400, 400)];
testB.backgroundColor = [UIColor redColor];
[testB addTarget:self action:#selector(buttonTouch) forControlEvents:UIControlEventTouchDown];
[tempView addSubview:testB];
break;
}
}
}
}
}
I know this is a not a nice way to do it, but it is the only way I managed to add some custom UI that also receives touch events on the player.
Cheers!

how can i move one screen to another dynamically in ios?

I am creating 5 buttons dynamically in my project.
Now I want code for each of the dynamic buttons to move to the next screen when I click a button.
If you have sample example same like my requirement then please post here.
I know its very easy for drag and drop control to connect next form but I want to do that dynamically.
Code I have so far:
for (i = 1; i <= 5; i++) {
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
aButton.frame = CGRectMake(xCoord, yCoord, buttonWidth, buttonHeight);
[
aButton addTarget:self action:#selector(whatever:)
forControlEvents:UIControlEventTouchUpInside
];
[scrollView addSubview:aButton];
yCoord += buttonHeight + buffer;
}
You can push a new UIViewController programmatically
Refer to this answer: Push another View in UINavigationController?
See this answer for using Nibs: Navigation Controller Push View Controller
UIViewController *viewController = [[UIViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];

Screen with different options for autorotate

I have a view with a collection of images. If the image is clicked then I show it full screen on same screen. When the phone is rotated, I want it to autorotate only if the image is full screen, otherwise no. I have isZoomedIn that is true when a image is full screen else false.
I have implemented the method shouldAutorotate. If it is zoomed-in it returns Yes otherwise No but it doesn't work even if isZoomedIn is set corectly.
I created a demo having a button to pop-up a new view on same screen similar to your image selection on clicking.
-(IBAction)buttonClicked:(id)sender //Called when button tapped to pop-up a new view.
{
flag = YES; //Flag check for rotating new view ,i.e., YES.
newView = [[UIView alloc] initWithFrame:CGRectMake(5, 5, self.view.frame.size.width-10, self.view.frame.size.height-10)];
[newView setBackgroundColor:[UIColor blueColor]];
closeNewViewBtn = [[UIButton alloc] initWithFrame:CGRectMake(30, 30, 100, 50)];
[closeNewViewBtn addTarget:self action:#selector(removeView) forControlEvents:UIControlEventTouchUpInside];
[closeNewViewBtn setTitle:#"Remove View" forState:UIControlStateNormal];
[closeNewViewBtn setBackgroundColor:[UIColor redColor]];
[newView addSubview:closeNewViewBtn];
[self.view addSubview:newView];
}
-(void)removeView //Called to remove view or in your case change it for removing the image or what ever you doing.
{
flag = NO;
[newView removeFromSuperview];
}
-(BOOL)shouldAutorotate //Rotation check
{
if(flag)
return YES; //Will rotate when new view is present.
else
return NO; //Will not rotate when new view is not present.
}
This will get you required needs.

UIButton suddenly stops working

So I'm having issues with the buttons for the filters in my photo app. I'm not exactly sure why, but they've suddenly stopped working. The selector is not being called when they're tapped, but I have no idea why. They were working just fine a few days ago, but for some reason they're not now. I've checked the UIView subviews array, verified that it's right on top. I need a way to see if, for some reason, the touches are not making it to the button. I'm not sure how to do this.
I wish I had more information to give, but this is all I've got. I hope someone has some suggestions because I'm at wit's end with it.
Thanks in advance!
Button Creation Method:
-(void)createFilterButtonsForThumbnail:(UIImage *)thumbnail
{
UIView *filtersContainer = self.filterContainer;
CGRect buttonFrame = CGRectMake(kFilterFrameThickness, kFilterFrameThickness,
thumbnail.size.width, thumbnail.size.height);
CGFloat frameWidth = thumbnail.size.width+(2*kFilterFrameThickness);
CGFloat frameHeight = kFilterPickerHeight;
UIEdgeInsets backgroundInsets = UIEdgeInsetsMake(0, kFilterFrameThickness, 0, kFilterFrameThickness);
UIImage *buttonBackgroundImage = [[UIImage imageNamed:#"FilmReel"] resizableImageWithCapInsets:backgroundInsets];
for (int i = 0;i<(self.filterPaths.count+kFilterNonLookups+1);i++){
UIImageView *buttonBackground = [[UIImageView alloc] initWithFrame:CGRectMake(kFilterSidePadding+(i*(frameWidth+kFilterSidePadding)),
0,
frameWidth,
frameHeight)];
[buttonBackground setImage:buttonBackgroundImage];
UIButton *thumbnailButton = [[UIButton alloc] initWithFrame:buttonFrame];
UIImage *filteredThumbnail = [self applyFilterAtIndex:i ToImage:thumbnail];
[thumbnailButton setImage:filteredThumbnail forState:UIControlStateNormal];
[thumbnailButton addTarget:self action:#selector(filterSelected:) forControlEvents:UIControlEventTouchUpInside];
[thumbnailButton setTag:i];
[buttonBackground addSubview:thumbnailButton];
[filtersContainer addSubview:buttonBackground];
if ((i > (kFilterProMinimumIndex)) && ([self isProVersion]) == NO){
UIImageView *proTag = [[UIImageView alloc] initWithImage:nil];
CGRect proFrame = CGRectMake(buttonFrame.origin.x,
buttonFrame.origin.y + buttonFrame.size.height - kFilterProIconHeight-kFilterFrameThickness,
kFilterProIconWidth,
kFilterProIconHeight);
[proTag setBackgroundColor:[UIColor orangeColor]];
[proTag setFrame:proFrame];
[thumbnailButton addSubview:proTag];
[self.filterProTags addObject:proTag];
}
}
}
Selector Method:
-(void)filterSelected:(UIButton *)button
{
NSLog(#"Pressed button for index %i",button.tag);
int buttonTag = button.tag;
if ((buttonTag < kFilterProMinimumIndex+1) || ([self isProVersion] == YES)){
[self.imageView setImage:[self applyFilterAtIndex:buttonTag ToImage:self.workingImage]];
}
else {
[self processProPurchaseAfterAlert];
}
}
I see a couple issues in this, but I'm not sure which ones are causing it to break. First, you should instantiate your button using buttonWithType: on UIButton:
UIButton *thumbnailButton = [UIButton buttonWithType:UIButtonTypeCustom];
[thumbnailButton setFrame:buttonFrame]
The reason for this is UIButton is a class cluster, and you should let the OS give you the correct button.
Secondly, you're adding the Button as a Subview of an UIImageView, which by default, has userInteractionEnabled set to NO.
This property is inherited from the UIView parent class. This class
changes the default value of this property to NO.
You should have the button be one large button, with the background of the button be the image you want it to be.

Image view not responding to touch event

I have a grid of thumbnail images, and when one of them is touched, I'd like to show the whole image. Now, I know that UIImageView does not respond to touch events, but as suggested in this answer, I created a UIButton to handle the event. See code below:
- (void)displayImage
{
NSUInteger i = 0; // The actual code is different and works; this is just for brevity's sake.
// UILazyImageView is a subclass of UIImageView
UILazyImageView *imageView = [[UILazyImageView alloc] initWithURL:[NSURL URLWithString:[[[self images] objectAtIndex:i] thumbnailUrl]]];
UIButton *imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[imageButton setFrame:[imageView frame]];
[imageButton addTarget:self action:#selector(imageTapped:) forControlEvents:UIControlEventTouchUpInside];
[imageView addSubview:imageButton];
[[self containerView] addSubview:imageView];
[imageView release];
}
}
- (void)imageTapped:(id)sender
{
NSLog(#"Image tapped.");
// Get the index of sender in the images array
NSUInteger index = 0; // Don't worry, I know. I'll implement this later
FullImageViewController *fullImageViewController = [[[FullImageViewController alloc] initWithImageURL:[NSURL URLWithString:[[[self images] objectAtIndex:index] url]]] autorelease];
[[self navigationController] pushViewController:fullImageViewController animated:YES];
}
Ok. So I've create a custom button, set its frame to match the image frame, told it to respond to touch up inside and how to respond, and added it to the image's subviews. But when I run this, I get nothing. The "Image tapped." doesn't appear in the console, so I know that the message isn't being sent. What am I doing wrong here?
Many thanks for all your help.
by default UIImageView has its userInteractionEnabled property set to NO
add this line
imageView.userInteractionEnabled = YES;
Try
imageView.userInteractionEnabled = YES;
This is a property inherited from UIView, but as per Apple's docs, UIImageView changes its default value to NO, ignoring all events.
In addition to setting imageView.userInteractionEnabled = YES, you can eliminate the button altogether and add a UITapGestureRecognizer to the UIImageView to handle taps. It would look something like:
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
[imageView addGestureRecognizer:recognizer];

Resources