Rounding corners of UIModalPresentationFormSheet - ios

forgive me if this is an obvious question i am relatively new.
I have a modal view which i set up with a custom size and rounded corners:
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 600, 450);
self.view.layer.cornerRadius = 60.0;
}
However i find that when i round the view corners, i get this greyish colour appear on the edges of it (as if theres something else behind it) : (see picture).
How do i remove these greyish edges so it shows the background content like normal? I've tried adding
self.view.layer.masksToBounds = YES;
however this still gives the same effect as above.
Thanks,

- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 600, 450);
self.view.superview.layer.cornerRadius = 60.0;
self.view.superview.layer.masksToBounds = YES;
}
I think you should set corner radius of the superView.

use like this
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 600, 450);
self.view.layer.cornerRadius = 60.0;
self.view.layer.masksToBounds = YES; //add this line
}

Use this, it will remove the shadow
self.view.layer.masksToBounds = YES;

It turns out you need to round the superview and mask the superview;
[self.view superview].layer.cornerRadius = 30.0f;
[self.view superview].layer.masksToBounds = YES;
So in the end its looked like this :)
- (void)viewWillLayoutSubviews{
//setup custom size modal view
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 600, 450);
[self.view superview].layer.cornerRadius = 30.0f;
[self.view superview].layer.masksToBounds = YES;
}
Thanks for your help Shan

Related

iOS Layer animation with auto layout

