I thought I'd try and reuse the font settings and size class variations in my own view. I have my drawing code within drawRect within a UILabel class. However the size of the font isn't that I've set with my sizing classes.
OK, I know I'm not using the label as intended, but shouldn't this work ?
H
=
IB_DESIGNABLE
#interface TitleBannerView : UILabel
M
=
#implementation TitleBannerView
- (void)drawRect:(CGRect)rect {
NSLog(#"self.font.pointSize=%f", self.font.pointSize);
UIFont* textFont = [UIFont fontWithName:APP_FONT size:self.font.pointSize];
//reuse the font in my drawing code here
//Don't add the label!
//[super drawRect: rect];
Maybe you should try preferredFontDescriptorWithTextStyle which respect the user's selected content size category as described here.
UIFontDescriptor *userFont = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody];
float userFontSize = [userFont pointSize];
UIFont *font = [UIFont fontWithName:APP_FONT size:userFontSize];
You need to use the system font in IB with all your sizing classed and use this method.
#import <UIKit/UIKit.h>
#interface UILabelEx : UILabel
#end
#import "UILabelEx.h"
#import "Constants.h"
#implementation UILabelEx
- (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {
[super traitCollectionDidChange: previousTraitCollection];
self.font = [UIFont fontWithName:APP_FONT size:self.font.pointSize];
}
#end
I am trying to have dynamic font size for the textview.I have mad a custom class for the dynamic font size of text view.I have used following code for the custom class.
#import "CustomTextView.h"
#implementation CustomTextView
- (void)drawRect:(CGRect)rect
{
// Drawing code
int numLines = self.contentSize.height / self.font.lineHeight;
self.font = [UIFont fontWithName:self.font.fontName size:((self.frame.size.height / numLines) - 4)];
[super drawRect: rect];
}
#end
but this does not work.it shows a black color for the textview.please guide how to do it?
There must be something wrong while implementing "CustomTextView.h" in your ViewController.
Let us know how u have done the same.
Share your code in ViewController.
Have you added "CustomTextView" as subview in your view controller.
I'm working with and interface built using size classes and autolayout. One of the issues I'm encountering is that I can no longer use a fixed font size for the text fields - less text will be visible on smaller screens.
One of the solutions is to use "Adjust to Fit", however that option only works when there's enough text to overflow the text field horizontally.
What is the correct solution for the font size to use when the UITextField size at runtime is unknown?
Am using a custom class for all labels and am assigning two properties at the time of designing. One is autoFont and another is the fontSize which is currently the font size in iPhone 4 inch xib at design time. Here is the class.
the .h file
#import <UIKit/UIKit.h>
#interface CustomLabel : UILabel
#property (nonatomic) IBInspectable BOOL autoFont;
#property (nonatomic) IBInspectable CGFloat fontSize;
#end
and here is the .m file
#import "CustomLabel.h"
#implementation CustomLabel
#synthesize autoFont;
#synthesize fontSize;
- (void)layoutSubviews
{
[super layoutSubviews];
if (autoFont) {
float newFontSize = [UIScreen mainScreen].bounds.size.height * (fontSize / 568.0);
if ([UIScreen mainScreen].bounds.size.height < 500) {
newFontSize = [UIScreen mainScreen].bounds.size.height * (fontSize / 480.0);
}
self.font = [UIFont fontWithName:self.font.fontName size:newFontSize];
}
}
#end
i think this is the easiest solution for this kind of problem and also i have did this same thing with buttons and text fields by using custom class.
I'm aware of non interface builder soultion.
You get height of your screen and set label's font accordingly.
CGFloat windowHeight = [UIApplication sharedApplication].delegate.window.frame.size.height;
label.font = [UIFont fontWithName:#"Font-Name" size:windowHeight / 10];
How to uniquely identify iPhone 6 and iPhone 6 plus portrait screens using size classes?
My App looks good in iPhone 4 and iPhone 5 but the same looks with lots of empty spaces in iPhone 6 and 6 plus because of screen sizes. Though am using auto layout i can't increase the font size or view size only for iPhone 6 and 6 plus alone. I knew that we can change the font size and view size using size classes. but in my case don't know what to do.
Am using xCode 6.1 and my app supports from iOS 7 to latest iOS 8.1. Am expecting solution only in storyboards as am doing my UI designs fully in storyboard. If storyboard has limited functionality to achieve my needs please let me know how to achieve the same with code through out the app?
Another option to adjust the font size according to the iPhone type, is to use 'User Defined Runtime Attributes'.
Define an extension to UILabel:
extension UILabel {
var adjustFontToRealIPhoneSize: Bool {
set {
if newValue {
var currentFont = self.font
var sizeScale: CGFloat = 1
let model = UIDevice.CurrentDevice().modelName()
if model == "iPhone 6" {
sizeScale = 1.3
}
else if model == "iPhone 6 Plus" {
sizeScale = 1.5
}
self.font = currentFont.fontWithSize(currentFont.pointSize * sizeScale)
}
}
get {
return false
}
}
}
In order to determine the current model name, please refer to the following answer: https://stackoverflow.com/a/26962452/4165128
On the storyboard, select the label you wish to adjust, open the right pane, select the identity inspector, and add the 'adjustFontToRealIPhoneSize' property to the list of user defined runtime attributes (with type 'Boolean' and checkbox checked).
Do the same for each label you wish to adjust (copy & paste surprisingly works here).
Use Compact width and Regular Height in storyboard
Add layout constraint of hight and width relative with super view by adding multiplier.
Let's say you have image view which has size half the super view then add multiplier 0.5.
Check out adjustsFontSizeToFitWidth # UILabel Class Reference. This will allow you to do some nice adjustments based on the different devices.
label.adjustsFontSizeToFitWidth = YES;
I don't have too much idea of sizeClass for different font size in different iPhone devices but I figured out with this solution.
Add this method to your utility class.
Just pass your super view to this method, this method is recursive so if you pass self.view than all subviews are set.
Change your font size as you need.
-(void)setAllFonts:(UIView *)view
{
CGFloat fontSizeDiff = 0.0;
if (IS_IPHONE_6)
{
fontSizeDiff = 1;
}
else if (IS_IPHONE_6PLUS)
{
fontSizeDiff = 2;
}
for (UIView *vw in [view subviews])
{
if ([vw isKindOfClass:[UILabel class]] || [vw isKindOfClass:[UIButton class]])
{
if ([vw isKindOfClass:[UILabel class]])
{
UIFont *font = [(UILabel *)vw font];
[(UILabel *)vw setFont:[UIFont fontWithName:font.fontName size:font.pointSize+fontSizeDiff]];
}
else
{
UIFont *font = [(UIButton *)vw titleLabel].font;
[(UIButton *)vw titleLabel].font = [UIFont fontWithName:font.fontName size:font.pointSize+fontSizeDiff];
}
}
else if ([vw isKindOfClass:[UIView class]] || [vw isKindOfClass:[UIScrollView class]])
{
[self setAllFonts:vw];
}
}
}
Swift Version of #iBhaviks answer :
func getFontScaleForDevice() -> CGFloat {
var sizeScale = CGFloat(1.0)
if DeviceType.IS_IPHONE_6 {
sizeScale = 1.2
} else if DeviceType.IS_IPHONE_6P {
sizeScale = 1.4
} else if DeviceType.IS_IPAD {
sizeScale = 1.4
}
return sizeScale
}
func setAllFonts(targetView:UIView, scale:CGFloat) {
for vw in targetView.subviews {
if let vl = vw as? UILabel {
vl.font = vl.font.fontWithSize(round(vl.font.pointSize * scale))
} else if let vb = vw as? UIButton, vbl = vb.titleLabel {
vbl.font = vbl.font.fontWithSize(vbl.font.pointSize * scale)
} else if vw.subviews.count > 0 {
setAllFonts(vw, scale: scale)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
let sizeScale = getFontScaleForDevice()
if sizeScale > CGFloat(1.0) {
setAllFonts(view, scale: sizeScale)
}
view.layoutIfNeeded()
}
Maybe you could set the perfect font size for the big screens, and then set the Autoshrink to minimum font size with the perfect size for the small screens, in that way you can have a dynamic font size without coding.
You will have to set the constraints for the label to adjust its size with the screen size anyway.
Hope this help
After struggling lot just found of something for my need so posting the same for the future readers.
As of now there is no way to uniquely identify the iPhone 6 model portraits using Size classes. However you can use compact width and regular height to design for all iPhones portrait screens
To change font size you have to identify which iPhone the app currently running on using code and set the font size based on the same
For my requirement - same layout for all the screen sizes - use multiplier in widths and heights constrains. Check Jignesh answers for this question to know more about it.
EDIT 24-SEP-2015
I recently found a way to customize your size class by using UITraitColleection only for iPhone 6 plus so you don't need to write much of code. i hope this link will help someone in future.
Bit late to this but I needed a label that would scale up to any device and used this method.
Create a new subclass of UILabel and in the .h file put this…
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface OTHD_ScalableLabel : UILabel
#property (nonatomic, assign) IBInspectable CGFloat fontScale;
#end
and in the .m file put this…
#import "OTHD_ScalableLabel.h"
#implementation OTHD_ScalableLabel
- (void) layoutSubviews
{
[super layoutSubviews];
if( self.fontScale < 0.1 || self.fontScale > 1.0 ) self.fontScale = 1.0;
CGFloat height = CGRectGetHeight(self.bounds) * self.fontScale;
if( height ) self.font = [UIFont fontWithName:self.font.fontName size:height];
}
#end
You can then just change your class in IB and using IBInspectable you will be able to scale the label up or down. Obviously, for the pedantics out there, this is not a good idea for general use but there are some cases where you might need, for example, a large label that displays full screen on an iPhone as well as full screen on an iPad.
Here is an example of a function that I use to toggle between two different font size at runtime. It decides which font to use based on the horizontal size class - which essentially splits devices into two groups "iPad" and "iPhone". Here is a good refernce on whch devices belong to which size classes: http://useyourloaf.com/blog/size-classes/
iPad and Up
iPhone Plus and Down
func chooseFont(compactFont: UIFont, regularFont: UIFont) -> UIFont {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.window!.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.compact ? compactFont : regularFont
}
Based on your screen shot I would suggest using Dynamic Type. That way the user is in charge of the size of the text.
I use Storyboards heavily for my iPhone development. To keep the Labels look the same I create custom UILabels and set the font and size in the custom classes. Then in the Storyboard I assign those classes to the labels displayed in the view.
This works fine but I have 4-5 different kind of labels which only differ by size or weight. How do I deal with this situation? Currently I have the following:
PrimaryLabel
PrimaryLabelBold
DescriptionLabel
DescriptionLabelSmall
DescriptionLabelBold
I think this is too much work and these have to be a better way!!
No need to subclass UILabel so many times. Just create one subclass, like so:
MyLabel.h
typedef NS_ENUM(NSUInteger, MyLabelStyle) {
MyLabelStyleSmall,
MyLabelStyleMedium,
MyLabelStyleBig,
};
#interface MyLabel : UILabel
#property (nonatomic) MyLabelStyle style;
#end
MyLabel.m
#import "UILabel+Styles.h"
#implementation UILabel (Styles)
- (void)setStyle:(MyLabelStyle)style
{
switch (style) {
case MyLabelStyleSmall:
self.font = [UIFont systemFontOfSize:12.0];
break;
case MyLabelStyleMedium:
self.font = [UIFont systemFontOfSize:17.0];
break;
case MyLabelStyleBig:
self.font = [UIFont systemFontOfSize:22.0];
break;
default:
self.font = [UIFont systemFontOfSize:17.0];
break;
}
}
#end
In your storyboard, set the style of a particular label using User Defined Runtime Attributes:
2 corresponds to MyLabelStyleBig. Use strings instead of an enum if you want.
You can subclass the UILabel class and than create the constructor method in which you can define the type of label you want ie
PrimaryLabel
PrimaryLabelBold
DescriptionLabel
DescriptionLabelSmall
DescriptionLabelBold
For this you can create an enumeration depecting the types of Label's you want. Within the constructor method you can set this enum value.
Happy coding :)