Popovercontroller doesn't display full - iphone

I have an UIPopovercontroller in with an content that generate from an viewcontroller.
popOverController = [[UIPopoverController alloc]initWithPopUp:emLightPopUp];
popOverController.delegate = self;
// Get device position.
CGRect position = {parentButton.frame.origin,emLightPopUp.popUpView.frame.size};
CGSize popUpViewFrameSize = emLightPopUp.popUpView.frame.size;
Link screenshot: http://i.stack.imgur.com/AxqoG.png
The issue is that when I change the position of select devices (touched button) upwards, the displayed popup will be resized like the screenshot.
I already try to set content size inside the subclass of uipopover but it still doesn't work:
self.popoverContentSize = emLightPopUp.popUpView.frame.size;
EDIT:
I solved this problems by calculate the position that display the popup and scroll the scrollview inside into an upper position. Check out this code:
-(void)moveDeviceOutMiddleScreen:(id)deviceButton
{
UIButton* button = (UIButton*)deviceButton;
CGFloat yPositionRange = button.frame.origin.y - self.floorZoomScrollView.contentOffset.y;
int middle_top_y = 70;
int middle_bottom_y = 166;
if (yPositionRange > middle_top_y && yPositionRange < middle_bottom_y) {
CGRect newRect = CGRectMake(self.floorZoomScrollView.contentOffset.x,
self.floorZoomScrollView.contentOffset.y +yPositionRange*0.6,
self.floorZoomScrollView.frame.size.width, self.floorZoomScrollView.frame.size.height);
[self.floorZoomScrollView scrollRectToVisible:newRect animated:NO];
}
}
Thanks for your responses.

You are setting the value with itself.
self.popoverContentSize = emLightPopUp.popUpView.frame.size;
Instead, you should set the desired size (assuming emLightPopUp is the view controller displayed in the popup controller):
[self setPopoverContentSize:emLightPopUp.bounds animated:YES];

Related

How can I correctly position a UIImageView inside a UITableViewCell?

I have a custom UITableViewCell loaded from a nib. In it are three UIImageView views. In the -(UITableViewCell*) tableView:(UITableView*) cellForRowAtIndexPath:(NSIndexPath*)indexPath method I check a property for each row and determine whether each one is visible. If they are not visible, I shift the x position of the image so that there are no empty spaces. I am using:
cell.imageView1.hidden = YES;
cell.imageView2.hidden = YES;
cell.imageView3.hidden = YES;
int x = 0;
CGRect frame1 = cell.imageView1.frame;
if (property1)
{
cell.imageView1.hidden = NO;
frame1.origin.x = x;
x += SPACING;
}
CGRect frame2 = cell.imageView2.frame;
if (property2)
{
cell.imageView2.hidden = NO;
frame2.origin.x = x;
x += SPACING;
}
// etc...
For some reason, when the table is initially shown, the images are in the wrong location, but if I scroll up and down so that the cell is not shown then shown again, the image location goes to its correct place. What is causing this?
I'm not sure If I understood your code. But you could try calling setNeedsLayout after changing the frames.
[cell setNeedsLayout]
This method indicates that this views needs to layout on the next rendering.
Thanks to Felipe for pointing me to the right solution. In my UITableViewCell subclass I overrode the layoutSubviews method to properly layout the images there according to their state.

Objective C: Subview not clickable

