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;
Related
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)
In objective-c I am often updating the frames of my views during animations. I currently have a messy solution to doing so:
CGPoint newOrigin = CGPointMake(25.0, 25.0);
view.frame = CGRectMake(newOrigin.x, newOrigin.y, view.frame.size.width, view.frame.size.height);
What I'm looking for is a simple convenience method that works like this:
view.frame = CGRectWithNewOrigin(view.frame, newOrigin);
Is there an existing method in the SDK which does this or will I need to define my own?
Solved: 0x7fffffff has the correct answer but JackWu's suggestion is a better approach:
The solution offered by Jack Wu solved my problem. The iOS SDK has no method which does this so you will need to define your own inline method to do so. However, utilizing the UIView's center property is a better approach. No need to define an inline function and it also will continue to work if the view has had a transform applied to it.
It's easy enough to define a new inline method just like the ones already being used, like CGRectMake().. What about something like this?
static inline CGRect CGRectWithNewOrigin(CGPoint origin, CGRect frame) {
return CGRectMake(origin.x, origin.y, frame.size.width, frame.size.height);
}
Then use it like you would for any other function of CGRect
CGPoint newOrigin = CGPointMake(25.0, 25.0);
CGRect newRect = CGRectWithNewOrigin(newOrigin, oldRect);
CGRectOffset does the thing (in many but not all cases):
Returns a rectangle with an origin that is offset from that of the source rectangle.
This works:
view.frame = (CGRect){.origin = newOrigin, .size = view.frame.size};
Otherwise, you can just write your own C function, I'm pretty sure one doesn't exist. (I just looked at CGGeometry.h for the hundredth time.)
Though it's a little more general than what you are asking for, I've often thought something like this would be useful:
static inline CGRect CGRectFromOriginSize(CGPoint origin, CGSize size) {
return (CGRect){.origin = newOrigin, .size = view.frame.size};;
}
This works fine:
CGRect newFrame = view.frame;
newFrame.origin = CGPointMake(25.0, 25.0);
view.frame = newFrame;
Try this:
CGPoint newOrigin = CGPointMake(25.0, 25.0);
CGRect newFrame = view.frame;
newFrame.origin = newOrigin;
view.frame = newFrame;
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.
I am running into a problem with the uiscrollview. When I have it as a regular scroll view all the UIButtons work as expected. When I add paging to it the buttons no longer respond. I have a top edge sticking out and they do accept the press from there. They are definitely behind the scroll view but they will scroll on and off the page when it is moved like I want them to. I have read a lot of different responses but most will not provide the answer unless you use gesture controllers. I am attaching the piece of code that creates the paging. can you let me know what I might be missing?
-(void)scollPagingSetup:(float)frameSize {
float numberOfPages;
int maxheight;
[self.view setPagingEnabled:YES];
[self.view setBounces:YES];
UIView *first = [[UIView alloc]initWithFrame:self.view.frame];
[self.view addSubview:first];
maxheight = [UIScreen mainScreen].bounds.size.height;
numberOfPages = ceil(frameSize/maxheight);
for (int i = 1; i < numberOfPages; i++) {
CGRect frame;
frame.origin.x = 0;
frame.origin.y = self.view.frame.size.height * i;
frame.size = self.view.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
[self.view addSubview:subview];
}
self.view.contentSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height *numberOfPages);
}
Thank you in advance for taking a look. I found something that would answer this problem but I was unable to grasp what the real solutions was to the problem. here is the link to that question:
IPhone UIButton doesn't respond in a UIScrollView
The problem is that the content size is not set properly so the "clickable area" (content area's size) is also not set... on your last line of code (line before the last "}") you are setting the scrollView's contentSize's frame to itself which will just be 0... try this instead (I use "first" (the nested view) instead of "self" (the scroll-view itself).
self.view.contentSize = CGSizeMake(firstframe.origin.x, (firstframe.origin.y - 20) * numberOfPages);
Note from question-poster on edited answer:
I made a change to the answer. After I worked with the app some more i was not scrolling fully. I made the change to reflect what I did to fix this and cause a full page scroll. the -20 offset was needed due to the offset of the uiscrollview. This offset can be seen in interface builder.
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;