CGAffineTransform: rotation on UIButton resizes button image - iphone

I've got a strange problem using UIButtons, type custom. I'm placing 4 of those buttons on a UIScrollview, rotating each button by a random angle using CGAffineTransform. Now it seems that the buttons themselves change size depending on the angle of rotation.
UIGraphicsBeginImageContext(tempCtxSize);
[cookbookImage drawInRect:CGRectMake(imgOffsetX, imgOffsetY+frmOffsetY, cookbookImage.size.width, cookbookImage.size.height)];
[cookbookFrame drawInRect:CGRectMake(0.0f, frmOffsetY, cookbookFrame.size.width, cookbookFrame.size.height)];
UIImage *combinedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
…
UIButton *cookbookViewButton = [UIButton buttonWithType:UIButtonTypeCustom];
[cookbookViewButton setFrame:CGRectMake(0.0f, 0.0f, combinedImage.size.width, combinedImage.size.height)];
[cookbookViewButton setBackgroundColor:[UIColor clearColor]];
[cookbookViewButton setBackgroundImage:combinedImage forState:UIControlStateNormal];
CGAffineTransform rotation = [cookbookViewButton transform];
rotation = CGAffineTransformRotate(rotation, angle); // some random angle
[cookbookViewButton setTransform:rotation];

This is a system bug:
" Important If a view’s transform property does not contain the identity transform, the frame of that view is undefined and so are the results of its autoresizing behaviors."
from: Handling Layout Changes Automatically Using Autoresizing Rules
Solution: set the parent view's autoResizeSubviews to NO.
parentView.autoresizesSubviews = NO;

Don't set the frame of cookbookViewButton - set the bounds.

Related

How can I set maskToBounds effect on CAShapeLayer(Rounded-Recr cornered UIView)?

I want to make the glow effect spread outside of thisView.
I used this code to make Half-Rounded rect cornered UIVew.
Round two corners in UIView
Here is my code.
+ (UIView *)makeUpperHalfRoundedView:(UIView *)view {
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = view.bounds;
UIBezierPath *roundedPath =
[UIBezierPath bezierPathWithRoundedRect:maskLayer.bounds
byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight
cornerRadii:CGSizeMake(8.f, 8.f)];
maskLayer.fillColor = [[UIColor blackColor] CGColor];
maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
maskLayer.path = [roundedPath CGPath];
// maskLayer.masksToBounds = NO;
//Don't add masks to layers already in the hierarchy!
UIView *superview = [view superview];
[view removeFromSuperview];
view.layer.mask = maskLayer;
[superview addSubview:view];
return view;
}
And there are two image buttons in this view closed to the boundary.
If a touch event happen on buttons, glow effect shows(showsTouchWhenHighlighted)
Before using this piece of code, I just used
thisView.layer.cornerRadius = 8;
thisVIew.layer.masksToBounds = NO;
and glow effect spread outside of 'thisView'.
But after using CAShapeLayer in 'thisView' to masking half-roused rect, the glow effect are masked by boundary.
What you're seeing is exactly how a mask is supposed to work. You are applying the mask to the layer of the superview. Let's call that view superview (just as in your code). Okay, so what will that do? It will mask superview and all its sublayers. That includes its subviews. Its subviews are actually its sublayers.
So, since the buttons are subviews of superview, they are masked like everything else inside superview.
If you don't want that to happen, don't make the buttons subviews of superview. They can sit on top of superview without being its subviews, for example.

How to show delete button on top of the UIView