I'm about to implement a Facebook-like side navigation for an iPhone App. I can slide it in and out without problems but when I want to click a button or anything in that navigation view nothing happens.
Here is the code for my side navigation view I initialize in viewDidLoad:
self.sideNavigationView = [[UIView alloc] initWithFrame:CGRectMake(self.navigationController.view.frame.size.width, 20, 238, self.navigationController.view.frame.size.height-20)];
[self.navigationController.view addSubview:self.sideNavigationView];
Then I have the following method to slide it in:
- (IBAction) openMenuBar: (id) sender {
if (!self.sideNavigationIsExpanded) {
self.sideNavigationView.frame = CGRectMake(self.navigationController.view.frame.size.width, 20, 238, self.navigationController.view.frame.size.height-20);
}
CGRect destination = self.navigationController.view.frame;
CGRect sideNavigationDestination = self.sideNavigationView.frame;
sideNavigationDestination.size.width = 238;
// Slide back
if (self.sideNavigationIsExpanded) {
sideNavigationDestination.origin.x = self.view.frame.size.width;
destination.origin.x = 0;
sideNavigationDestination.origin.y = 20;
self.sideNavigationIsExpanded = NO;
}
// Slide in
else {
sideNavigationDestination.origin.x = self.view.frame.size.width;
destination.origin.x = - sideNavigationDestination.size.width;
sideNavigationDestination.origin.y = 20;
self.sideNavigationIsExpanded = YES;
self.sideNavigationView.hidden = NO;
}
[UIView animateWithDuration:0.25 animations:^{
self.sideNavigationView.frame = sideNavigationDestination;
self.navigationController.view.frame = destination;
} completion:^(BOOL finished) {
if (!self.sideNavigationIsExpanded)
self.sideNavigationView.hidden = YES;
self.view.userInteractionEnabled = !self.sideNavigationIsExpanded;
self.sideNavigationView.userInteractionEnabled = self.sideNavigationIsExpanded;
}];
}
I tried several combinations of userInteractionEnabled = YES at every subview... Changed nothing...
Could it be that the subviews of my sideNavigationView aren't selectable because when I initialize it it is out of sight? I tried initializing it with a frame in sight (CGRectMake(0,0,238,300)) and that worked. -_-
So how could I solve my problem?
As sideNavigationView is a subview of self.view then this line:
self.view.userInteractionEnabled = !self.sideNavigationIsExpanded;
is preventing touches from reaching your sideNavigationView at all. A view will not pass a touch on to its subviews if its own userInteractionEnabled property is set to NO, even though you have set the subview's property to YES in the next line.
As for initialising off-screen, I don't believe this will have any bearing on whether the view can receive touches once it is moved back onscreen.

UIScrollview paging like animation

