I'm currently building an App using a TabView as the main navigation method. In my app I would like to build a page similar to the Top Charts in the native App Store App with two lists side by side:
So far I came up with this code (simplified demo):
import SwiftUI
struct Demo: View {
var body: some View {
TabView {
Tab("Main Tab", systemImage: "tray.and.arrow.down.fill") {
NavigationStack {
HStack {
List {
Text("Left List")
}
List {
Text("Right List")
}
}
.navigationTitle("Demo")
.navigationBarTitleDisplayMode(.inline)
}
}
}
}
}
#Preview {
Demo()
}
However, I’m encountering a couple of issues:
• Scrolling to the top of the left list doesn’t trigger the toolbar background effect, and the content overlaps with the tabs in a strange way. Scrolling to the top of the right list works as expected.
• The navigation title is always hidden.
I haven’t been able to find a solution to these problems. What would be the correct approach? Thank you!
Visual Design
RSS for tagDiscuss 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
I'm trying to achieve a specific UI design in SwiftUI where the bottom section of my List has a different background color than the top section. For example in the Medications portion of the Health app, the "Your Medications" Section has a different background than the top "Log" Section. How do I achieve this?:
Here some example code. I wonder if I am supposed to use two Lists instead. If I use two Lists though and nest it in a ScrollView, the height of the lists needs to be specified. I am working with dynamic content, though so I don't think that is ideal.
class ProtocolMedication {} // Example model
struct HomeView: View {
@Query private var protocolMedications: [ProtocolMedication]
var body: some View {
NavigationStack {
List {
// Upper sections with default background
Section {
Text("Content 1")
} header: {
Text("Log")
}
// Bottom section that needs different background
Section {
ForEach(protocolMedications) { medication in
Text(medication.name)
}
} header: {
Text("Your Medications")
}
}
.listStyle(.insetGrouped)
}
}
}
This question came up, a customer wants to add payment, with gesture, to their app. This gesture is a swipe, from bottom to top (like when minimizing applications). The question immediately arose, will the application pass the review with such UI/UX ? Will there be any problems ? I'm not talking about problems when the user can minimize the application when paying, or pay (accidentally) when minimizing. I want to know if there will be any problems from Apple's rules when releasing the app ? I haven't found the exact information yet
Topic:
App Store Distribution & Marketing
SubTopic:
App Review
Tags:
Design
App Review
Visual Design
Interaction Design
Hello everyone,
in my website I need to give users the ability to choose a color via input type=“color”.
I don't understand why it works fine on desktop (even on Safari for Mac) but doesn't open the color picker on iPhone.
How can I solve this?
Thank you,
Andrea
I found that there is such a click-to-expand horizontally and smoothly effect in the system application called "message", which is good. I wonder if I can add a similar effect to my own app. If possible, are there any implementation ideas or examples that I can refer to? Thanks!
Does anyone have any idea why withAnimation is buggy when you apply a clip shape to an image? I've attached a screenshot of what happens below. Sometimes when hovering, it looks like the item gets drawn at the wrong location for a frame or two and then is placed back into position and the animation starts. It doesn't happen when the hover state ends, only the very initial hover event. This also doesn't happen without the .clipShape. I've also tried using .mask, but the same issue occurs. Has anyone ran into this?
Hi Friends!
I’m facing an issue with SceneKit.
I’m developing a 3D mobile game. I have a character 3D model and several skeletal animations CAAnimation. I import both the model and the animations from Maya in *.dae format. The character’s animations play continuously one after the other, with each new animation being triggered randomly. The transition between animations makes smoothly by setting the fadeInDuration and fadeOutDuration properties. Here’s an example of the code:
import UIKit import QuartzCore import SceneKit
class TestAnimationController: UIViewController {
var bodyNode: SCNNode?
override func viewDidLoad() {
super.viewDidLoad()
let scnView = SCNView(frame: self.view.bounds)
scnView.backgroundColor = .black // Set your desired background color
scnView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
let scene = SCNScene(named: "art.scnassets/scene/Base_room/ROOM5.scn")!
bodyNode = collada2SCNNode(filepath: "art.scnassets/female/girl_body_races.dae")!
bodyNode?.renderingOrder = 10
scene.rootNode.addChildNode(bodyNode!)
playIdleAnimation()
scnView.scene = scene // Assign the scene to the SCNView
self.view.addSubview(scnView) // Add the SCNView to your main view)
}
func collada2SCNNode(filepath:String) -> SCNNode? { if let scene = SCNScene(named: filepath) { let node = scene.rootNode.childNodes[0] return node } else { return nil } }
func playIdleAnimation() {
let array = [
"art.scnassets/female/animations/idle/girl_idle_4.dae",
"art.scnassets/female/animations/idle/girl_idle1.dae",
"art.scnassets/female/animations/idle/girl_idle2.dae",
"art.scnassets/female/animations/idle/Girl_idle3.dae",
]
let animation = CAAnimation.animationWithSceneNamed(array.randomElement() ?? "")!
self.setAnimationAdd(
fadeInDuration: 1.0,
fadeOutDuration: 1.0,
keyTime: 0.99,
animation,
isLooped: false
) { [weak self] in
guard let self = self else { return }
try? self.playBoringAnimations()
}
}
func playBoringAnimations() {
let array = [
"art.scnassets/female/animations/boring/girl_boring1.dae",
"art.scnassets/female/animations/boring/girl_boring2.dae",
"art.scnassets/female/animations/boring/girl_boring3.dae",
"art.scnassets/female/animations/boring/girl_boring4.dae",
"art.scnassets/female/animations/boring/girl_boring5.dae",
"art.scnassets/female/animations/boring/girl_boring6.dae",
"art.scnassets/female/animations/boring/girl_boring8.dae"
]
let animation = CAAnimation.animationWithSceneNamed(array.randomElement() ?? "")!
self.setAnimationAdd(
fadeInDuration: 1.0,
fadeOutDuration: 1.0,
keyTime: 0.99,
animation,
isLooped: false
) { [weak self] in
guard let self = self else { return }
try? self.playIdleAnimation()
}
}
func setAnimationAdd(fadeInDuration : CGFloat, fadeOutDuration : CGFloat, keyTime : CGFloat, _ animation: CAAnimation, isLooped: Bool, completion: (() -> Void)?) {
animation.fadeInDuration = fadeInDuration
animation.fadeOutDuration = fadeOutDuration
if !isLooped {
animation.repeatCount = 1
} else {
animation.repeatCount = Float.greatestFiniteMagnitude
}
animation.animationEvents = [
SCNAnimationEvent(keyTime: keyTime, block: { _, _, _ in completion?() })
]
bodyNode?.addAnimation(animation, forKey: "avatarAnimation")
}
}
Everything worked perfectly until I updated to iOS 18. On a physical device, the animations now transition abruptly without the smooth blending that was present in earlier iOS versions. The switch between them is very noticeable, as if the fadeInDuration and fadeOutDuration parameters are being ignored.
However, in the iOS 18 simulator, the animations still transition smoothly as before.
Here two example videos - IOS 17.5 and IOS 18 https://youtube.com/shorts/jzoMRF4skAQ - IOS 17,5 smooth https://youtube.com/shorts/VJXrZzO9wl0 - IOS 18 not smooth
I try this code in IOS 17.5, everything works fine
Does anyone have any ideas on how to fix this issue?
Topic:
Graphics & Games
SubTopic:
SceneKit
Tags:
Games
Core Animation
Graphical Debugger
Visual Design
Hi all,
I’m working on a custom action sheet in SwiftUI that slides in and out from the bottom using .transition(.move(edge: .bottom)). However, I’ve encountered an issue where the transition doesn’t respect my specified animation duration.
Here’s the basic structure of my action sheet:
ZStack {
Color.black
.opacity(0.5)
VStack {
SomeActionSheetContent()
}
.transition(.move(edge: .bottom))
.zIndex(1)
}
Each button inside the action sheet triggers a dismissal using this code:
Button {
withAnimation(onDismissAnimation) { isPresented = false }
}
onDismissAnimation can be any Animation, but for demonstration, I’m using .linear(duration: 5).
The problem is that when dismissing the action sheet, the animation is significantly faster than expected, around 5 times faster. For example, a 0.35-second animation finishes in just a fraction of that time.
To investigate further, I tested with .transition(.move(edge: .top)), and in that case, the transition respects the specified animation duration perfectly.
Does anyone know why the transition behaves differently when dismissing to the bottom versus the top?
I have been playing around with the page layout on my IPad Pro and discovered that is is impossible to group apps if you leave an empty space in the page. I found the option fun to finally place my apps where i want and not just lined up from top to bottom.
I discovered if you leave gaps in the page layout it is impossible to groupe apps. The moment you hover the app over the groupe, the groupe shifts back to fill the empty space. Once I filled up all the empty space then the groupe stops moving. It is pretty annoying.
The was excited to see the new feature to finally hate it completely. I do hope someone will fix this problem.
I have an iPhone/iPad application for which there is no watchOS target and as such no separate Watch app. I do not have separate watchOS app icons included as well in Assets. However, an Apple Watch is supposed to receive push notifications for the application.
Do we as app developers need to provide watchOS app icons, with different resolutions as suggested by Apple in HIG, in app's Assets for the app logo to appear properly in the notification coming in watch, for both short look and long look? As of now, my app's icon appear pixelated in short look and I am not sure whether it is an app icon issue or because I did not include watchOS app icons in Assets.
I can't for the life of me get transitions and animations to work well with SwiftData and List on MacOS 15 and iOS 18.
I've included an example below, where I define several animations and a transition type, but they are all ignored.
How do I animate items being added to / removed from a List()?
I am attached to List() due to its support for selection, context menu, keyboard shortcuts, etc. If I would switch to ScrollView with VStack I would have to rebuild all of that.
Also, this is super basic and should just work, right?
Thanks for reading.
import SwiftUI
import SwiftData
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
/// Issues on iOS:
/// Items animate into and out of view, but I seem to have no control over the animation.
/// In the code here I've specified a 'bouncy' and a slow 'easeIn' animation: both are not triggered.
/// The code also specifies using a 'slide' transition, but it is ignored.
/// -> How do I control the transition and animation timing on iOS?
///
/// Issues on MacOS:
/// Items do not animate at all on MacOS! They instantly appear and are instantly removed.
/// -> How do I control the transition and animation timing on MacOS?
// animation added here -> has no effect?
@Query(animation: .bouncy) private var items: [Item]
var body: some View {
VStack {
Button("Add to list") {
// called without 'withAnimation' -> no animation
let newItem = Item(timestamp: Date())
modelContext.insert(newItem)
}
List() {
ForEach(items, id: \.self) { item in
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
.transition(.slide) // items do not slide in/out of view
.onTapGesture {
// called with 'withAnimation' -> no animation
withAnimation(.easeIn(duration: 2)) {
modelContext.delete(item)
}
}
}
.animation(.spring(duration: 3), value: items)
}
}
.padding()
}
}
#Preview {
ContentView()
.modelContainer(for: Item.self, inMemory: true)
}
Hi, I made a macOS app that automatically sets the correct input/output devices depending on the connected speakers/microphones. The App is supposed to live in the background and act automatically, only allowing the users to change through settings which is accessible through the toolbar or through clicking on the toolbar icon to cycle between modes.
However, my app was just rejected for not providing UI beyond this.
Guideline 4 - Design
"Menu items are not visible, except by right-clicking. Users should not have to right click to access menu items."
I don't think that this app needs a UI beyond that for something which it is supposed to do automatically.
I'm having a hard time to understand what's expected here, should I invent a UI to pass the review and give option to the user to disable that?
Topic:
App Store Distribution & Marketing
SubTopic:
App Review
Tags:
Design
App Review
Visual Design
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?