Hello,
If we have the following code:
import SwiftUI
struct ContentView: View {
@State private var usdAmount = 0.0
var body: some View {
VStack {
Text("Currency Form")
Form {
TextField("Dollar Amount", value: $usdAmount, format: .currency(code: "USD")) // 1
// TextField("Dollar Amount", value: $usdAmount, format: .number) // 2
.keyboardType(.numberPad)
}
Text("usdAmount = \(usdAmount)")
}
.padding()
}
}
When the line marked // 1 is left uncommented (the TF has a .currency() formatter applied) the behaviour of the TF is rather odd.
Upon display it shows US$0.00
Upon editing the value the US$ part remains. So if the user enters US$123 the value is not stored into the usdAmount property.
The User must delete all the existing text and enter e.g. 456.78 and then the value is stored to the usdAmount property.
When Line //1 is commented-out and line //2 is uncommented then the TF behaves correctly because the TF value is just 0 on first display.
Should we not use the .currency() format? Or am I using it wrong?
Thanks.
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Post
Replies
Boosts
Views
Activity
After 5 years, 6 releases, SwiftUI still miss fundamental feature, lock interface orientation by view (can be by container, modal, …).
Many apps for iPhone just want portrait orientation but in some cases needed a modal in lanscape for a photo viewer or video player. Interface orientation options in info.plist just don’t work because will lock all views in the app.
I have a list view that is accessed by pressing a button from a pervious view, all are which are in a NavigationView from the Main view. For this list view I have applied the .searchable tag to allow users to search through the list. When a user taps on an item in the list a .sheet will present to present a more detailed overview.
The issue happens that if a user searches for an item in the list, and taps on the item to present the sheet the keyboard will disappear while the sheet presents but then pop back up despite still editing the search bar on the list view.
Currently, my view is roughly set up like this.
var body: some View {
ThemesListView
}
.sheet(item: $presentedSheetTheme, onDismiss: { fetchedThemes.nsSortDescriptors = themeListSort.nsSortDescriptorObject }) {themeToPassOn in
EditThemeView(themeToEdit: themeToPassOn) }
var ThemesListView: some View {
List {
Button(action: {
presentedSheetTheme = theme
}
}
.searchable(text: query, placement: .navigationBarDrawer(displayMode: .always))
}
I have tried many things to fix this, even finding this thread (https://forums.developer.apple.com/forums/thread/746826) however none of the solutions were any help.
Here is a link (https://imgur.com/a/KKJ27iY) to a video of the issue.
This issue seems to be fixed in some iOS versions such as 17.0 and 18.0 Beta 1 however many other versions such as 17.4 or 17.5 still experience this issue meaning I still need to fix it for these versions.
Any help would be greatly appreciated, thanks!
I am trying to change the colour of the "Back" from blue to white but having difficulty do so, if anyone can suggest me a better way to do it would be grateful.
"import UIKit
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = UIColor(red: 0.216, green: 0.776, blue: 0.349, alpha: 1)
appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
UINavigationBar.appearance().tintColor = .white
return true
}
}"
See FB13917278 (App Becomes Unresponsive for iOS/iPadOS 18 Regular Size Class Interactions When Selecting One Particular View in Sidebar).
The widget I have create for iOS 17 uses the containerBackground to display an image in the background. This works fine. But when I set the home screen to the iOS 18 tinted option the background disappears. I want the background to stay because it contains an image of that is meaningful to the user.
I use the following code:
@ViewBuilder
var body: some View {
if let memory = entry.memory, let uiImage = memory.image {
Group {
if entry.showCaption {
memoryBody(with: memory)
} else {
Color.white.opacity(0.0000000001)
}
}
.foregroundStyle(.white)
.widgetBackground(
Image(uiImage: uiImage)
.resizable()
.scaledToFill()
)
} else if let memory = entry.memory {
memoryBody(with: memory)
.widgetBackground(Color.gray)
} else {
noMemoryBody()
}
}
extension View {
func widgetBackground(_ backgroundView: some View) -> some View {
if #available(iOSApplicationExtension 17.0, *) {
return containerBackground(for: .widget) {
backgroundView
}
} else {
return background(backgroundView)
}
}
}
struct Question {
var title: String
var options : [String]
}
struct SimpleQuestions: View {
@State var selectedOption = ""
@State var question = Question(title: "question title", options: \["one", "two", "three"\])
var body: some View {
VStack {
Text(question.title)
ForEach(question.options, id: \.self) { option in
HStack {
Button {
selectedOption = option
} label: {
Circle()
.foregroundStyle(selectedOption == option ? .blue : .gray.opacity(0.5))
.frame(width: 23, height: 23)
}}}}}
Hello,
I have a view has two textfields(a and b) and a button.
I want to move focus between textfields using enter key. that is;
enter value on a -> presss enter key -> enter value on b
How can I do it in swiftUI?
if someone give me an advice about it, I'd de very appreciated.
thanks,
c00012
I used to be able to show my app's icon in the UI using this code:
if let icon = UIImage(named: "AppIcon") {
Image(uiImage: icon)
.resizable()
.frame(width: 64, height: 64)
.cornerRadius(10)
}
But this doesn't work when building with Xcode 16 and iOS 18 SDK.
How can I show my app's icon in the UI without resorting to duplicating the asset?
I am developing an application that has a 3D model, developed on blender in parts and then combined and pushed to Reality Composer Pro. I would like to be able to select parts of the model such as the right arm, and when that's done, a description window to open up with more information. How do I go about selecting a part of my model?
When will SwiftUI plot will support dates on the x-axes (hrs, month, years) and when will the plot library supports logarithmic scales.
Great progress so far.
Thanks.
The Human Interface Guidelines for Live Activities provide several examples of compact presentations that have a timer counting down formatted like "3min" or "3m", similar to the timers in the Clock app. Such examples can be found in this Stack Overflow question: https://stackoverflow.com/questions/77551496/is-it-possible-to-make-an-only-minutes-1m-countdown-in-a-live-activity
A Timer initialized with init(timerInterval:pauseTime:countsDown:showsHours:) has provided a live countdown timer in widgets and live activities, but the formatting is limited. And since live activities come with limitations that prevent us from using Timers, there's no real way to implement this kind of thing ourselves.
What is Apple's official guidance for implementing this kind of timer for the compact presentation?
It is pretty cool that you can preview Spatial Photos and Videos with just PreviewApplication.push(...), but the issue is, you can disable the editing, but buttons to export content to Files still going to be there.
So if my application uses this to showcase some proprietary or licensed content in my application, I cannot really disable an option of exporting it from my app. And another, more major issue, a lot of developers would not even know that user can save Previewed item, as this Save to Files button is not that easy to find.
I am using ShareLink to share a URL. That URL is using the opengraph tags for audio (og:audio). If a users taps messages on the share sheet before the preview is rendered then sends the messages, they never see the rich URL preview. I don't know if this is a bug in the share sheet or if there is something I should be doing differently.
If the user waits until the preview is rendered on the share sheet everything works fine.
Also, if I go to Safari and share the same URL it works as expected.
I've filed FB13900806 for this but I'm looking for workarounds or guidance on better ways to do this.
tl;dr: My view layout breaks when Dynamic Type is set to Medium, AX1, or AX2, because a Spacer() incorrectly collapses to zero height.
Details:
I'm trying to build out a vertically scrollable view with the following:
A top header view that does not scroll.
A scroll view, which contains a variable amount of content that will not always fill the screen
A bottom view that is scrollable, but should be bottom aligned if the content doesn't fill the screen.
Here's how it should look:
I'm using the following logic to achieve this, which works for most Dynamic Type sizes:
import SwiftUI
struct CollapsingSpacerView: View {
var body: some View {
VStack {
Text("Non scrollable, top aligned content")
GeometryReader { geometry in
ScrollView(.vertical) {
VStack(spacing: 20) {
Text("Scrollable, top aligned content")
Color.red
.frame(width: 200, height: 200)
Spacer()
Text("Scrollable, bottom aligned content")
}
.frame(minWidth: geometry.size.width, minHeight: geometry.size.height)
.border(.blue)
}
.border(.green)
}
}
}
}
#Preview("spacer") {
CollapsingSpacerView()
}
However, when I change the Dynamic Type setting to one of: Medium, AX1, or AX2, the Spacer stops spacing and all of the scrollable content gets compressed around the vertical center, like this:
Is there a better way to get this layout without relying on Spacer? One workaround I've found is to give the non-scrolling header a fixed height, but that's less than ideal and would love to hear other options.
Hey there,
I am currently developing a SwiftUI app for iPad.
However, I am currently experiencing a behavior, that I can not explain.
My code creates a user-management view. This all works fine if I run it on my iPad Pro with Apple-M-Chip. However, if I try to run the exact same code on an older A-Chip iPad Air (4th Generation), my app crashes.
I can recreate this behavior in the simulator on my Mac. When I run it on an iPad Pro Simulator, all works fine. When I run it in an iPad Air (4th Gen) simulator, the app becomes unresponsive.
Unfortunatley Xcode does not throw any error that I could use to identify the problem.
Currently I solved it with a work-around: As soon as I add a Spacer (even with a with of 0) the code works as expected and the UI is shown. As soon as I remove the Spacer, it crashes again.
HStack(alignment: .top){
VStack{
if(data.ui_user.id != -1){
HStack{
Text("Employee-No.:")
Spacer()
TextField("Employee-No.", value: $data.ui_user.id, format: .number).textFieldStyle(.roundedBorder).disabled(true).containerRelativeFrame(.horizontal, count: 10, span: 3, spacing: 0)
}
}
HStack{
Text("Family Name:")
Spacer()
TextField("Family Name", text: $data.ui_user.familyName).textFieldStyle(.roundedBorder).containerRelativeFrame(.horizontal, count: 10, span: 3, spacing: 0)
}
HStack{
Text("Given Name:")
Spacer()
TextField("Given Name", text: $data.ui_user.givenName).textFieldStyle(.roundedBorder).containerRelativeFrame(.horizontal, count: 10, span: 3, spacing: 0)
}
HStack{
Text("Role:")
Spacer()
Picker("Select role", selection: $data.selectedRole){
ForEach(0 ..< self.availableRoles.count, id:\.self){
Text(self.availableRoles[$0].name ?? "???").tag($0)
}
}.pickerStyle(.menu).containerRelativeFrame(.horizontal, count: 10, span: 3, spacing: 0).background(.drkBlueContainer).cornerRadius(5).foregroundColor(.drkOnBlueContainer).tint(.drkOnBlueContainer)
//If I add this spacer, it works. If not, it crashes
//Spacer().frame(width: 0.0)
}.disabled(noEditAdmin && data.ui_user.id != -1)
}
Divider()
VStack{
HStack{
Text("Created at:")
Spacer()
TextField("Created at", value: $data.ui_user.createdAt, format: .dateTime).textFieldStyle(.roundedBorder).disabled(true).containerRelativeFrame(.horizontal, count: 10, span: 3, spacing: 0)
}
HStack{
Toggle("Terminates:", isOn: $data.ui_user.expires)
.padding(.trailing, 2.0)
}
if(data.ui_user.expires){
HStack{
DatePicker("Terminates at:", selection: $data.ui_user.expiresAt, displayedComponents: .date).pickerStyle(.automatic)
}}
}
}
If anyone has any ideas, I would be very grateful for a hint :-)
Hello,
I have a view has 4 textfields and a button.
I want to show 4 values from textfields on popup messagebox. so I wrote a following codes.
@State private var lender = ""
@State private var amount = ""
@State private var rate = ""
@State private var duration = ""
Button(action: {showingAlert = true},
label: {
Text("Inputs")
.padding()
.background(RoundedRectangle(cornerRadius: 10).strokeBorder())
}).padding(10)
.accentColor(.green)
.alert("Inputs", isPresented: $showingAlert){
Text("Lender: \(lender)").font(.title3)
Text("Amount:\(amount)").font(.title3)
Text("Rate:\(rate)")
Text("Duration:\(duration)")
Button("OK", role: .cancel){}
}
When I run this code, Alert popped up but there's no values.
If someone point my mistakes, I'd very appreciated.
thanks,
c00012
I'm building a Swift Chart that displays locations in a horizontal timeline. The chart is scrollable.
When the chart is zoomed in, I want to show an annotation for every 6 hours.
Unfortunately, when axisMarks are set to .stride(by: .hour, count: 6), the annotations do not appear for the first several months in the timeline. I tried setting .stride(by: .minute, count: 360), but the result is the same.
Is this a Swift Charts bug, or am I doing something wrong?
A reproducible example is below. To reproduce:
Run the code below
See that annotations are missing at the leading edge of the chart. They only show up from a certain point on the chart's domain.
Tested on various iPhone and iPad simulators and physical devices, the issue appears everywhere.
P.S. I am aware that the example code below is not performant and that the annotations overlap when the chart is zoomed out. I have workarounds for that, but it's beyond the scope of my question and the minimum reproducible example.
struct ChartAnnotationsBug: View {
/// Sample data
let data = SampleData.samples
let startDate = SampleData.samples.first?.startDate ?? Date()
let endDate = Date()
/// Scroll position of the chart, expressed as Date along the x-axis.
@State var chartPosition: Date = SampleData.samples.first?.startDate ?? Date()
/// Sets the granularity of the shown view.
@State var visibleDomain: VisibleDomain = .month
var body: some View {
Chart(data, id: \.id) { element in
BarMark(xStart: .value("Start", element.startDate),
xEnd: .value("End", element.endDate),
yStart: 0,
yEnd: 50)
.foregroundStyle(by: .value("Type", element.type.rawValue))
.clipShape(.rect(cornerRadius: 8, style: .continuous))
}
.chartScrollableAxes(.horizontal) // enable scroll
.chartScrollPosition(x: $chartPosition) // track scroll offset
.chartXVisibleDomain(length: visibleDomain.seconds)
.chartXScale(domain: startDate...endDate)
.chartXAxis {
AxisMarks(values: .stride(by: .hour, count: 6)) { value in
if let date = value.as(Date.self) {
let hour = Calendar.current.component(.hour, from: date)
if hour == 0 { // midnight
AxisValueLabel(collisionResolution: .truncate) {
VStack(alignment: .leading) {
Text(date, format: .dateTime.hour().minute())
Text(date, format: .dateTime.weekday().month().day())
.bold()
}
}
AxisTick(stroke: .init(lineWidth: 1))
} else if [6, 12, 18].contains(hour) { // period
AxisValueLabel(collisionResolution: .truncate) {
Text(date, format: .dateTime.hour().minute())
}
AxisTick(length: .label)
}
}
}
}
.frame(height: 100)
.padding(.bottom, 40) // for overlay picker
.overlay {
Picker("", selection: $visibleDomain.animation()) {
ForEach(VisibleDomain.allCases) { variant in
Text(variant.label)
.tag(variant)
}
}
.pickerStyle(.segmented)
.frame(width: 240)
.padding(.trailing)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
} //: overlay
} //: body
} //: struct
// MARK: - Preview
#Preview {
ChartAnnotationsBug()
}
// MARK: - Data
enum SampleDataType: String, CaseIterable {
case city, wood, field
var label: String {
switch self {
case .city:
"City"
case .wood:
"Wood"
case .field:
"Field"
}
}
}
enum VisibleDomain: Identifiable, CaseIterable {
case day
case week
case month
var id: Int {
self.seconds
}
var seconds: Int {
switch self {
case .day:
3600 * 24 * 2
case .week:
3600 * 24 * 10
case .month:
3600 * 24 * 40
}
}
var label: String {
switch self {
case .day:
"Days"
case .week:
"Weeks"
case .month:
"Months"
}
}
}
struct SampleData: Identifiable {
let startDate: Date
let endDate: Date
let name: String
let type: SampleDataType
var id: String { name }
static let samples: [SampleData] = [
.init(startDate: Date.from(year: 2024, month: 3, day: 1, hour: 23, minute: 59),
endDate: Date.from(year: 2024, month: 3, day: 10),
name: "New York",
type: .city),
.init(startDate: Date.from(year: 2024, month: 3, day: 10, hour: 6),
endDate: Date.from(year: 2024, month: 3, day: 20),
name: "London",
type: .city),
.init(startDate: Date.from(year: 2024, month: 3, day: 20),
endDate: Date.from(year: 2024, month: 4, day: 10),
name: "Backcountry ABC",
type: .field),
.init(startDate: Date.from(year: 2024, month: 4, day: 10),
endDate: Date.from(year: 2024, month: 4, day: 20),
name: "Field DEF",
type: .field),
.init(startDate: Date.from(year: 2024, month: 4, day: 20),
endDate: Date.from(year: 2024, month: 5, day: 10),
name: "Wood 123",
type: .wood),
.init(startDate: Date.from(year: 2024, month: 5, day: 10),
endDate: Date.from(year: 2024, month: 5, day: 20),
name: "Paris",
type: .city),
.init(startDate: Date.from(year: 2024, month: 5, day: 20),
endDate: Date.from(year: 2024, month: 6, day: 5),
name: "Field GHI",
type: .field),
.init(startDate: Date.from(year: 2024, month: 6, day: 5),
endDate: Date.from(year: 2024, month: 6, day: 10),
name: "Wood 456",
type: .wood),
.init(startDate: Date.from(year: 2024, month: 6, day: 10),
endDate: Date(),
name: "Field JKL",
type: .field)
]
}
extension Date {
/**
Constructs a Date from a given year (Int). Use like `Date.from(year: 2020)`.
*/
static func from(year: Int? = nil, month: Int? = nil, day: Int? = nil, hour: Int? = nil, minute: Int? = nil) -> Date {
let components = DateComponents(year: year, month: month, day: day, hour: hour, minute: minute)
guard let date = Calendar.current.date(from: components) else {
print(#function, "Failed to construct date. Returning current date.")
return Date()
}
return date
}
}
I'm building a Swift Chart that displays locations in a horizontal timeline. The chart is scrollable.
Unfortunately, when chartScrollPosition is offset by some amount (i.e. the user has scrolled the chart), changing chartXVisibleDomain results in chartScrollPosition jumping backwards by some amount.
This results in bad user experience.
A minimum reproducible example is below. To reproduce:
Run the code below
Using the picker, change chartXVisibleDomain. ThechartScrollPosition remains the same, as expected.
Scroll the chart on the horizontal axis.
Using the picker, change chartXVisibleDomain. ThechartScrollPosition changes unexpectedly.
You can verify this by watching the labels at the bottom of the chart. The chart simply ends up showing a different area of the domain. Tested on various iPhone and iPad simulators and physical devices, the issue appears everywhere.
Is this a SwiftUI bug, or am I doing something wrong?
struct ScrollableChartBug: View {
/// Sample data
let data = SampleData.samples
let startDate = SampleData.samples.first?.startDate ?? Date()
let endDate = Date()
/// Scroll position of the chart, expressed as Date along the x-axis.
@State var chartPosition: Date = SampleData.samples.first?.startDate ?? Date()
/// Sets the granularity of the shown view.
@State var visibleDomain: VisibleDomain = .year
var body: some View {
Chart(data, id: \.id) { element in
BarMark(xStart: .value("Start", element.startDate),
xEnd: .value("End", element.endDate),
yStart: 0,
yEnd: 50)
.foregroundStyle(by: .value("Type", element.type.rawValue))
.clipShape(.rect(cornerRadius: 8, style: .continuous))
}
.chartScrollableAxes(.horizontal) // enable scroll
.chartScrollPosition(x: $chartPosition) // track scroll offset
.chartXVisibleDomain(length: visibleDomain.seconds)
.chartXScale(domain: startDate...endDate)
.chartForegroundStyleScale { typeName in
// custom colors for bars and for legend
SampleDataType(rawValue: typeName)?.color ?? .clear
}
.chartXAxis {
AxisMarks(values: .stride(by: .month, count: 1)) { value in
if let date = value.as(Date.self) {
AxisValueLabel {
Text(date, format: .dateTime.year().month().day())
.bold()
}
AxisTick(length: .label)
}
}
}
.frame(height: 90)
.padding(.bottom, 40) // for overlay picker
.overlay {
Picker("", selection: $visibleDomain.animation()) {
ForEach(VisibleDomain.allCases) { variant in
Text(variant.label)
.tag(variant)
}
}
.pickerStyle(.segmented)
.frame(width: 240)
.padding(.trailing)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
} //: overlay
} //: body
} //: struct
// MARK: - Preview
#Preview {
ScrollableChartBug()
}
// MARK: - Data
enum SampleDataType: String, CaseIterable {
case city, wood, field
var color: Color {
switch self {
case .city:
.gray
case .wood:
.green
case .field:
.brown
}
}
var label: String {
switch self {
case .city:
"City"
case .wood:
"Wood"
case .field:
"Field"
}
}
}
enum VisibleDomain: Identifiable, CaseIterable {
case day
case week
case month
case year
var id: Int {
self.seconds
}
var seconds: Int {
switch self {
case .day:
3600 * 24 * 2
case .week:
3600 * 24 * 10
case .month:
3600 * 24 * 40
case .year:
3600 * 24 * 400
}
}
var label: String {
switch self {
case .day:
"Days"
case .week:
"Weeks"
case .month:
"Months"
case .year:
"Years"
}
}
}
struct SampleData: Identifiable {
let startDate: Date
let endDate: Date
let name: String
let type: SampleDataType
var id: String { name }
static let samples: [SampleData] = [
.init(startDate: Date.from(year: 2022, month: 3, day: 1),
endDate: Date.from(year: 2022, month: 3, day: 10),
name: "New York",
type: .city),
.init(startDate: Date.from(year: 2022, month: 3, day: 20, hour: 6),
endDate: Date.from(year: 2022, month: 5, day: 1),
name: "London",
type: .city),
.init(startDate: Date.from(year: 2022, month: 5, day: 4),
endDate: Date.from(year: 2022, month: 7, day: 5),
name: "Backcountry ABC",
type: .field),
.init(startDate: Date.from(year: 2022, month: 7, day: 5),
endDate: Date.from(year: 2022, month: 10, day: 10),
name: "Field DEF",
type: .field),
.init(startDate: Date.from(year: 2022, month: 10, day: 10),
endDate: Date.from(year: 2023, month: 2, day: 10),
name: "Wood 123",
type: .wood),
.init(startDate: Date.from(year: 2023, month: 2, day: 10),
endDate: Date.from(year: 2023, month: 3, day: 20),
name: "Paris",
type: .city),
.init(startDate: Date.from(year: 2023, month: 3, day: 21),
endDate: Date.from(year: 2023, month: 10, day: 5),
name: "Field GHI",
type: .field),
.init(startDate: Date.from(year: 2023, month: 10, day: 5),
endDate: Date.from(year: 2024, month: 3, day: 5),
name: "Wood 456",
type: .wood),
.init(startDate: Date.from(year: 2024, month: 3, day: 6),
endDate: Date(),
name: "Field JKL",
type: .field)
]
}
extension Date {
/**
Constructs a Date from a given year (Int). Use like `Date.from(year: 2020)`.
*/
static func from(year: Int? = nil, month: Int? = nil, day: Int? = nil, hour: Int? = nil, minute: Int? = nil) -> Date {
let components = DateComponents(year: year, month: month, day: day, hour: hour, minute: minute)
guard let date = Calendar.current.date(from: components) else {
print(#function, "Failed to construct date. Returning current date.")
return Date()
}
return date
}
}
Currently I have a cloud syncing status icon that utilizes the new "rotate" symbol effect introduced with iOS 18. After the synchronization is complete, I want to replace the icon with another symbol using the "replace" contentTransition. These are the codes I used to achieve this:
Image(systemName: coreDataStack.cloudKitUIStatus.symbolName)
.foregroundColor(coreDataStack.cloudKitUIStatus.symbolColor)
.symbolEffect(.rotate, isActive: coreDataStack.cloudKitUIStatus == .inProgress)
.contentTransition(.symbolEffect(.replace))
However, the rotation effect continues after the replace transition. This means the new icon (checkmark.icloud.fill) continues the spinning animation from the previous symbol (arrow.triangle.2.circlepath.icloud) until it completes the full circle.
How can I stop the rotation immediately before the contentTransition? Thanks!