I have a view that have some images, text, and more to show and two button in left and right when user click on left or righr button page should get side and another page should get open with new info.
How i can do it please help.
try with this link.. You will get the logic to solve your problem. Place a button on each side where you want & use the logic from this thread
Enable paging for the scrollview.
When a button is tapped modify the content offset of the scrollview by the width of the scrollview using setContentOffset:animated:
Use this code
-(IBAction)prevButtonPage:(id) sender
{
CGFloat xOffset = pagingScrollView.contentOffset.x;
CGFloat yOffset = pagingScrollView.contentOffset.y;
if (pagingScrollView.contentOffset.x != pagingScrollView.frame.origin.x)
{
[pagingScrollView setContentOffset:CGPointMake(xOffset- 320, yOffset) animated:YES];
// [arrayIndia objectAtIndex:i];
}
NSLog(#" custom x==%f %f", pagingScrollView.contentOffset.x, pagingScrollView.contentSize.width);
}
-(IBAction)nextButtonPage:(id) sender
{
CGFloat xOffset = pagingScrollView.contentOffset.x;
CGFloat yOffset = pagingScrollView.contentOffset.y;
if ((pagingScrollView.contentOffset.x != pagingScrollView.frame.origin.x)&&(pagingScrollView.contentOffset.x !=[imageArray count]) )
{
[pagingScrollView setContentOffset:CGPointMake(xOffset + 320, yOffset) animated:YES];
}
NSLog(#" custom x==%f %f", pagingScrollView.contentOffset.x, pagingScrollView.contentSize.width);
}

iOS: navigation bar's titleView doesn't resize correctly when phone rotates

I'm writing an iPhone app that (like most apps) supports auto-rotation: You rotate your phone, and its views rotate and resize appropriately.
But I am assigning a custom view to navigationItem.titleView (the title area of the navigation bar), and I can't get that view to resize correctly when the phone rotates.
I know what you're thinking, "Just set its autoresizingMask to UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight," but it's not that simple. Of course, if I don't set my view's autoresizingMask, then my view doesn't resize; and I want it to resize.
The problem is, if I do set its autoresizingMask, then it resizes correctly as long as that view is visible; but the titleView's size gets messed up in this scenario:
Run the app, with the phone held in portrait mode. Everything looks good.
Do something that causes the app to push another view onto the navigation stack. E.g. click a table row or button that causes a call to [self.navigationController pushViewController:someOtherViewController animated:YES].
While viewing the child controller, rotate the phone to landscape.
Click the "Back" button to return to the top-level view. At this point, the title view is messed up: Although you are holding the phone in landscape mode, the title view is still sized as if you were holding it in portrait mode.
Finally, rotate the phone back to portrait mode. Now things get even worse: The title view shrinks in size (since the navigation bar got smaller), but since it was already too small, now it is much too small.
If you want to reproduce this yourself, follow these steps (this is a bit of work):
Make an app using Xcode's "Navigation-based Application" wizard.
Set it up so that the top-level table view has rows that, when you click them, push a detail view onto the navigation stack.
Include this code in both the top-level view controller and the detail view controller:
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
Include this code in only the top-level view controller:
- (void)viewDidLoad {
[super viewDidLoad];
// Create "Back" button
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Master"
style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
// Create title view
UILabel* titleView = [[[UILabel alloc] initWithFrame:CGRectMake(0,0,500,38)] autorelease];
titleView.textAlignment = UITextAlignmentCenter;
titleView.text = #"Watch this title view";
// If I leave the following line turned on, then resizing of the title view
// messes up if I:
//
// 1. Start at the master view (which uses this title view) in portrait
// 2. Navigate to the detail view
// 3. Rotate the phone to landscape
// 4. Navigate back to the master view
// 5. Rotate the phone back to portrait
//
// On the other hand, if I remove the following line, then I get a different
// problem: The title view doesn't resize as I want it to when I:
//
// 1. Start at the master view (which uses this title view) in portrait
// 2. Rotate the phone to landscape
titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.navigationItem.titleView = titleView;
}
Finally, follow my repro steps.
So ... am I doing something wrong? Is there a way to make my titleView always resize correctly?
You should also set the contentMode of the UIImageView to get the titleView properly displayed in landscape and/or portrait mode :
imgView.contentMode=UIViewContentModeScaleAspectFit;
The whole sequence: (self is a UIViewController instance)
UIImageView* imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"myCustomTitle.png"]];
imgView.autoresizingMask=UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
imgView.contentMode=UIViewContentModeScaleAspectFit;
self.navigationItem.titleView = imgView;
[imgView release];
I had something similar - but it was returning (popping) to root view controller. Ultimately, I went with the following for popping:
[[self navigationController] setNavigationBarHidden:YES animated:NO];
[[self navigationController] popViewControllerAnimated:YES];
[[self navigationController] setNavigationBarHidden:NO animated:NO];
And it worked. There may have been a better way but - after all the hours I'd already spent on this issue - this was good enough for me.
I dealt with this same issue by keeping track of the customView's initial frame, then toggling between that and a scaled CGRect of the initial frame in a -setLandscape method on a UIButton subclass. I used the UIButton subclass as navigationItem.titleView and navigationItem.rightBarButtonItem.
In UIButton subclass -
- (void)setLandscape:(BOOL)value
{
isLandscape = value;
CGFloat navbarPortraitHeight = 44;
CGFloat navbarLandscapeHeight = 32;
CGRect initialFrame = // your initial frame
CGFloat scaleFactor = floorf((navbarLandscapeHeight/navbarPortraitHeight) * 100) / 100;
if (isLandscape) {
self.frame = CGRectApplyAffineTransform(initialFrame, CGAffineTransformMakeScale(scaleFactor, scaleFactor));
} else {
self.frame = initialFrame;
}
}
Then in the InterfaceOrientation delegates I invoked the -setLandscape method on the customViews to change their sizes.
In UIViewController -
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self updateNavbarButtonsToDeviceOrientation];;
}
- (void)updateNavbarButtonsToDeviceOrientation
{
ResizeButton *rightButton = (ResizeButton *)self.navigationItem.rightBarButtonItem.customView;
ResizeButton *titleView = (ResizeButton *)self.navigationItem.titleView;
if (self.interfaceOrientation == UIDeviceOrientationPortrait || self.interfaceOrientation == UIDeviceOrientationPortraitUpsideDown) {
[rightButton setLandscape:NO];
[titleView setLandscape:NO];
} else {
[rightButton setLandscape:YES];
[titleView setLandscape:YES];
}
}
(Answering my own question)
I got this working by manually keeping track of the titleView's margins (its distance from the edges of the navigtion bar) -- saving when the view disappears, and restoring when the view reappears.
The idea is, we aren't restoring the titleView to the exact size it had previously; rather, we are restoring it so that it has the same margins it had previously. That way, if the phone has rotated, the titleView will have a new, appropriate size.
Here is my code:
In my view controller's .h file:
#interface MyViewController ...
{
CGRect titleSuperviewBounds;
UIEdgeInsets titleViewMargins;
}
In my view controller's .m file:
/**
* Helper function: Given a parent view's bounds and a child view's frame,
* calculate the margins of the child view.
*/
- (UIEdgeInsets) calcMarginsFromParentBounds:(CGRect)parentBounds
childFrame:(CGRect)childFrame {
UIEdgeInsets margins;
margins.left = childFrame.origin.x;
margins.top = childFrame.origin.y;
margins.right = parentBounds.size.width -
(childFrame.origin.x + childFrame.size.width);
margins.bottom = parentBounds.size.height -
(childFrame.origin.y + childFrame.size.height);
return margins;
}
- (void)viewDidUnload {
[super viewDidUnload];
titleSuperviewBounds = CGRectZero;
titleViewMargins = UIEdgeInsetsZero;
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// Keep track of bounds information, so that if the user changes the
// phone's orientation while we are in a different view, then when we
// return to this view, we can fix the titleView's size.
titleSuperviewBounds = self.navigationItem.titleView.superview.bounds;
CGRect titleViewFrame = self.navigationItem.titleView.frame;
titleViewMargins = [self calcMarginsFromParentBounds:titleSuperviewBounds
childFrame:titleViewFrame];
}
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Check for the case where the user went into a different view, then
// changed the phone's orientation, then returned to this view. In that
// case, our titleView probably has the wrong size, and we need to fix it.
if (titleSuperviewBounds.size.width > 0) {
CGRect newSuperviewBounds =
self.navigationItem.titleView.superview.bounds;
if (newSuperviewBounds.size.width > 0 &&
!CGRectEqualToRect(titleSuperviewBounds, newSuperviewBounds))
{
CGRect newFrame = UIEdgeInsetsInsetRect(newSuperviewBounds,
titleViewMargins);
newFrame.size.height =
self.navigationItem.titleView.frame.size.height;
newFrame.origin.y = floor((newSuperviewBounds.size.height -
self.navigationItem.titleView.frame.size.height) / 2);
self.navigationItem.titleView.frame = newFrame;
}
}
}
For IOS5 onwards, as this is an old question...This is how I accomplished the same issue with the title text not aligning properly.
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment:2 forBarMetrics:UIBarMetricsLandscapePhone];
Tested on ios5/6 sims works fine.
This is what I did:
self.viewTitle.frame = self.navigationController.navigationBar.frame;
self.navigationItem.titleView = self.viewTitle;
The viewTitle is a view created in the xib, it takes the size of the navigationBar and after it has been added the titleView adjust the size to leave room to the back button. Rotations seem to work fine.
I had had same problem, but I seem to get workaround with following code.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UIView *urlField = self.navigationItem.leftBarButtonItem.customView;
CGRect frame = urlField.frame;
frame.size.width = 1000;
urlField.frame = frame;
}
In my case, the custom view is a UITextField, but I hope this will help you.

