UIButton autoresizing woes - iphone

Trying to get UIButtons to decrease height but maintain width when device is rotated.
Here's code from initWithFrame: of the view that contains the buttons.
ParentView.m
self = [super initWithFrame:CGRectMake(0, 0, UIKeyboardPortraitHeightPhone, 320)];
self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
self.autoresizesSubviews = YES;
// And then on each button I call
myButton.frame = myFrame;
myButton.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin);
The problem: Before I even rotate the device, the buttons have resized and gotten smaller (in height) than the frame I initialized them to.
Previous research: It looks like I'm having the same problem as this person: Cannot get UIButton autoresizingMask to work, but I followed the advice and got the same unsatisfactory result.
I also looked at the apple docs, which say that the autoresizing mask is only supposed to take effect when the bounds of the parent view change. Obviously either the bounds of my parent view are changing without me realizing it, or something else fishy is going on here.
Any ideas as to what could be the problem?

Related

UIView layer shadow darkens after rotation

I have a UIView that I'm using as a header, and I've applied a drop shadow to this view. It gets onscreen as I intended, but after a rotation the shadow becomes twice as dark, as though it had been redrawn over top of itself. Subsequent rotations make it even darker. Here is the code for the header and shadow:
self.header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, HEADER_HEIGHT)];
self.header.backgroundColor = [UIColor whiteColor];
self.header.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth;
// Drop shadow.
self.header.layer.shadowColor = [UIColor blackColor].CGColor;
self.header.layer.shadowOpacity = 0.5;
self.header.layer.shadowRadius = 2.0;
self.header.layer.shadowOffset = CGSizeMake(0, 2);
// self.header.layer.shouldRasterize = YES;
// self.header.layer.rasterizationScale = [UIScreen mainScreen].scale;
This code all occurs in viewWillLayoutSubviews of my View Controller, and call [super willLayoutSubviews] at the beginning of the method. I have tried putting the same code in viewWillAppear:animated to no effect.
While writing this question out, I figured out the solution.
I was re-initializing the header every time viewWillLayout subviews was called.
Aside from being inefficient, this also caused the shadow to draw over itself for some reason.
I fixed this by initializing all of my views in loadView, and doing the frame setting in viewWillLayoutSubviews. This resolved the issue, and is nicer because I am not re-initializing objects that already exist.

How do you ensure that a UIView shrinks down to the size of its superview?

I'm creating a custom view (a subclass of UIView), the purpose of which is to hold together a static background image, a static border/frame overlay, and several smaller images that can be rotated, stretched, and dragged around the view (before the whole view is exported as an image).
I'm stuck on displaying this custom view from within another view. The images are coming from the iPhone camera, which has a very high resolution, and the only things I have been able to manage so far are cutting off the majority of the image or having my view go over the end of the screen. I need to be able to display it alongside menu items and so on, without editing the image (so that it can be sent on in its full form).
I am also adding the image to a fullscreen view, and it still will not change size.
I am initialising the view with as follows
- (id)initWithImage:(UIImage *)image
{
self = [super init];
if (self) {
[self setClipsToBounds:YES];
[self setAutoresizesSubviews:YES];
[self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
_image = image;
_imageView = [[UIImageView alloc] initWithImage:_image];
[_imageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[self addSubview:_imageView];
}
return self;
}
And I add it to another view with
self.card = [[SGImageCard alloc] initWithImage:[SGCardDataController cardImage]];
[self.cardPlaceHolder setAutoresizesSubviews:YES];
[self.cardPlaceHolder setContentMode:UIViewContentModeScaleAspectFit];
[self.cardPlaceHolder addSubview:self.card];
That view has also been set up in Interface Builder, and set there to autoresize its subviews and to cliptobounds (sometimes -- I have tried both ways). I have added my view in viewdidload (when the placeholder does not have its frame, for a reason I don't know), and also later, when it does (and it doesn't work either way).
What am I missing? (Have I even gone about this the right way?)
I finally solved this by setting the AutoResizeMasks to
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleRightMargin | UIViewAutoResizingFlexibleBottomMargin
And also setting the ContentModes to
UIViewContentModeScaleAspectFit

Image View in Button Doesn't Appear

I am trying to use the background view of the image view of a UIButton but for some reason it will not show up. This is what I have tried:
detailCell.greenPriorityButton.imageView.frame = detailCell.greenPriorityButton.frame;
[detailCell.greenPriorityButton.imageView setBackgroundColor:[UIColor greenColor]];
[detailCell.greenPriorityButton.imageView setHidden:NO];
[detailCell.greenPriorityButton.imageView setOpaque:YES];
I have called NSLog on the imageView property and it seems everything is as it should be. I can also tap on the button and the method associated with it will be called so I know it exists. Just in case I am missing something here is the NSLog return:
<UIImageView: 0x1d97e1b0; frame = (254 61; 20 20); clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x1d97e210>>
The reason I am not using dot notation to set the image view properties above is because they don't seem to change the values. For example, if I say detailCell.greenPriorityButton.imageView.hidden = NO; it doesn't seem to do anything.
Thanks for any help!
Edit
The reason for not just setting the background color of the button and not its image view is because I am trying to create a small shape in the button. However I want the tappable space to have margins around the shape so it is still user friendly. I thought the image view property would lend useful as I could manipulate the frame and layer of that separately from the frame and layer of the button.
I have now tried adding a UIView *greenBackground as a subview to the button, however this doesn't appear either.
If you want a view that you can have within the view of the button for the purpose of setting its color then I would think that trying to use the imageview is the wrong approach. You could just add a subview that has the changed background color. something like this:
UIView *colorView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 10, 10)];//Whatever rect you want that will be in reference to the frame of the button
colorView.backgroundColor = [UIColor greenColor];
[detailCell.greenPriorityButton addSubview:colorView];

