Dynamic Type and Widget Layout

I have a ToDo list app with an accompanying widget that displays upcoming items with an 'n more...' label at the bottom if they don't all fit.

At the moment the number of rows is hard-coded based on widget family (4 for small and medium, 11 for large).

How do I make the row count and 'more' text adjust for dynamic type sizes? Small and medium fonts should display 4 rows while large will only fit 3 before content is pushed off the bottom.

Accepted Reply

To answer my own question:

Use ViewThatFits and build views with every possible count. Seems unnecessarily expensive but it works.

var body: some View {
	ViewThatFits {
		ForEach((1...entry.toDos.count).reversed(), id: \.self) { limit in
			VStack(alignment: .leading, spacing: 4) {
				ForEach(entry.toDos.prefix(limit), id: \.self.identifier) { entry in
					ToDoView(checked: entry.completed, flag: entry.flag, text: entry.name)
				}
				if (limit < entry.toDos.count) {
					Text(String(format:NSLocalizedString("%i more...", comment: "[n] more..."), entry.toDos.count - limit))
						.font(.footnote)
						.foregroundStyle(.secondary)
						.padding(.leading, 24)
						.padding(.top, -3)
						.unredacted()
				}
			}
		}
	}
}

Replies

To answer my own question:

Use ViewThatFits and build views with every possible count. Seems unnecessarily expensive but it works.

var body: some View {
	ViewThatFits {
		ForEach((1...entry.toDos.count).reversed(), id: \.self) { limit in
			VStack(alignment: .leading, spacing: 4) {
				ForEach(entry.toDos.prefix(limit), id: \.self.identifier) { entry in
					ToDoView(checked: entry.completed, flag: entry.flag, text: entry.name)
				}
				if (limit < entry.toDos.count) {
					Text(String(format:NSLocalizedString("%i more...", comment: "[n] more..."), entry.toDos.count - limit))
						.font(.footnote)
						.foregroundStyle(.secondary)
						.padding(.leading, 24)
						.padding(.top, -3)
						.unredacted()
				}
			}
		}
	}
}