Dynamically changing position of a UIView

Here's my setup. I have a viewcontroller that I'm creating and adding as a subview. The viewcontroller presents some options that a user can chose from. The viewcontroller is being pushed in response to a "long press" gesture. Within the viewcontroller, I added a child UIView to group some other controls together so I can move them around the screen as a unit and, when they are displayed, center them on the location of the long press. Here is the code that instantiates the view controller, changes its location, and adds it as a subview:
UserOptions *opts = [[UserOptions alloc] initWithNibName:#"UserOptions" bundle:nil];
[opts recenterOptions:location];
[self.view addSubview:opts.view];
That bit of code does create and push the viewcontroller, but the call to recenterOptions doesn't do anything. Here is that method:
- (void) recenterOptions:(CGPoint)location {
CGRect oldFrame = self.optionsView.frame;
CGFloat newX = location.x; // + oldFrame.size.width / 2.0;
CGFloat newY = location.y; // + oldFrame.size.height / 2.0;
CGRect newFrame = CGRectMake(newX, newY, oldFrame.size.width, oldFrame.size.height);
self.optionsView.frame = newFrame;
}
Note that self.optionsView is the child UIView that I added to the viewcontroller's nib.
Does anyone know why I'm unable to change the location of the UIView?
Regards,
Eric
A couple things. First, try adding the view to the view hierarchy before calling -recenterOptions:
UserOptions *opts = [[UserOptions alloc] initWithNibName:#"UserOptions"
bundle:nil];
[self.view addSubview:opts.view];
[opts recenterOptions:location];
Next, just set the center of the view instead of trying to change its frame:
- (void) recenterOptions:(CGPoint)location {
[[self optionsView] setCenter:location];
}
Are you verifying that your optionsView is valid (non-nil)?
I agree with Rob, btw. You need to change your title to match your question.
Views are loaded lazily. Until you call self.view, the view is not loaded and optionsView is nil, hence self.optionsView.frame = newFrame does nothing.