Please help me. I am phasing a problem, show a delete button on top of the view.
Without using bezier path showing like this
When i use bezier path is showing like this
how i can show the button.
This is the code i am using
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
[view1 setBackgroundColor:[UIColor orangeColor]];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view1.bounds byRoundingCorners:UIRectCornerTopLeft| UIRectCornerTopRight cornerRadii:CGSizeMake(10.0, 10.0)];
// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = view1.bounds;
maskLayer.path = maskPath.CGPath;
// Set the newly created shape layer as the mask for the image view's layer
view1.layer.mask = maskLayer;
[self.view addSubview:view1];
UIButton *bt1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[bt1 setTitle:#"D" forState:UIControlStateNormal];
[bt1 setFrame:CGRectMake(87, -10, 25, 25)];
[view1 addSubview:bt1];
please help me. Thanks in advance.
You could always add the button in your superview depending of the view's position.
What #Larme said is true ,when you're making a view you're masking all the subviews that view has.
In case you don't want to do that just enter in your view's drawRect and draw there transparent corners to achieve the same effect.

CALayer Border is appearing above subview (Z-order related, I think)

I have searched but could not find the reason for this behavior.
I have a UIButton whose image I am setting. Here is how the button should appear. Note that this is just a photoshop of the intended button design:
Essentially, it is a square custom UIButton with a white border and a little surrounding shadow. In the upper right corner, there is a "X" mark, that will be added programmatically as a subview.
Here is the screenshot of the button within the actual app. At this point, I have only added a shadow and the X mark as a subview:
How, when I try to add the white border, here is what it looks like:
It seems that the white border is appearing above the X mark sublayer. I don't know why.
Here is the code that I am using:
// selectedPhotoButton is the UIButton with UIImage set earlier
// At this point, I am adding in the shadow
[selectedPhotoButton layer] setShadowColor:[[UIColor lightGrayColor] CGColor]];
[[selectedPhotoButton layer] setShadowOffset: CGSizeMake(1.0f, 1.0f)];
[[selectedPhotoButton layer] setShadowRadius:0.5f];
[[selectedPhotoButton layer] setShadowOpacity:1.0f];
// Now add the white border
[[selectedPhotoButton layer] setBorderColor:[[UIColor whiteColor] CGColor]];
[[selectedPhotoButton layer] setBorderWidth:2.0];
// Now add the X mark subview
UIImage *deleteImage = [UIImage imageNamed:#"nocheck_photo.png"];
UIImageView *deleteMark = [[UIImageView alloc] initWithFrame:CGRectMake(53, -5, 27, 27)];
deleteMark.contentMode = UIViewContentModeScaleAspectFit;
[deleteMark setImage:deleteImage];
[selectedPhotoButton addSubview:deleteMark];
[deleteMark release];
I don't understand why the border is appearing above the deleteMark subview. Is there any way to get the intended effect?
Thank you!
From Apple's docs on CALayer:
The border is drawn inset from the receiver’s bounds by borderWidth. It is composited above the receiver’s contents and sublayers and includes the effects of the cornerRadius property.
In order to get the effect you want, I suggest you put the image into an own subview/sublayer and set that sublayer's borderWidth property.
You can set the layer's zPosition to -1. That worked for me.
I had similar problem (I wanted to prevent border line to be on top of my subviews)
CAShapeLayer * _border = [CAShapeLayer layer];
_border.strokeColor = [UIColor colorWithRed:119/255.0f green:119/255.0f blue:119/255.0f alpha:1.0f].CGColor;
_border.fillColor = nil;
[bgRoundView.layer addSublayer:_border];
_border.path = [UIBezierPath bezierPathWithRoundedRect:bgRoundView.bounds cornerRadius:20.f].CGPath;

uibutton animation

is there a possibility to animate an uibutton in this way that a thing or whatever comes out of the background e.g. a wheat ear comes out of a field.
is this possible?
thanks :)
Unless you want a more complicated animation, you can just create a custom type UIButton (either with IB by changing the type to Custom, or programmatically with UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom]), then set the button's image with [aButton setImage:[UIImage imageNamed:#"wheat_ear" forState:UIControlStateNormal].
To move it, just animate its position normally...
[UIView animateWithDuration:0.5 animations:^{aButton.center = newCenter;}];
Or, to provide the illusion of it coming out of the field, animate the bounds of the image so that it starts with the image's width and zero height, and ends with the image's width and height:
CGRect originalFrame = aButton.frame;
aButton.frame = CGRectMake(originalFrame.origin.x, originalFrame.origin.y, originalFrame.size.width, 0);
[UIView animateWithDuration:0.5 animations:^{aButton.frame = originalFrame;}];

UIScrollView starting point

I have a iPhone app with a main view that is 480 x 510. I'm a bit confused as to how the coordinate system changes when I go from portrait to landscapeRight.
Initially, I had a 480x480 content area, and wanted to add a button on the side to bring up a menu. However, the only way I could find to have the writing run down the length of the left side of the app was to change the orientation of the whole app to landscape right.
Now, with the orientation in Landscape, the scrollview is starting at the top left, when I really want it to start at the original orientation point (from when it was in portrait mode), which would be bottom left. But I can't figure out how to change the original starting point of the scrollview. I tried contentOffset, but it doesn't seem to be working.
Another way of going about this (that I might end up doing) is forget having a title on the button, and just create a graphic for the button that has text vertically oriented.
if (self = [super initWithCoder:coder]) {
// Size of the scrollview
self.contentSize = CGSizeMake(480, 510);
[self setContentOffset:CGPointMake (0, -160)];
self.showsHorizontalScrollIndicator = YES;
self.showsVerticalScrollIndicator = YES;
self.alwaysBounceVertical = NO;
self.alwaysBounceHorizontal = NO;
self.bounces = YES;
self.userInteractionEnabled = YES;
self.musicGridView = [[[MusicGridView alloc] initWithCoder:coder] autorelease];
// Rectangle where I put the music grid (origin is left aligned, and down 160 pixels to account for landscape view)
self.musicGridView.frame = CGRectMake(0, 160, 480, 480);
[self addSubview: musicGridView];
self.menuButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.menuButton.frame = CGRectMake(0, 480, 480, 32);
[menuButton setTitle: #"Tap to get Menu" forState: UIControlStateNormal];
[menuButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[menuButton addTarget:self action:#selector(showMenu) forControlEvents:UIControlEventTouchUpInside];
[self addSubview: menuButton];
simply set the points x,y in
//it goes in particular pont of view
[scrollview setContentOffset:CGPointMake(x,y) animated:YES];
//if x=0 in loop, increase y value scrollview move only vertical direction
[scrollview setContentOffset:CGPointMake(0,y) animated:YES];
//if y=0 in loop, increase x values scrollview move only horizontal direction
[scrollview setContentOffset:CGPointMake(x,0) animated:YES];
Andrey Tarantsov has done an awesome rundown of the various quirks of the UIScrollView class, including code for various workarounds to common problems. It might be worthwhile taking a look.