Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS frame change one property (eg width)

This question was originally asked for the objective-c programming language. At the time of writing, swift didn't even exist yet.

Question

Is it possible to change only one property of a CGRect ?

For example:

self.frame.size.width = 50; 

instead of

self.frame = CGRectMake(self.frame.origin.x,                          self.frame.origin.y,                          self.frame.size.width,                          50); 

of course I understand that self.frame.size.width is read only so I'm wondering how to do this?

CSS ANALOGY proceed at your own risk

for those of you who are familiar with CSS, the idea is very similar to using:

margin-left: 2px; 

instead of having to change the whole value:

margin: 5px 5px 5px 2px; 
like image 632
Jacksonkr Avatar asked Mar 02 '12 17:03

Jacksonkr


People also ask

What's the difference between the Uiview bounds property and the frame property?

Frame refers to the coordinate system of the view's container (parent view). Bounds refer to the own coordinate system of the view.

How do I change the width of a view in Swift?

1) Control-drag from a frame view (e.g. questionFrame) to main View, in the pop-up select "Equal heights". 2)Then go to size inspector of the frame, click edit "Equal height to Superview" constraint, set the multiplier to 0.7 and hit return.

When to use bounds iOS?

Since frame relates a view's location in its parent view, you use it when you are making outward changes, like changing its width or finding the distance between the view and the top of its parent view. Use the bounds when you are making inward changes, like drawing things or arranging subviews within the view.

What is Cgrect?

A structure that contains the location and dimensions of a rectangle.


2 Answers

To answer your original question: yes, it's possible to change just one member of a CGRect structure. This code throws no errors:

myRect.size.width = 50; 

What is not possible, however, is to change a single member of a CGRect that is itself a property of another object. In that very common case, you would have to use a temporary local variable:

CGRect frameRect = self.frame; frameRect.size.width = 50; self.frame = frameRect; 

The reason for this is that using the property accessor self.frame = ... is equivalent to [self setFrame:...] and this accessor always expects an entire CGRect. Mixing C-style struct access with Objective-C property dot notation does not work well in this case.

like image 159
Ole Begemann Avatar answered Sep 24 '22 01:09

Ole Begemann


I liked Ahmed Khalaf's answer, but it occurred to me that you may as well just write out a few C functions... the key advantage being that it'll be easier to track down errors in the event that you're using the wrong type.

Having said that, I wrote a .h file with these function declarations:

CGRect CGRectSetWidth(CGRect rect, CGFloat width); CGRect CGRectSetHeight(CGRect rect, CGFloat height); CGRect CGRectSetSize(CGRect rect, CGSize size); CGRect CGRectSetX(CGRect rect, CGFloat x); CGRect CGRectSetY(CGRect rect, CGFloat y); CGRect CGRectSetOrigin(CGRect rect, CGPoint origin); 

And a corresponding .m file with these function implementations:

CGRect CGRectSetWidth(CGRect rect, CGFloat width) {     return CGRectMake(rect.origin.x, rect.origin.y, width, rect.size.height); }  CGRect CGRectSetHeight(CGRect rect, CGFloat height) {     return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, height); }  CGRect CGRectSetSize(CGRect rect, CGSize size) {     return CGRectMake(rect.origin.x, rect.origin.y, size.width, size.height); }  CGRect CGRectSetX(CGRect rect, CGFloat x) {     return CGRectMake(x, rect.origin.y, rect.size.width, rect.size.height); }  CGRect CGRectSetY(CGRect rect, CGFloat y) {     return CGRectMake(rect.origin.x, y, rect.size.width, rect.size.height); }  CGRect CGRectSetOrigin(CGRect rect, CGPoint origin) {     return CGRectMake(origin.x, origin.y, rect.size.width, rect.size.height); } 

So, now, to do what you want, you can just do:

self.frame = CGRectSetWidth(self.frame, 50); 

Get even Fancier (update I made a year later)

This has a redundant self.frame in it, though. To fix that, you could add a category on UIView with methods that look like this:

- (void) setFrameWidth:(CGFloat)width {     self.frame = CGRectSetWidth(self.frame, width); // You could also use a full CGRectMake() function here, if you'd rather. } 

And now you can just type in:

[self setFrameWidth:50]; 

Or, even better:

self.frameWidth = 50; 

And just so you can do something like this:

self.frameWidth = otherView.frameWidth; // as opposed to self.frameWidth = otherView.frame.size.width; 

You'll need to also have this in your category:

- (CGFloat) frameWidth {     return self.frame.size.width; } 

Enjoy.

like image 25
ArtOfWarfare Avatar answered Sep 26 '22 01:09

ArtOfWarfare