Style UITableViewCell text using UIAppearance - ios

I've got a tableView of type Plain containing one PrototypeCell of Type Custom. The prototype cells class is the default UITableViewCell class, as I'm NOT using any specialized subclass.The problem is, that I simply want to style the textlabels contained within the default UITableViewCell (textLabel and detailTextLabel) by using UIAppearance for iOS7.
I've tried
[[UILabel appearance]] appearanceWhenContainedIn:[UITableViewCell class], nil] setTextColor:UIColor.redColor];
to no avail. I know that the Apple documentation states, that the default labels mentioned above are always created with the default font and with textcolor black. However I expected, that styling the UILabels with appearance should work out. Any ideas regarding that topic?
REMARK: I know it's possible to set the textcolors usingcell.textLabel.textColor = UIColor.redColor, but I want to define the styling once.

If you want to use this two labels, you don't have a Custom cell but a Subtitle cell. And still you can change the properties of these labels in the IB.
Just double click on the labels to change their properties. (Or have a look in ContentView on the left):

Related

Dynamic type "Body" style doesn't work in a UITableView with static cells

I'm designing a table view with static cells in Interface Builder, and I want the text size to change to support dynamic type. I've created a cell with "Basic" style, which means it contains one automatic label, and set the size of the label to "Body". But the font is always 17 points regardless of the dynamic type setting. This doesn't happen with labels I manually add to "Custom" style cells.
Screenshot:
The cell at the top is the problematic one. It's 17 points even though I've turned the dynamic type font size all the way down. The second cell was created by manually adding a label to a "Custom" style cell and setting the font size to "Body"; this is what the first cell should look like. The third label is a "Basic" style cell fixed at 17 points, for comparison.
MVCE is available here: https://drive.google.com/file/d/1-3di9-WWVsjcbktD6mxAyU4BrLR_g6nG/view. I unfortunately can't paste the code into the question because there is no code, only a storyboard. Here's how I made it:
Create a new single view project
Delete the view controller from the storyboard
Add a new UITableViewController, set it as the initial view controller
Select the table view and change "Content" to "Static Cells"
For the first cell: change "Style" to "Basic", then select the label and change Font to Text Styles - Body
Second cell: leave Style as Custom, drag in a label, and change Font to Text Styles - Body (same as above)
Third cell: change Style to Basic and don't change text size
Actually, the only solution I figured out on my side for this problem is to switch the style to Custom ⟹ you can't use the Dynamic Type feature as expected with Basic static cells. 😨
Other use cases have encountered this situation as explained in this stackoverflow answer:
Dynamic type does work with static tables, but in my tests, just not with "Basic" cell type.
Change it to a "Custom" cell type, add your label and the four constraints, and make sure to choose one of the dynamic fonts.
... and this site details every steps to get the result with illustrations if need be: 😉
To overcome this problem we must set the table view cell style to ‘Custom’ and drag a label (or labels) in ourselves.

How to make UITableViewCell read out a UIImageView automatically the way it does for UILabel with voice over

I've tried adding random labels to a UITableViewCell and the accessibility voice over system reads all of them automatically.
I'm also trying to add a UIImageView as an accesibility element and would like it to be read automatically with the cell as well. It's basically a little status icon.
I set the accessibilityLabel on the image.
I also set isAccessibilityElement to YES
Right now it treats the image as a separate object. I can select the image and or swipe left and right to read it separately instead of it being read with the cell.
Returning it in a custom accessibilityLabel getter for the cell should work too, but I'd like to use the automatic solution as much as possible. Is there some property to set on the UIImageView to have it act like a UILabel and be automatically read as well?
I think you have two options, one is a bit unclean, being create a label that is hidden with the same text and read through that.
I think the cleaner option for you is to maybe subclass ImageView and just give it a text or label property and have the accessibility voice just read over that instead.

Cannot move content view in cells in Interface Builder

