Setting an equal width to text views in SwiftUI
Let’s take a look on how to set an equal width to multiple views where the width equals to the widest Text() view in SwiftUI. SwiftUI does not have an easy to use view modifier for this at the moment, therefore we’ll add one ourselves. Example use case is displaying two text bubbles with width equaling to the widest bubble.
Creating a content view with text bubbles
The content view contains two TextBubble views with different text. The minimum width for both Text() values are stored in the @State property. The property is updated by custom equalWidth() view modifiers in TextBubble views using bindings. In other words, the view modifier updates the minimum width based on the text in a TextBubble view and uses the calculated value for both TextBubble views.
A view modifier applying equal widths
PreferenceKeys in SwiftUI are used for propagating values from child views to ancestor views. This is what we are using here as well: TextBubble views are reading their size using a GeometryReader and then setting the width of the text to our custom EqualWidthPreferenceKey. The background view modifier is used for layering GeometryReader behind the content view which avoids GeometryReader to affect the layout. Transparent color view is only used for producing a value for the preference key which is then set to the binding in the preference key change callback. The frame view modifier reads the value and makes the returned view wider if needed.
We created a view modifier which reads a view width and propagates the value to other views using a preference key, a binding, and a @State property.