Basically, the title says everything. I'm trying to do some customization and i need to use less-than-zero width to make buttons be closer to each other.
I've learned it from this answer.
I can do it by manually setting every fixed space width, but how can I do it via [appearance] or something to make it default?
Something like this:
// works for every button not only Fixed Space
[UIBarButtonItem appearance] setWidth:-10];
!!! OR !!!
How can i set less-than-zero width in XCode? I'm creating everything using Storyboard anyway, it says that's not a valid value to set.
Any help would be really great.
I normally solve this kind of problem by subclassing the container and overriding layoutSubviews or didLayoutSubviews. This gives you a lot of control of all kind of styling behavior. In this particular case you would determine the widths programmatically and adjust the frames accordingly.
Make your instance class a subclass of this subclass, and you will have the layout code neatly separated from your implementation.
Related
I have a custom subclass of UIButton that I want to re-use in multiple projects, some of which use interface builder and storyboards, and some of which may not. It involves setting the button's frame in several places.
If I add
self.translatesAutoresizingMaskIntoConstraints = YES;
in the initialization, everything looks and works right, however, I get:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
Will attempt to recover by breaking constraint…etc
logged to the console. However, if I set
self.translatesAutoresizingMaskIntoConstraints = NO;
none of the button sizing works and the button is completely broken.
Is there a way I can suppress the error since it seems to degrade to the right thing or can I somehow manually remove the offending constraint?
I've tried dumping the constrains after the button is initialized, however, it does not seem to contain the constraint AutoLayout ends up breaking.
Edited: Below are links to a sample project and then my button code. It works great when auto layout is turned off in the storyboard, however, when auto layout is turned on, the buttons seem to position at the origin (seems to be because when initWithCoder is called, the buttons don't have superviews or any position information).
http://www.kudit.com/dump/KFB.zip
http://www.kudit.com/dump/KuditConfirmButton.zip
Your guess is correct, in that when the buttons are initialized from the storyboard (using initWithCoder:) the frame is zero - this is expected for views using autolayout - frames don't get assigned until later on.
I have your sample project mostly working under autolayout by creating a boolean ivar called hasSetup, which get set to YES inside the setup method. The setup method doesn't run if the frame is zero. I also call it again from layoutSubviews. This gets around the not-working-when-using-autolayout in storyboard problem.
The various layers still aren't the correct size though. You may want to look into resizing them from layoutSubviews.
You also can't use setFrame under autolayout - you need to make sure any constraints on your view (like the sizing constraints from the storyboard) are adjusted instead. It's going to get quite messy dealing with both possibilities.
They look really good though - hope to see them on GitHub when you've sorted these problems.
I'm coding a custom TableViewCell and I need to set a background image for each one (actually same background image on all cells) and I'll add some labels for different type of texts (different in font, size, color, etc...) and a left image hosted on a web server. I've read a tutorial on how to make the TableViewCell using IB and add it to cellForRowAtIndePath method. It worked but the image size and texts in labels are not showing like I was seeing them in IB, not wysiwyg at all lol
So, I need your help to choose the proper way to customize these cells, should I go for the IB way or programming tips are better?
Thx in advance for helping,
Stephane
I am guessing that the size of your images is going beyond the expected size of the imageView property for the left image. That usually pushes around all the other UI elements. You can avoid that by setting imageView.layer.masksToBounds of your cell to YES.
In general, for the problem you describe, I would recommend doing everything programmatically. You will have the opportunity for abstraction and include your program logic more economically.
To keep your cellForRowAtIndexPath method reasonably short, you can call your own formatCellAtIndexPath method and keep the formatting logic neatly separated from the content.
I find it easiest to create the TableViewCell in IB to start with and then, when I have it looking the way I like it, to switch to a cell built programatically.
I have a view with a UIScrollView, UIImageView for a background, and a UITextView. I have created several other views just like this and they all come out okay - with a background image and scrollable text but for some reason, now I can't make that work. Either my image overlaps all of the text so that I can't read it or the UITextView default background (white) shows up so that the user can't see the background image. What could be causing this problem?
Do you use Interface Builder or build the views hierarchy in code?
In both cases you should make sure that the order of your views is correct.
In IB the view that you want to appear on top of all the rest has to be under the rest of the views.
In code, make sure that the text view is the last to be added to the hierarchy.
You could also use the next code in order to check if this is the problem:
[self.view bringSubviewToFront:textView];
Okay, it must have had something to do with choosing the delegate. I can't say that I completely understand how I fixed it but it had to do with declaring the delegate in IB.
How do I arrange some UILabels and/or UIButtons of a variable length? I just want to add them to a UITableViewCell and they should arrange in a left-to-right flow, much like lines of text in a paragraph.
I only found possibilities to create lables with a fixed size and position using "initWithFrame:...". Same seems to be true for Interface Builder, as far as I can tell. Any solution is appreciated no matter if it's done in code or using a custom cell XIB-file.
UITableViewCell, UILabel, and UIButton are all subclasses of UIView and the documentation for UIView says:
Layout and subview management
A view may contain zero or more subviews.
Each view defines its own default resizing behavior in relation to its parent view.
A view can manually change the size and position of its subviews as needed.
So, it is certainly possible to do.
You can create your labels and buttons using initWithFrame: with the argument CGRectZero and then resize them (based on the text or whatever) using setBounds: or setFrame: (because right now you're just going to set the size of the view). Then, add these views as subviews of the cell's contentView.
Then, in a custom subclass of UITableViewCell you can implement your solution by overriding the default behavior (which does nothing) of layoutSubviews: to set the origin field of the subview's frames (i.e., CGRect) that will position the subviews in the cell's content view (the size has already been set). You may need to call setNeedsLayout: or layoutIfNeeded:.
This is really a rough outline of how it is possible to implement a solution because there are a lot of details left out. For example, if you resize a button based on the the text of the titleLabel you'll probably want to pad some to the width and height otherwise the button will be the size of the label and will look odd. In the layoutSubviews: method there could be a fair amount of logic to layout the labels and buttons the way you want (e.g., it would be simpler if all the subviews of a cell where of the same type such as all labels) esp. if the subviews could wrap to a new line.
For multiline UILabels to get the width and height you should use the NSString method sizeWithFont:constrainedToSize:lineBreakMode: you can then use the sizes you get to lay everything out where it needs to be.
I want to do the same thing to allow users to enter tags into a text field - a bit like how when you type in an email address, the address gets converted into a blue tag (the the users name in when that users email address is already in your contacts list). Haven't written it yet, but will be happy to share with you once I do. I can't commit to how long it I will take to write this unfortunately. However if no one else has code they can share and you need to get the job done quickly - Just as a tip, consider this:
Create tag view objects where each object knows the size of the parent text field/tag container view and where each tag object has a utility method which a further tag object can use to insert itself at the right position. This approach makes it easy to manage the view and relayout tags using a simple iteration flow.
Hi
If you still need an answer...
To get the size of text (and to then calculate the frame of the UILabel/UIButton etc) use the sizeWithFont: NSString function which will give you the width/height of a string of text using a specified font.
There is a little bit of maths that you'll need to do to work out the best fit, where to place the UILabels, and the spacing, but you will have the data that you need to do it.
Hope this helps!
I have a loadView call that basically places one view at the top (like a header) and one at the bottom (like a footer). It's possible via a passed in parameter to not have a header or a footer, to hide them later, or to resize the view. I have all this working, but it's very susceptible to breaking because the views can go in various places of various sizes and all must be manually set to the correct size or they will not use up all the space. I want one in between the two of them that automatically resizes to fill whatever space is not taken by the others.
loadView doesn't seem to be able to obtain the size of its parent's frame (or where it's being fit in, exactly), nor do I see an obvious way to just put the center view at a certain position and have its width and height automatically adapted.
Any ideas?
If I'm not explaining myself well enough and you know Java Swing, think BorderLayout with a BorderLayout.NORTH, BorderLayout.SOUTH, and BorderLayout.CENTER component.
loadView isn't a good place for this. You really want to use viewWillAppear instead. Setting autoresizeMask to have fixed borders should do what you want without having to worry about calculating layout, and it's best to do this all in IB rather than doing manual layout all the time.