Visual Design

RSS for tag

Discuss animation, branding, color, layout, typography, and other elements of great looking apps.

Posts under Visual Design tag

33 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

How to interact during the Transition process?(wwdc24 UIKit consultation)
Recently I tried to apply a custom transition to a custom contextMenu. However, I want to make sure that during the transition process (which is not over yet), my contextMenu elements such as buttons can be tapped. But I tried a lot of things without success. I know you have a lot of experience, so I would like to ask you about how to implement the transition and be able to interact before it is over. I know that a UIView can be tapped during animation, but I haven't tried the button in a UIView. I've been trying to transition ViewControllers. For example, in a transition from fromViewController to toViewController, I wanted to be able to tap on a tableView in toViewController during the transition, but I was frustrated and found it very difficult to implement. I would like to ask you about the possibilities of interaction during the Viewcontrollers transition. (PS: In Github Issues, I uploaded a GIF example of the plus button on the left of the input box in iMessage. After tapping the plus button, you can tap the "Apple Cash" button before the transition is finished.) Your advice would be incredibly valuable to me. Thank you in advance for your time and assistance. [GithubLink]https://github.com/Juhnkerg/DemoForInteractionDuringTransition)
0
0
50
1d
Swift Charts animation woes using centered AxisValueLabel
Hi, I'm having some trouble when animating my chart with a custom AxisValueLabel. Specifically, as soon as I set its init parameter centered to true, the x axis' leftmost value of the previous dataset sticks around during the animation to the next dataset. Here's a GIF of a screen recording from a minimum reproducible example I built. Keep a close eye on the x axis of the third BarMark, and notice how the 0 from the first BarMark sticks around longer than necessary / intended. While it isn't visible in the GIF, the extra 0 eventually does disappear, but only after the transition if fully complete, making the animation feel distracting and amateur-ish, rather than smooth. This is my code for the x axis. If I turn centered to false, this problem immediately goes away. .chartXAxis { AxisMarks( preset: .aligned, values: .stride( by: .day, count: 1, calendar: .current ) ) { value in AxisValueLabel(centered: true) { Text("\(value.index)") } } } As you might be able to tell, my x axis is date based, and I'm working on showing one BarMark per day of the week. I have a ZIP of my minimum reproducible example that I can provide for anyone interested, although I don't know how to share it here. Any advice on what I can do to fix this?
2
0
69
1d
How to replicate UIImageView's `scaleAspectFill` for Images inside a custom Layout?
I've defined a custom layout container by having a struct conform to Layout and implementing the appropriate methods, and it works as expected. The problem comes when trying to display Image, as they are shown squished when just using the .resizable() view modifier, not filling the container when using .scaledToFit() or extending outside of the expected bounds when using .scaledToFill(). I understand that this is the intended behaviour of these modifiers, but I would like to replicate UIImageView's scaledAspectFill. I know that this can usually be achieved by doing: Image("adriana-wide") .resizable() .scaledToFill() .frame(width: 200, height: 200) .clipped() But hardcoding the frame like that defeats the purpose of using the Layout, plus I wouldn't have direct access to the correct sizes, either. The only way I've managed to make it work is by having a GeometryReader per image, so that the expected frame size is known and can bet set, but this is cumbersome and not really reusable. GalleryGridLayout() { GeometryReader { geometry in Image("adriana-wide") .resizable() .scaledToFill() .frame(width: geometry.size.width, height: geometry.size.height) .clipped() } [...] } Is there a more elegant, and presumably efficient as well as reusable, way of achieving the desired behaviour? Here's the code of the Layout.
1
0
84
2d
Best Way to Support Different Devices in SwiftUI?
Hi, I have pretty much finished my app's layout but realized I needed to scale it for different devices. I have read online that hardcoding values (esp in frames) is a big no-no, and GeometryReader should be heavily utilized. Also was recommended ViewThatFits. The problem is, I want the app to look the exact same across all devices. What is the best way to get started? Also, when testing, do I only have to test on an iPad and iPhone or are the dimensions significantly different amongst each class of devices?
0
0
230
Apr ’24
Animates wrongly at every switch of direction, animates right in same direction
I need to create an animation for previous and next questions. The current question should move out and next/prev question should come in. If you run the app and keep pressing next, it works well. Current question moves out towards left Next question appears from right to left. But if I switch the direction to previous, Current question moves out towards left( should move out towards right) next question comes in from left to right( which is correct). Similar discrepancy happens when I switch direction from prev to next. Why is this so? import SwiftUI struct Question { let id: Int let text: String } extension AnyTransition { static var slideRight: AnyTransition { let insertion = AnyTransition.move(edge: .trailing) let removal = AnyTransition.move(edge: .leading) return .asymmetric(insertion: insertion, removal: removal) } static var slideLeft: AnyTransition { let insertion = AnyTransition.move(edge: .leading) let removal = AnyTransition.move(edge: .trailing) return .asymmetric(insertion: insertion, removal: removal) } } struct QuizView: View { let questions = [ Question(id: 1, text: "11111111111"), Question(id: 2, text: "222222222222222222222222"), Question(id: 3, text: "3333333333333333333"), Question(id: 4, text: "444444444444444444444444"), Question(id: 5, text: "55555555555555555555"), Question(id: 6, text: "6666666666666666666666666") ] @State private var currentQuestionIndex = 0 @State private var navigationDirection: NavigationDirection = .forward var body: some View { VStack(spacing: 20) { Text(questions[currentQuestionIndex].text) .id(questions[currentQuestionIndex].id) // Important for transition .transition(navigationDirection == .forward ? .slideRight : .slideLeft) .frame(maxWidth: .infinity, maxHeight: .infinity) HStack { Button("Previous") { moveToPreviousQuestion() } .disabled(currentQuestionIndex == 0) Spacer() Button("Next") { moveToNextQuestion() } .disabled(currentQuestionIndex == questions.count - 1) } } .padding() .animation(.easeInOut(duration: 1.0), value: currentQuestionIndex) } private func moveToNextQuestion() { if currentQuestionIndex < questions.count - 1 { navigationDirection = .forward currentQuestionIndex += 1 } } private func moveToPreviousQuestion() { if currentQuestionIndex > 0 { navigationDirection = .backward currentQuestionIndex -= 1 } } } enum NavigationDirection { case forward, backward }
0
0
283
Apr ’24
Animates wrongly at every switch of direction, animates right in same direction
If you run the app and keep pressing next, it works well. current question moves out towards left, next question appears from right to left. But if I switch the direction to previous, current question moves out towards left( should move out towards right) next question comes in from left to right( which is correct). Similar discrepancy happens when I switch direction from prev to next. Why is this so? import SwiftUI struct Question { let id: Int let text: String } extension AnyTransition { static var slideRight: AnyTransition { let insertion = AnyTransition.move(edge: .trailing) let removal = AnyTransition.move(edge: .leading) return .asymmetric(insertion: insertion, removal: removal) } static var slideLeft: AnyTransition { let insertion = AnyTransition.move(edge: .leading) let removal = AnyTransition.move(edge: .trailing) return .asymmetric(insertion: insertion, removal: removal) } } struct QuizView: View { let questions = [ Question(id: 1, text: "11111111111"), Question(id: 2, text: "222222222222222222222222"), Question(id: 3, text: "3333333333333333333"), Question(id: 4, text: "444444444444444444444444"), Question(id: 5, text: "55555555555555555555"), Question(id: 6, text: "6666666666666666666666666") ] @State private var currentQuestionIndex = 0 @State private var navigationDirection: NavigationDirection = .forward var body: some View { VStack(spacing: 20) { Text(questions[currentQuestionIndex].text) .id(questions[currentQuestionIndex].id) // Important for transition .transition(navigationDirection == .forward ? .slideRight : .slideLeft) .frame(maxWidth: .infinity, maxHeight: .infinity) HStack { Button("Previous") { moveToPreviousQuestion() } .disabled(currentQuestionIndex == 0) Spacer() Button("Next") { moveToNextQuestion() } .disabled(currentQuestionIndex == questions.count - 1) } } .padding() .animation(.easeInOut(duration: 1.0), value: currentQuestionIndex) } private func moveToNextQuestion() { if currentQuestionIndex < questions.count - 1 { navigationDirection = .forward currentQuestionIndex += 1 } } private func moveToPreviousQuestion() { if currentQuestionIndex > 0 { navigationDirection = .backward currentQuestionIndex -= 1 } } } enum NavigationDirection { case forward, backward }
1
0
257
Apr ’24
WithAnimation not working in certain orders of operations
Hi, I am currently working through a SwiftUI tutorial where I am adding words entered into a text field to be displayed in a list beneath it. While doing so, I noticed that when trying to animate the insertion of the word into the text field, it wasn't working. private func addNewWord(){ let answer = newWord.lowercased().trimmingCharacters(in: .whitespacesAndNewlines) guard answer.count > 0, !usedWords.contains(answer) else {return} newWord = "" withAnimation { usedWords.insert(answer, at: 0) } } But, when I switched around those last 2 statements, the following code works properly: private func addNewWord(){ let answer = newWord.lowercased().trimmingCharacters(in: .whitespacesAndNewlines) guard answer.count > 0, !usedWords.contains(answer) else {return} withAnimation { usedWords.insert(answer, at: 0) } newWord = "" } Does anyone know why this is ? Is there something that has to do with the withAnimation call not being the final part in the function call ? Does it have to do with altering different State variables before or after the withAnimation call ? Is this expected behavior or some type of bug? Please let me know, here is the entire SwiftUI Struct in case you want to run this and see for yourselves. Thank you (Currently using xcode 15.0 on OS Sonoma 14.3.1) struct ContentView: View { @State private var newWord : String = "" @State private var usedWords : [String] = [String]() @State private var rootWord : String = "" var body: some View { NavigationStack { List { Section { TextField("Enter your word", text: $newWord).textInputAutocapitalization(.never) } Section{ ForEach(usedWords, id: \.self){ word in HStack { Image(systemName: "\(word.count).circle") Text(word) } } } } .navigationTitle(rootWord) } .padding() .onSubmit() { addNewWord() } } private func addNewWord(){ let answer = newWord.lowercased().trimmingCharacters(in: .whitespacesAndNewlines) guard answer.count > 0, !usedWords.contains(answer) else {return} // newWord = "" withAnimation { usedWords.insert(answer, at: 0) } newWord = "" } }
0
0
312
Mar ’24
SectorMark foreground style colors
Dear all, I am using SwiftUI 15.2 and I have created a donut chart using SectorMark. Now, I have three values to show in the chart. When I set up the foregroundstyle, it returns orange, blu and green colors, whereas I'd like to have different colors (e.g. red, yellow and green). Chart(data, id: \.risultato) { dataItem in SectorMark(angle: .value("Type", dataItem.partite), innerRadius: .ratio(0.7), angularInset: 1.5) .foregroundStyle(by: .value("Type", dataItem.risultato)) .annotation(position: .overlay){ Text("\(dataItem.partite)") .font(.caption) } } .frame(height: 150) I'm reporting the final result here below. Do you know how I can customize them? Thanks in advance for your support, Andrea
2
0
685
Feb ’24
Maximise Image above Form
Dear All, I want to maximise an Image above a Form. That should be easy enough but with the naive code, the Form is pushed out of the screen. I don't want to allow scrolling. This is my code: Image(systemName: "gear") .resizable() .scaledToFit() Form { Section("section 1") { Text("text 1") Text("text 2") Text("text 3") } Section("section 2") { Text("text 1") Text("text 2") Text("text 3") } } .scrollDisabled(true) Any hint on how to achieve that the Form is fully displayed and the Image dynamically maximised in the space that is left? Thanks in advance! Cheers F
2
0
507
Mar ’24
UIAlertAction has a poor color contrast ratio in destructive style
Hi Folks, I am reaching out for an iOS A11y color contrast issue, which I have also fired a bug report 12525894 but does not get any reply. The UIAlertAction in destructive style has a poor color contrast ratio of less than 4.5: 1 between text color and background color. This applies to any system/third party app which uses UIAlertViewController from UIKit and Alert from SwiftUI (Take the system Photos app as an example). Given that the "titleTextColor" property from UIAlertAction class is private, developers have no ways to modify the alert action to make it WCAG compatible. Here is an example of the Photo app alert. The text "Delete Photo" (#EB4E3D) should have a contrast ratio of at least 4.5 to 1 against its background(#EAEBE7) to comply to the Web Content Accessibility Guidelines (WCAG). Actual result: The text "Delete Photo" (#EB4E3D) has a contrast ratio of 3.08 to 1 against its background(#EAEBE7), which does not match 4.5:1 Web Content Accessibility Guidelines (WCAG).
0
0
430
Dec ’23
SwiftUI Sheet Animation Issue with Non-Default Background Colors
I'm working on a SwiftUI project where I use a .sheet modifier to present a bottom drawer with two detent sizes: .medium and .large. The drawer contains a button that toggles its size between these two states. This part works as expected. However, I'm facing an animation issue when I set a non-default background color to the sheet. Here's the simplified code for context: struct ContentView: View { @State private var selectedDetent: PresentationDetent = .medium var body: some View { VStack {} .sheet(isPresented: .constant(true)) { Button("Press Me") { selectedDetent = selectedDetent == .medium ? .large : .medium } .presentationBackground(.gray) .presentationDetents([.medium, .large], selection: $selectedDetent) } } } The issue arises when I try to set a background color using .presentationBackground(.gray) (or any color, even white). Instead of the expected behavior when pressing the button (where the upper part of the sheet closes, and the bottom part stays attached to the screen bottom), the sheet momentarily turns into a square in the middle of the screen before moving down to the .medium position. As soon as I remove the.presentationBackground(.gray) line, it works as expected: I tried several approaches, such as: Using a custom background view. Explicitly specifying animations. Adjusting view hierarchy and layering. Unfortunately, none of these solutions worked. The issue persists with any color. It seems like a bug or limitation in SwiftUI's handling of sheet animations with custom backgrounds. Has anyone else encountered this issue, or does anyone have a workaround or solution?
1
0
1.1k
Dec ’23
Color extension for positive/negative recognized color
Hey there! 👋🏻 I'm currently localizing my app and came across the interesting fact that in China (I'm not aware of other countries) the color red is associated with something positive, whereas in Germany (where I come from) the color green evokes a positive association. I then tried out whether this is taken into account in Apple's native apps. For example, in the Stocks app, a price gain with German localization is shown in green, whereas a price gain with Chinese localization is shown in red. Now I'm wondering whether there is a static property of the Color or UIColor class where I can retrieve a positive or negative color depending on the localization. Does anyone have experience with this? Thanks in advance! 😊
1
0
456
Nov ’23