I have a simple container view(green) and two sub views(red and blue) as below.
The container view is not applying auto layout and I config its size & location by frame.
While the sub views are applying auto layout(see code below)
#implementation XXView {
UIView *_leftView;
UIView *_rightView;
}
- (instancetype)init {
self = [super initWithFrame:CGRectZero];
if (self) {
[self setupViewHierarchy];
[self setupConstraints];
}
return self;
}
- (void)setupViewHierarchy {
_leftView = [[UIView alloc] init];
_leftView.backgroundColor = UIColor.redColor;
_leftView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_leftView];
_rightView = [[UIView alloc] init];
_rightView.backgroundColor = UIColor.blueColor;
_rightView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_rightView];
self.backgroundColor = UIColor.greenColor;
}
- (void)setupConstraints {
[NSLayoutConstraint activateConstraints:#[
[_leftView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:10],
[_leftView.topAnchor constraintEqualToAnchor:self.topAnchor],
[_leftView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[_leftView.widthAnchor constraintEqualToConstant:50],
[_rightView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-10],
[_rightView.topAnchor constraintEqualToAnchor:_leftView.topAnchor],
[_rightView.bottomAnchor constraintEqualToAnchor:_leftView.bottomAnchor],
[_rightView.widthAnchor constraintEqualToAnchor:_leftView.widthAnchor],
]];
}
...
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
XXView *tv = [[XXView alloc] init];
CGFloat width = self.view.bounds.size.width;
tv.frame = CGRectMake(50, 400, width-100, 100);
[self.view addSubview:tv];
self.tv = tv;
}
Then I would like to animate the container's width change by using the CABasicAnimation as below:
- (void)startAnimation {
[CATransaction begin];
CGFloat width = self.bounds.size.width;
CABasicAnimation *widthAnimation = [CABasicAnimation animationWithKeyPath:#"bounds.size.width"];
widthAnimation.fromValue = #(width/2);
widthAnimation.toValue = #(width);
widthAnimation.duration = 1;
[self.layer addAnimation:widthAnimation forKey:#"123"];
[CATransaction commit];
}
However, the animation is not as I would expect. I would expect the left view moves as the container's leading side and the right view does as the trailing side.
What I see is, the green view expands as expected and the left view moves as green view's leading side. However, the right view is always keeping the same distance to left view. Below is the screenshot taken at the beginning of the animation.
Why the animation is not working as expected?
The problem is that your CABasicAnimation is modifying the bounds of the layer ... but as far as auto-layout is concerned that does not change the width of the view.
It's not really clear what your goal is here, but if you change your animation method to this it might get you on your way:
- (void)startAnimation {
CGRect f = self.frame;
CGFloat fw = f.size.width;
f.size.width = fw / 2;
self.frame = f;
[self layoutIfNeeded];
f.size.width = fw;
[UIView animateWithDuration:1.0 animations:^{
self.frame = f;
[self layoutIfNeeded];
}];
}

updating custom uiview's frame after adding subviews to it

I am having a big mental block figuring out something I think easy. Please see this very short video: http://screencast.com/t/eaW7rbECv4Ne.
I would like to draw a rectangle in my layoutSubviews method around the whole area that covers the subviews. I currently draw yellow rect around each term as you can see in the video.
I have a StatementView. In each key tap I am creating new objectView and adding it to my StatementView like below. I add the objectViews to a containerView and try to get the origin and size of the containerView in order to draw the stroke around it. However, it always gives me 0.
How should I update containerViews bounds values after I add the subviews to it?
// Created by ilteris on 1/31/15.
// Copyright (c) 2015 ilteris. All rights reserved.
#implementation QWZStatementView
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.userInteractionEnabled = NO;
self.textField = [[MyUITextField alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
self.textField.inputView = [LNNumberpad defaultLNNumberpad];
self.textField.delegate = self;
self.isNumerator = NO;
self.isDenominator = NO;
[self addSubview:self.textField];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statementOneTextFieldChanged:) name:UITextFieldTextDidChangeNotification object:nil];
self.containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[self addSubview:self.containerView];
self.autoresizesSubviews = YES;
self.objectsArray = [NSMutableArray arrayWithCapacity:1];
self.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
}
return self;
}
-(void)statementOneTextFieldChanged:(NSNotification *)notification {
NSLog(#"statementOneTextFieldChanged");
QWZObjectView *objectView = [[QWZObjectView alloc] initWithFrame:self.bounds];
[self.containerView addSubview:objectView];
QWZTerm* term = [QWZQuestionDetailViewController createAndReturnCoreDataTermForJSONDict:objectData];
[objectView createTerm:term];
[self.objectsArray addObject:objectView];
[self setNeedsLayout];
}
- (void)layoutSubviews {
NSLog(#"layoutSubviews StatementView");
[super layoutSubviews];
CGSize totalSize = CGSizeMake(0, 0);
for (QWZObjectView* objectView in self.objectsArray) {
CGSize textSize = objectView.bounds.size;
objectView.frame = CGRectMake(totalSize.width , totalSize.height, textSize.width , textSize.height);
totalSize.width = textSize.width + totalSize.width;
}
CGRect bounds = self.containerView.bounds;
/*
NSLog(#"self.containerView.bounds is %#", NSStringFromCGRect(self.containerView.bounds)); //always 0.
bounds.origin = CGPointMake(totalSize.width/2, self.containerView.bounds.origin.y); //adding this code didn't help at all.
CGFloat borderWidth = 2.0f;
self.bounds = CGRectInset(self.bounds, -borderWidth, -borderWidth);
self.layer.borderColor = [UIColor redColor].CGColor;
self.layer.borderWidth = borderWidth;
*/
bounds.origin = CGPointMake(totalSize.width/2, self.containerView.bounds.origin.y);
self.containerView.bounds = bounds;
}
#end

Why is UIScrollView's contentSize adjusted when zooming?

With the code below, I see a red square appear which I can scroll around (because scrollview's content is 4x screen).
But once I start zooming out (scale < 1.0), the scrollview's contentSize immediately jumps to scale times the iPad's screen size. For example:
0.985783 757.081249 1009.441665
After which I cannot move the square around anymore. I can only move the square when scale get's above 1.0; in which case the scroll indicators show that the contentSize is still scale times screen size.
Another effect is that when zooming out below 1.0, the red square moves toward the top-left corner normally by zooming out. However, after I release the screen (without any further zooming), it moves even further to the corner. EDIT: This must be the rubber banding of the scrollview.
(The square itself does scale as expected.)
What I am missing here? Here's my view controller code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
self.scrollView.contentSize = CGSizeMake(self.view.bounds.size.width * 2, self.view.bounds.size.height * 2);
self.scrollView.backgroundColor = [UIColor colorWithWhite:0.5f alpha:1.0f];
self.scrollView.minimumZoomScale = 0.1f;
self.scrollView.maximumZoomScale = 4.0f;
self.scrollView.clipsToBounds = YES;
self.scrollView.delegate = self;
self.contentView = [[UIView alloc] initWithFrame:self.scrollView.bounds];
[self.scrollView addSubview:self.contentView];
[self.view addSubview:self.scrollView];
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(400, 400, 100, 100)];
view.backgroundColor = [UIColor redColor];
[self.contentView addSubview:view];
}
#pragma UIScrollViewDelegate
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.contentView;
}
- (void)scrollViewDidEndZooming:(UIScrollView*)scrollView
withView:(UIView*)view
atScale:(double)scale
{
NSLog(#"%f %f %f", scale, self.scrollView.contentSize.width, self.scrollView.contentSize.height);
}

Adding subviews programmatically positions them weirdly

I have a view in which I want to add multiple subviews, however when I add them, they get positioned in positions where I didn't set the frame. The x coordinate is correct, but the y is quite off.
Using the Interface Builder it went quite smooth, just drag them in and send the correct frame and origin. However I don't appear to be able to set the origin; I get expression is not assignable when I try view.frame.origin = CGPointMake(x, y), and setting the x and y coordinates directly gives me the same error.
Does this happens because subviews cannot overlap programmatically without setting a special attribute (that I'm missing)?
Edit: The views are being set in the initWithStyle method of a UITableViewCell.
Edit 2: Added code within initWithStyle method.
// Initialize images
self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image"]];
self.anImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"anImage"]];
self.anotherImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"anotherImage"]];
// Set imageview locations
self.imageView.frame = CGRectMake(0, 0, 300, 54);
self.anImageView.frame = CGRectMake(20, 53, 16, 52);
self.anotherImageView.frame = CGRectMake(179, 43, 111, 53);
To avoid expression is not assignable, you have to set the entire frame at once, either using
view.frame = CGRectMake(x, y, width, height)
or
CGRect frame = self.view.frame;
frame.origin.x = newX;
self.view.frame = frame;
Most likely you are setting the frames in the viewDidLoad method. The problem here is that you are setting the frame before the viewControllers frame has been resized based on the constraints of the app.
Try moving your frame setting into the method viewWillAppear and see if that fixes your problem.
Edit: Because you are doing this in a cell, and not in a viewController you would do something like the following:
In initWithStyle:reuseIdentifier
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.customView = [[UIView alloc] initWithFrame:CGRectZero];
}
return self;
}
Then override layoutSubviews to actually set the views frame
- (void)layoutSubviews
{
[super layoutSubviews];
self.customView.frame = CGRectMake(x, y, width, height);
}
As far as the "expression is not assignable" warning, this is because you cannot just set a views origin without setting the height and width. Use:
view.frame = CGRectMake(x, y, width, height);
If you want to keep the same width and height without having to hard code it do something like
view.frame = CGRectMake(x, y, view.frame.size.width, view.frame.size.height);