I can't change a position and size of title and subtitle label in Interface Builder. What should I do?
You can't edit the position of the default UITableViewCell subviews in interface builder. You can change the text alignment, content insets, and other related properties but you can't explicitly change their frames. You can do this in code when you are displaying the cells themselves as some other answers point out, but I recommend against doing this as it can cause some other side effects when Apple makes changes to these components.
If you need to customize the position of these subviews, you should instead just build them manually. You can do this in interface builder by selecting the cell, then selecting the 4th tab on the right (Attributes Inspector), then change the Style to Custom. Once you do this, the default subviews will disappear in interface builder and you can just add your own.
You have chosen the default cell style for your cell. The Title and Subtitle labels for the chosen style you see are some basic UI controls that are meant to be used for typical scenarios of displaying content in a tableView usually. If the framing of the labels are comfortable and okay to you, then it is fine. If not, you need to make your own custom style cell.
Basically you cannot modify the default cell style that Apple provides. Just make the cell style Custom and do whatever you want with the layout.

UITableView row count like iOS Mail app

How do you add counts inside of a UITableView UITableViewCell like the iOS Mail app?
In addition to DDBadgeViewCell (mentioned by #micpringle), there's also TDBadgedCell.
I tried out both and found TDBadgedCell to suit my needs more, as it puts the badges over the cell's text rather than under it, meaning the badges are visible even for cells with long texts.
The project also seems to be (currently, at least) more active than DDBadgeViewCell. (That being said, there seems to be a bug in the non-ARC version of TDBadgedCell.)
Create a custom UITableViewCell, position the labels where you want them (title, subtitle, count, whatever you need). I highly recommend Matt Gallaghers custom UITableView code - it takes a lot of the headaches out of dealing with custom rows. You'll have to follow Matt Gallaghers steps for customizing the cell.
To get the appearance of the count label as close as possible to your example (mail.app), you'll have to set the UILabel backgroundColor to gray (or whatever color you want it to be), textColor to white, and layer.cornerRadius to something equal to half the height of the label (if label is 20 high, cornerRadius should be 10). This will result in a UILabel with white text, gray background, round corners. Note - this isn't the most efficient method of doing this, but Apple hasn't put up the WWDC session video where they explain the performant method better (I missed that session).
The easiest solution would be to set an UILabel as accessoryView or using a custom UITableViewCell subclass which could be designed using IB.
I'd recommend creating a simple rounded UIView and a UILabel as a subview in it. I'd probably create a UITableViewCell subclass to manage the content.
Definitively the most easy way would be using a ready-to-use class like TDBadgedCell

Add multiple lines to detailTextLabel in UITableViewCell

I'm using a UITableView with cell style of UITableViewCellStyleValue1.
I'm want to have multiple lines in the detailTextLabel, is that possible? Or do I have to make a custom cell?
You can set cell.detailTextLabel.numberOfLines = 2 to get 2 lines in there. However, I doubt UITableViewCell will lay out the labels as you expect in that case. You may want to subclass UITableViewCell and override -layoutSubviews to position the labels how you want. You can call [super layoutSubviews] and then just tweak the positions of the labels. You'll probably want to use -[NSString sizeWithFont:constrainedToSize:lineBreakMode:] to calculate the correct size for the detail text label.
Alternatively, instead of subclassing UITableViewCell, you could try doing the tweaks in -tableView:willDisplayCell:forRowAtIndexPath:, though if the cell ever decides it needs to re-layout, then your tweaks will be erased. I recommend you go with the subclassing approach.
Edit: BTW, with the subclass approach, all you have to do is change [UITableViewCell alloc] to [MyTableViewCellSubclass alloc]. Since you're not introducing new methods or properties, the variable can still remain typed as a UITableViewCell and you won't have to change any other code.
The detailTextLabel is a UILabel, the word wrapping rules apply just like with a label you create.
http://developer.apple.com/iphone/library/documentation/uikit/reference/UILabel_Class/Reference/UILabel.html#//apple_ref/occ/instp/UILabel/lineBreakMode
EDIT: Just thought, you'll also need to change the height of the cell if the text gets beyond some threshold of lines. probably 2 or 3 is okay.
At least on iOS 11 it works great just adding this line.
cell.detailTextLabel.numberOfLines = 2;
On SWIFT 4.0 and above:
cell.detailTextLabel?.numberOfLines = 0
Unless you never want to have more than 2 lines, do not set numberOfLines to 2 as advices in the comments because it's not an efficient way to code. It's not dynamic. The number of lines might be different base on your screen size, accessibility settings etc. Setting numberOfLines to 0, let the OS use as many lines necessary to display properly your text.

Resources