*modify* UIbutton position (Iphone SDK) - ios

I'm playing around with UIbuttons, just to get a feel on what can really be done with them. I have only one problem so far:
How do I modify the position of a UIButton?
- (IBAction)buttonClicked:(id)sender
{
UIButton *senderB = sender;
CGPoint position = senderB.frame.origin;
CGSize size = senderB.frame.size;
senderB.frame = CGRectMake(position.x,position.y + 10,size.width,size.height);
}
The above works just fine, however, creating a new CGrect for every time I want to simply change one seems rather inefficient to me.
Is there any way for me to directly set the values of senderB.frame.origin.x, etc?

I usually do it like this:
CGRect buttonFrame = button.frame;
buttonFrame.origin.y += 10;
button.frame = buttonFrame;

Nope. Notice that 'someview.frame' returns a CGRect by value, not by reference or pointer or whatever. That's why you get the 'Lvalue required' error.
However, setting the frame like you're doing is plenty fast.

The frame property is read only. What you can do is copying the current frame with
CGRect btFrame = senderB.frame;
btFrame.origin.x += 10;
senderB.frame = btFrame;

Related

Change the position dynamically

Im new to IOS development , so when i change the width of a UITextFeild dynamically i want the button below to shift up .
i tried using the constrains but it doesn't seem to shift dynamically .
(IBAction)selectStatus:(id)sender {
CGRect frameRect = _textViewDevices.frame;
frameRect.size.height = 10;
self.textViewDevices.frame = frameRect;
any good example of how to achieve that ?
I want to achieve something like the Relative positioning in android .
current box before any action
Try calling layoutIfNeeded after the modifications:
- (IBAction)selectStatus:(id)sender {
CGRect frameRect = _textViewDevices.frame;
frameRect.size.height = 10;
self.textViewDevices.frame = frameRect;
[self.view layoutIfNeeded];
}
If you have a height constraint on the text view, try to set its constant instead of setting the frame height:
- (IBAction)selectStatus:(id)sender {
self.textViewHeightConstraint.constant = 10;
[self.view layoutIfNeeded];
}
Programmatically when the first violet field changes in height, to make all the below views stay next to it, you should update the frame.origin.y properly.
So, for example, the status label should be reframed like this
CGRect frame = statusLabel.frame;
frame.origin.y = firstField.origin.y + firstField.size.height + 5;
statusLabel.frame = frame;
And the same for all below views (I've supposed 5 pixels of space between views)

Form Container Component for IOS

I recently switched from flash/flex development to IOS apps. The one thing I'm still struggling with is getting my UI components arranged the way I want them. I've tried using AutoLayout with constraints, but it feels really cumbersome, especially when there are a large number of components to arrange. What I want is something like the flex 'Form' and FormItem' components that provide a clean arrangement of labeled inputs. Can anyone point me to an equivalent solution for IOS?
I think I found what I was looking for here: XLForm
It isn't a perfect solution but I suspect it is as close as I'm going to get.
I'm not sure what you exactly want, since I do not have any experience with Flex.
If you want a UIView to clip to its subviews you can use:
[view sizeToFit];
Or if you want to control your frame via code, you have to disable auto layout in the storyboard. After that you can alter any UIView's properties e.g.:
UIView * view = [[UIView alloc] init];
CGRect newFrame = view.frame;
newFrame.size.height = 100;
newFrame.size.width = 100;
newFrame.origin.x = 50;
newFrame.origin.y = 100;
view.frame = newFrame;
or:
UIView * view = [[UIView alloc] init];
CGRect newFrame = view.frame;
newFrame.size = CGSeize(100,100)
newFrame.origin = CGPoint(0,0)
view.frame = newFrame;

is there a cleaner way to edit 1 of the 4 CGRect values of a UIView's frame?

generally when I want to move a label to the right 20px, or increase just the width of a view, I go through one of the following avenues
label.frame = CGRectMake(label.frame.origin.x+20, label.frame.origin.y, label.frame.size.width, label.frame.size.height);
or
CGRect viewFrame = view.frame;
viewFrame.x += 20;
view.frame = viewFrame;
I don't particularly like the amount of code that goes into either variation and was hoping you guys knew a shortcut that I hadn't discovered
A better method of moving to the right is the CGRectOffset macro:
label.frame = CGRectOffset(label.frame, 20.0f, 0.0f);
I find that this a clearer expression of the intent of my code.
Just to add:
Here's an article with nice CGRect tricks (Shrinking, Expanding, Edge Insetting, Intersecting)
Whenever possible I use center to modify the origin:
myView.center = CGPointMake(150, 150);
Or even better:
myView.center = anotherView.center;
To modify the size frame or bounds are the only way to go. You can use the various CGRect functions in CGGeometry to express the transformation at a higher level.

Setting the origin of the frame in iOS

I am trying to set the origin of the frame programmatically.
Method1:
button.frame.origin.y = 100;
Method 2:
CGRect frame = button.frame;
frame.origin.y = 100;
I tried method 1 but it is not working(showing an error saying Expression is not assignable). Method 2 is working. Why is this so?
Need guidance on what I am doing right.
The reason you can't do method #1 is because a frame's individual properties are read-only. However, the entire frame itself is writable/assignable, thus you can do method #2.
You can even do tricks like this:
CGRect newFrame = button.frame;
newFrame.origin.y += 100; // add 100 to y's current value
button.frame = newFrame;
You know
button.frame.origin.y return a value.
if you are using this one so you will get this error...
Expression is not assignable.
button.frame.origin.y = 100;
So this is correct way
CGRect frame = button.frame;
frame.origin.y = 100;
otherwise you can do like this...
button.frame = CGRectMake(button.frame.origin.x, 100, button.frame.size.width, button.frame.size.height)
It's because if you were able to directly change a frame's origin or size, you would bypass the setter method of UIView's frame property. This would be bad for multiple reasons.
UIView would have no chance to be notified about changes to it's frame. But it has to know about these changes to be able to update it's subviews or redraw itself.
button.frame.origin.y = 100;
equals to the following call:
[button getFrame].origin.y = 100;
in which [button getFrame] gives you the copied CGRect.
You are trying to set a variable of a structure of a structure. There is no pointer from the UIView to the structure (as it is a basic C struct so can't be pointed). hence, copied instead.
So basically, you are copying the structure and setting it. But, that just doesn't work like that.

Centering UIView

I have a UIViewController subclass that instantiates a UIView subclass (let's call that viewA). Then, viewA will sometimes instantiate another UIView which we'll call viewB.
I want viewB to be centered within the view controller.
My question is, "What is a (correct) way of doing this?"
TIA
There are many correct ways, but maybe the best one is to use the center-property:
[viewB setCenter: viewA.center];
Or maybe you need to use..
[viewB setCenter: viewA.navigationController.center];
You have to be careful to not end up on a fraction of a point. On non-retina you need to be on full points but for retina you can be on 0.5
One way would be to use center and then adjust
viewB.center = viewA.center;
viewB.frame = CGRectIntegral(viewB.frame);
I don't know a shorter way to do it than this one:
CGFloat x = CGRectGetMidX(self.view.bounds) - viewBWidth / 2;
CGFloat y = CGRectGetMidY(self.view.bounds) - viewBHeight / 2;
viewB.frame = CGRectMake(x,y,viewBWidth,viewBHeight);
viewB.frame = [MyClass centeredFrameForSize:desiredSize inRect:viewA.bounds];
+ (CGRect)centeredFrameForSize:(CGSize)size inRect:(CGRect)rect
{
CGRect frame;
frame.origin.x = rintf((rect.size.width - size.width)/2) + rect.origin.x;
frame.origin.y = rintf((rect.size.height - size.height)/2) + rect.origin.y;
frame.size = size;
return frame;
}

Resources