Background picture is "blinking" when the screen orientation is changed

I would like to change the background picture of my view controller, when the orientation is changed. I call my setupGUIForOrientation function in shouldAutorotateToInterfaceOrientation, like this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
[self setupGUIForOrientation:interfaceOrientation];
return YES;
}
The setupGUIForOrientation function:
-(void)setupGUIForOrientation:(UIInterfaceOrientation)orientation
{
if(!background) background = [[UIImageView alloc] init];
UIImage* image = [[StorageProvider storage].imageProvider getImageForSurfaceElement:#"background"];
int width = 0;
int height = 0;
CGRect bounds = [[UIScreen mainScreen] bounds];
if(UIInterfaceOrientationIsPortrait(orientation)) {
width = MIN(bounds.size.width, bounds.size.height);
height = MAX(bounds.size.width, bounds.size.height);
} else {
width = MAX(bounds.size.width, bounds.size.height);
height = MIN(bounds.size.width, bounds.size.height);
}
background.frame = CGRectMake(0, 0, width, height);
[self.view addSubview: background];
[self.view sendSubviewToBack: background];
[background setImage:image];
}
Everything is good (the image and the frame changes) except one thing: when the rotation happens, I can see the view controller's background color for one second, which is really ugly. Can I prevent it somehow? And, can I code this function on a better way? Thanks for any help!
I'm guessing, but you may be updating your view too early. Rather than call your method in shouldAutorotateToInterfaceOrientation, have you tried doing it in didRotateFromInterfaceOrientation?
I.e. making this change:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self setupGUIForOrientation:self.interfaceOrientation];
}

Resources