Manual iPhone rotation incorrectly positioned

I've managed to manually detect rotation and set my own rotation effects between two UIViewControllers. When in the first, rotating to landscape prompts the second to be pushed on with a manual animation. The status bar moves to the correct orientation. However, the view loaded by the second UIViewController is not in the position I expected it. Instead there is margin on the left where the status bar previously was and margin/space at the bottom that I was expecting to be filled by the view.
(Click to enlarge. The orange box is simply to reference where 0,0 is in the rotated UIView, CustomView)
The code I'm using in my view controller to do the rotation is:
-(void)loadView {
CustomView *customView = [[CustomView alloc] initWithFrame:CGRectMake(0, 20, 480, 300)];
self.view = customView;
CGAffineTransform rotate = CGAffineTransformMakeRotation(degreesToRadian(90));
[self.view setTransform:rotate];
[customView release];
}
Any help would be much appreciated!
EDIT Managed to solve after a variety of trial and error approaches - answer provided below. Perhaps there's a more elegant/obvious solution though - if so feel free to provide!
try these on the viewcontrollers. Solved the 20 pixel(status bar height) clip issue when I was getting fullscreen subviews to show up.
[viewcontroller1.view setCenter:CGPointMake(viewcontroller1.view.center.x, viewcontroller1.view.center.y-20)];
and/or
[viewcontroller2.view setCenter:CGPointMake(viewcontroller2.view.center.x-20, viewcontroller2.view.center.y)];
I managed to solve this by setting the View's bounds after the transformation:
self.view.bounds = CGRectMake(20, -20, 480, 300);

Learning the basics of UIScrollView

I've been having a very hard time finding good examples of UIScrollView. Even Apple's UIScrollView Suite I find a bit lacking.
I'm looking for a tutorial or example set that shows me how to create something similar to the iPhone Safari tab scrolling, when you zoom out from one browser window and can flick to others.
But I'm having a hard time just getting any old view showing within a scroll view. I have a view set up with an image in it, but when I add it to the scroll view, I only get a black rectangle, no matter what I put in the view I add.
Any links or code snippets would be great!
Here is a scroll view guide from Apple
The basic steps are:
Create a UIScrollView and a content view you want to put inside (in your case a UIImageView).
Make the content view a subview of the scroll view.
Set the content size of the scrollview to the frame size of the content view. This is a very important step that people often omit.
Put the scroll view in a window somewhere.
As for the paging behavior, check out UIScrollView’s pagingEnabled property. If you need to scroll by less than a whole page you’ll need to play tricks with clipsToBounds, sort of the reverse of what is happening in this StackOverflow question.
UIScrollView *scrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
NSInteger viewcount= 4;
for (int i = 0; i <viewcount; i++)
{
CGFloat y = i * self.view.frame.size.height;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, y,self.view.frame.size.width, self .view.frame.size.height)];
view.backgroundColor = [UIColor greenColor];
[scrollview addSubview:view];
[view release];
}
scrollview.contentSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height *viewcount);
For more information Create UIScrollView programmatically
New 3/26/2013
I stumbled on an easier way to do this without code (contentSize)
https://stackoverflow.com/a/15649607/1705353