iOS: layout change for accessibility font sizes

3.7k Views Asked by At

Apple contacts app displays contact info screen with avatar and action buttons (message, call, video, mail) laid out horizontally under avatar. When user changes font size in Settings > General > Accessibility > Larger Text > Larger Accessibility Size on > one of those Accessibility fonts selected then layout changes to have those actions buttons to be laid out vertically under avatar. Individual button layout changes to have text to the right of the image (from being below the image).

What is the best approach to achieve this without completely defining new layout in code for each case. Android would allow for inflating new layout for each case, but in iOS this presents stack of problems as outlined in Best way to change UIViewController view NIB programmatically. Other option of creating additional ViewControllers seems extreme as well: Easiest way to support multiple orientations? How do I load a custom NIB when the application is in Landscape?

I can correctly detect when font sizes are in Accessibility Category and flip axis of UIStack that contains action buttons, but short of changing layout programmatically I am stuck there.

2

There are 2 best solutions below

0
On

You might find answers in the WWDC 2017 : Building Apps with Dynamic Type video whose content is perfectly summarized here.

When you detect that an accessibility size is concerned, you should adapt your constraints in the traitCollectionDidChange method of the UITraitEnvironment protocol (iOS 11): take a look at the example section where the question How can I change items position to adapt text enlargement is well explained.

0
On

I ran into the same situation myself and following is the approach I took:

  1. Use UIStackView where ever possible. This is very useful as you'll see later.
  2. Traditionally, the above will be a horizontal layout for non-accessibility layouts. If they are vertical layouts as required by your design, that's okay too.
  3. To detect accessibility content modes, I'm using the following snippet:

    BOOL isAccessibilityType = [[[UIApplication sharedApplication] preferredContentSizeCategory] containsString:@"Accessibility"];
    

Note that the above can break if Apple changes the NSString value of those variables in a future update. You can also wrap the above in a C style function.

  1. Based on the output above, you can determine if the UIStackView layout should be vertical or horizontal. For accessibility modes, use Vertical and for non-accessibility modes, use horizontal. Keep your vertical layouts as they are.

  2. You can take this a step further by adjusting font-weights if you're using Dynamic Type. To balance text, you can make bold text semi-bold, semi-bold text medium and so on. But this is very situational.

  3. Observe the UIContentSizeCategoryDidChangeNotification notification to know when the user's preferred content size changes and adapt your interfaces accordingly.

If you're already using UIStackViews, you already have everything setup for you. If not, you'll have to determine a strategy to update your layouts either using them or some other mechanism.

I hope my answer helps you or guides you in the right direction.

EDIT: Perhaps I didn't completely read your question. Sorry about that.

I can correctly detect when font sizes are in Accessibility Category and flip axis of UIStack that contains action buttons, but short of changing layout programmatically I am stuck there.

Once you set the correct axis on the UIStackView you'll be required to do:

[stackView setNeedsUpdateConstraints];  
[stackView layoutIfNeeded];