[#179] Broken Onboarding UI for .accessibilityLarge (#504)

- reimagined the way the onboarding is composed
- the bare bone is now a VStack instead of a ZStack
- there is no use of GeometryReader anymore
This commit is contained in:
Lukas Korba 2022-12-08 07:37:00 +01:00 committed by GitHub
parent d11a67cee1
commit 1cf49e7b72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 57 deletions

View File

@ -12,7 +12,7 @@ struct OnboardingScreen: View {
let store: Store<OnboardingFlowReducer.State, OnboardingFlowReducer.Action> let store: Store<OnboardingFlowReducer.State, OnboardingFlowReducer.Action>
var body: some View { var body: some View {
GeometryReader { proxy in VStack {
ZStack { ZStack {
OnboardingHeaderView( OnboardingHeaderView(
store: store.scope( store: store.scope(
@ -32,14 +32,12 @@ struct OnboardingScreen: View {
) )
.zIndex(1) .zIndex(1)
OnboardingContentView( OnboardingContentView(store: store)
store: store,
width: proxy.size.width,
height: proxy.size.height
)
OnboardingFooterView(store: store)
} }
Spacer()
OnboardingFooterView(store: store)
} }
.navigationBarHidden(true) .navigationBarHidden(true)
.applyScreenBackground() .applyScreenBackground()
@ -81,7 +79,8 @@ struct OnboardingScreen_Previews: PreviewProvider {
) )
) )
.preferredColorScheme(.light) .preferredColorScheme(.light)
.previewDevice(PreviewDevice(rawValue: "iPhone 12 Pro")) .previewDevice(PreviewDevice(rawValue: "iPhone 14 Pro"))
.environment(\.sizeCategory, .accessibilityLarge)
OnboardingScreen( OnboardingScreen(
store: Store( store: Store(
@ -114,6 +113,6 @@ struct OnboardingScreen_Previews: PreviewProvider {
) )
) )
.preferredColorScheme(.dark) .preferredColorScheme(.dark)
.previewDevice(PreviewDevice(rawValue: "iPhone 12 Pro")) .previewDevice(PreviewDevice(rawValue: "iPhone 14 Pro"))
} }
} }

View File

@ -10,69 +10,51 @@ import ComposableArchitecture
struct OnboardingContentView: View { struct OnboardingContentView: View {
let store: Store<OnboardingFlowReducer.State, OnboardingFlowReducer.Action> let store: Store<OnboardingFlowReducer.State, OnboardingFlowReducer.Action>
let width: Double
let height: Double
var body: some View { var body: some View {
WithViewStore(self.store) { viewStore in WithViewStore(self.store) { viewStore in
let scale = imageScale
let imageWidth: CGFloat = width * scale
let imageXOffset: CGFloat = (width - imageWidth) / 2
let image = viewStore.steps[viewStore.index].background let image = viewStore.steps[viewStore.index].background
.resizable() .resizable()
.aspectRatio(contentMode: .fit) .scaledToFit()
.frame(width: imageWidth)
.offset(x: imageXOffset)
let title = Text(viewStore.steps[viewStore.index].title) let title = Text(viewStore.steps[viewStore.index].title)
.titleText() .titleText()
.lineLimit(0) .lineLimit(0)
.minimumScaleFactor(0.1) .minimumScaleFactor(0.1)
.padding(EdgeInsets(top: 0, leading: 10, bottom: 5, trailing: 10)) .padding(.vertical, 10)
let text = Text(viewStore.steps[viewStore.index].description) let text = Text(viewStore.steps[viewStore.index].description)
.paragraphText() .paragraphText()
.lineSpacing(2) .lineSpacing(2)
.padding(EdgeInsets(top: 0, leading: 10, bottom: 10, trailing: 10)) .minimumScaleFactor(0.1)
.padding(.horizontal, 20)
if viewStore.isFinalStep { if viewStore.isFinalStep {
VStack(alignment: .leading) { VStack {
title HStack {
.padding(.top, 73 * imageScale) title
.padding(.top, 60)
Spacer()
}
.padding(.horizontal, 20)
text text
image image
Spacer()
} }
} else { } else {
VStack(alignment: .leading) { VStack {
image image
title HStack {
title
Spacer()
}
.padding(.horizontal, 20)
text text
Spacer()
} }
} }
} }
} }
} }
/// Following computations are necessary to handle properly sizing and positioning of elements
/// on different devices (apects). iPhone SE and iPhone 8 are similar aspect family devices
/// while iPhone X, 11, etc are different family devices, capable to use more of the space.
extension OnboardingContentView {
var imageScale: CGFloat {
// Just to be sure that we counting with exactly 3 decimal points.
let aspectRatio = (floor(height / width * 1000)) / 1000
/// iPhone SE or iPhone 8 for example
if aspectRatio <= 1.725 {
return 0.7
} else {
return 1.0
}
}
}
struct OnboardingContentView_Previews: PreviewProvider { struct OnboardingContentView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
let store = Store( let store = Store(
@ -119,9 +101,9 @@ extension OnboardingContentView_Previews {
.zIndex(1) .zIndex(1)
OnboardingContentView( OnboardingContentView(
store: store, store: store
width: proxy.size.width, // width: proxy.size.width,
height: proxy.size.height // height: proxy.size.height
) )
} }
} }

View File

@ -15,26 +15,27 @@ struct OnboardingFooterView: View {
var body: some View { var body: some View {
WithViewStore(self.store) { viewStore in WithViewStore(self.store) { viewStore in
VStack(spacing: 5) { VStack(spacing: 5) {
Spacer()
if viewStore.isFinalStep { if viewStore.isFinalStep {
Button("onboarding.button.newWallet") { Button("onboarding.button.newWallet") {
viewStore.send(.createNewWallet, animation: .easeInOut(duration: animationDuration)) viewStore.send(.createNewWallet, animation: .easeInOut(duration: animationDuration))
} }
.activeButtonStyle .activeButtonStyle
.onboardingFooterButtonLayout() .onboardingFooterButtonLayout()
.minimumScaleFactor(0.1)
Button("onboarding.button.importWallet") { Button("onboarding.button.importWallet") {
viewStore.send(.importExistingWallet, animation: .easeInOut(duration: animationDuration)) viewStore.send(.importExistingWallet, animation: .easeInOut(duration: animationDuration))
} }
.secondaryButtonStyle .secondaryButtonStyle
.onboardingFooterButtonLayout() .onboardingFooterButtonLayout()
.minimumScaleFactor(0.1)
} else { } else {
Button("Next") { Button("Next") {
viewStore.send(.next, animation: .easeInOut(duration: animationDuration)) viewStore.send(.next, animation: .easeInOut(duration: animationDuration))
} }
.primaryButtonStyle .primaryButtonStyle
.onboardingFooterButtonLayout() .onboardingFooterButtonLayout()
.minimumScaleFactor(0.1)
ProgressView( ProgressView(
String(format: "%02d", viewStore.index + 1), String(format: "%02d", viewStore.index + 1),
@ -46,6 +47,7 @@ struct OnboardingFooterView: View {
.padding(.vertical, 20) .padding(.vertical, 20)
} }
} }
.padding(.top, 10)
.navigationLinkEmpty( .navigationLinkEmpty(
isActive: viewStore.bindingForDestination(.importExistingWallet), isActive: viewStore.bindingForDestination(.importExistingWallet),
destination: { destination: {
@ -93,7 +95,8 @@ struct OnboardingFooterView_Previews: PreviewProvider {
OnboardingFooterView(store: store) OnboardingFooterView(store: store)
.applyScreenBackground() .applyScreenBackground()
.preferredColorScheme(.light) .preferredColorScheme(.light)
.previewDevice("iPhone 13 Pro Max") .previewDevice("iPhone 14 Pro")
.environment(\.sizeCategory, .accessibilityLarge)
OnboardingFooterView(store: store) OnboardingFooterView(store: store)
.applyScreenBackground() .applyScreenBackground()

View File

@ -33,6 +33,7 @@ struct OnboardingHeaderView: View {
.navigationButtonStyle .navigationButtonStyle
.frame(width: 75) .frame(width: 75)
.disabled(viewStore.isInitialStep) .disabled(viewStore.isInitialStep)
.minimumScaleFactor(0.1)
} }
Spacer() Spacer()
@ -44,6 +45,7 @@ struct OnboardingHeaderView: View {
.navigationButtonStyle .navigationButtonStyle
.disabled(viewStore.isFinalStep) .disabled(viewStore.isFinalStep)
.frame(width: 75) .frame(width: 75)
.minimumScaleFactor(0.1)
} }
} }
.padding(.horizontal, 30) .padding(.horizontal, 30)
@ -51,7 +53,6 @@ struct OnboardingHeaderView: View {
Spacer() Spacer()
} }
.padding(.top, 5)
} }
} }
} }

View File

@ -47,7 +47,7 @@ extension Text {
func body(content: Content) -> some View { func body(content: Content) -> some View {
content content
.foregroundColor(Asset.Colors.Text.heading.color) .foregroundColor(Asset.Colors.Text.heading.color)
.font(.custom(FontFamily.Rubik.regular.name, size: 33, relativeTo: .callout)) .font(.custom(FontFamily.Rubik.medium.name, size: 33, relativeTo: .callout))
.shadow(color: Asset.Colors.Text.captionTextShadow.color, radius: 1, x: 0, y: 1) .shadow(color: Asset.Colors.Text.captionTextShadow.color, radius: 1, x: 0, y: 1)
} }
} }