Post not yet marked as solved
how to add a core animation layer as it own composition track.
So, straight to the problem:
I've created a custom UIViewControllerTransitioningDelegate that I use to animate a view from one view controller, to full-screen in another view controller. Im doing this by creating UIViewControllerAnimatedTransitioning-objects that animate the presented view's frame. And it works great! Except when I try to adjust the additionalSafeAreaInsets of the view controller owning the view during dismissal...
It looks like this property is not accounted for when I'm trying to animate the dismissal of the view controller and its view. It works fine during presentation.
So, what I want is: use additionalSafeAreaInsets to diminish the effect of the safe area during animation, by setting additionalSafeAreaInsets to the "inverted" values of the safe area. So that the effective safe area starts at 0 and "animates" to the expected value during presentation, and starts at expected value and "animates" to 0 during dismissal.
(I'm quoting "animates", since its actually the view's frame that is animated. But UIKit/Auto Layout use these properties when calculating the frames)
Any thoughts on how to battle this issue is great welcome!
The code for the custom UIViewControllerTransitioningDelegate is provided as an attachment.
FullScreenTransitionManager.swift
To me it looks like the safe area of a view is not updated after the owning view controller's .viewWillDisappear() method is called.
Is this intended or a bug in the framework?
The issue is easily visualised by creating a custom UIViewControllerTransitioningDelegate that animates a smaller view in one view controller, to full screen size in another (constrained to safe areas). Then the safe areas will expand as the present animation goes on (as expected), but will not shrink as the dismiss animation goes on (not expected!). The expected behaviour would be that the safe area expands during the present animation, and shrinks during the dismiss animation.
The gif below shows the unexpected behaviour. The grey area of the presented view controller is the safe area.
I've attached the code I used to visualise this problem. ViewController.swift presents MyViewController.swift using FullScreenTransitionManager.swift
FullScreenTransitionManager.swift
MyViewController.swift
ViewController.swift
Post not yet marked as solved
I'm trying to synchronize contents of a Metal layer with UIView animations (CAAnimation-based).
I've tried using custom CALayer animations by overriding the needsDisplay and action(forKey:) methods of CAMetalLayer, setting presentsWithTransaction to true, then performing a change inside a CATransaction. This works, but when animating a UIView and the contents of a CAMetalLayer side by side, the Metal contents slightly lags behind the UIView.
Is there any way to perfectly synchronize the app-side animated drawing with render server-side animations?
Post not yet marked as solved
I have a text cursor that's modeled as a CALayer. It "blinks" with an opacity animation.
I'm in process of moving most of my animations away from CAAnimation, and instead I am driving changes myself with a CVDisplayLink. Most of my animations are temporary, things like scroll the window, etc. And when I'm done I pause the CVDisplayLink.
My question: Is it reasonable to also drive the text cursor "blink" animation by my CVDisplayLink? That would mean my CVDisplayLink never gets to pause ... but it also means maybe the render server process does get to pause?
Post not yet marked as solved
I am moving layers around using UIView.animate(withDuration:,animations:,completion:). The animation works as it is supposed to, but changing the duration parameter doesn't change the duration. It always goes at the same speed. What might I be doing wrong? Is there some global thing I have to turn on for this to work?
Post not yet marked as solved
Following the document and demo
mixing_metal_and_opengl_rendering_in_a_view
section "Select a Compatible Pixel Format" only show MTLPixelFormatBGRA8Unorm as followed.
if I want to use MTLPixelFormatRGBA8Unorm, how can I find the cvpixelformat and gl format which match MTLPixelFormatRGBA8Unorm??
Thanks in advance.
// Table of equivalent formats across CoreVideo, Metal, and OpenGL
static const AAPLTextureFormatInfo AAPLInteropFormatTable[] =
{
// Core Video Pixel Format, Metal Pixel Format, GL internalformat, GL format, GL type
{ kCVPixelFormatType_32BGRA, MTLPixelFormatBGRA8Unorm, GL_RGBA, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV },
#if TARGET_IOS
{ kCVPixelFormatType_32BGRA, MTLPixelFormatBGRA8Unorm_sRGB, GL_RGBA, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV },
#else
{ kCVPixelFormatType_ARGB2101010LEPacked, MTLPixelFormatBGR10A2Unorm, GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV },
{ kCVPixelFormatType_32BGRA, MTLPixelFormatBGRA8Unorm_sRGB, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
{ kCVPixelFormatType_64RGBAHalf, MTLPixelFormatRGBA16Float, GL_RGBA, GL_RGBA, GL_HALF_FLOAT },
#endif
};
Post not yet marked as solved
Hi,
I want to add some animations in my quiz module in an app. Animations like bow arrow, floating balloons, etc. In bow arrow the arrow will hit the target on tap. How can I achieve these animations in swift?
Thanks in advance.
After animating from a group conditional view, the edit button on my list doesn't work. It works fine if there's no animation, but I'm not sure why an animation would cause the edit button to not work?
struct Overview: View {
@State var test = true
var body: some View {
Group {
if test {
Button(action: {
test = false
}) {
Text("Button")
}
} else {
NavigationView {
SimpleList()
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
.animation(.easeOut, value: test)
}
}
struct SimpleList: View {
let test = ["1", "2", "3", "4"]
var body: some View {
List {
ForEach(test, id: \.self) { t in
Text(t)
}
.onDelete(perform: deleteRow)
}
}
func deleteRow(_ :IndexSet) {
}
}
Post not yet marked as solved
Hi!
I am currently finalizing a new app that uses Metal to render a 3D scene and a UIKit overlay to display controls for interacting with objects in the scene. The render loop is driven via a CADisplayLink with its preferredFramesPerSecond set to 60.
I have recently noticed an issue where the app reports a steady 60 fps frame rate in the Xcode debug navigator, but still felt sluggish on the device. This feeling was only present on devices with ProMotion and often started after interactions with the UIKit overlay. I started investigating by using Metal System Trace and quickly found an explanation for the sluggish feeling: occasionally, the app would switch from its nominal 16ms-16ms-16ms cadence to 12ms-20ms-12ms, thus still averaging 60 fps, but with inconsistent frame times.
Pictures of the timeline can be found here.
I have tried setting the CAMetalLayer's presentsWithTransaction to true, waiting for the command buffer to be scheduled and then presenting the drawable, but, unfortunately, the problem persists.
If anybody can think of a potential reason / solution for this, I would be very thankful.
Post not yet marked as solved
I would like to be able to move an object,a ball, along a curved line. I am currently using xcode 12.5.
Plot point from the curve will be determined from data in a database.
Sample code would be much appreciated.
Post not yet marked as solved
I found Apple doc i.e https://developer.apple.com/documentation/uniformtypeidentifiers/uttype/3551599-webp.
is there anyway to support older version?
I have started learning Metal and the source text I was reading mentioned that interactions with images rendered to the screen is handled by Core Animation layers (CAMetalLayer) in iOS, but had no mention for any other platform. I am guessing for the other "mobile" platforms the same thing applies as iOS, but what handles this interaction for macOS, or is it also the same?
Post not yet marked as solved
I have a view that I am trying to get to animate on state change either using a transition or animate and so far nothing I've done has worked.
I've tried using withAnimation and .transition in various manners and no luck. Below is a repro and you'll see that the transition is very jagged.
Looking for suggestions on the best approach.
struct StackView: View {
@State var showStack = true
let columns = [
GridItem(.flexible()),
GridItem(.flexible()),
]
var body: some View {
VStack {
if showStack {
ZStack {
ForEach(0 ..< 15) { item in
TileView()
.rotationEffect(.degrees(Double.random(in: 1..<45)))
.transition(.asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .bottom)))
}
}
} else {
LazyVGrid(columns: columns, spacing: 20) {
ForEach(0 ..< 15) { item in
TileView()
.transition(.asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .bottom)))
}
}
}
}
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.9) {
withAnimation(Animation.easeInOut(duration: 1).delay(0.5)) {
showStack = false
}
}
}
}
}
struct TileView: View {
var body: some View {
RoundedRectangle(cornerRadius: 13)
.frame(width: 175, height: 175, alignment: .center)
.foregroundColor(.red)
.shadow(radius: 13)
.overlay(
Text("1")
.font(.largeTitle)
)
.transition(.asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .bottom)))
}
}
Post not yet marked as solved
I have created the main view of my app and there is a button that will display a pop-up view doing some user input tasks. I would like the background dim view to fade in and fade out while the pop-up view is using scale animation in transition. The animation works pretty well while showing the view, but it does not work when it disappears.
Following is my code that is relative to this problem. There is a button in the main view that will toggle isAddViewShown to display the pop-up view, and there are two buttons that will close it. So I passed the action into the pop-up view as shown, but it did not work.
I'm pretty new to SwiftUI so I'm not sure whether that is what I'm supposed to do. Is there any way to let the animation work as designed?
public struct SMMainView: View {
@State private var isAddViewShown: Bool = false
public var body: some View {
ZStack {
/*
Some other views
*/
// This is actually a dim view using opacity animation in transition
if isAddViewShown {
Color.black.opacity(0.5)
}
// This is a customized pop-up view using scale animation in transition
if isAddViewShown {
SMAddView(onCreate: { name, description in
/*
do some extra operations with name and description
*/
withAnimation(.easeInOut(duration: 0.25)) {
isAddViewShown.toggle()
}
},
onClose: {
withAnimation(.easeInOut(duration: 0.25)) {
isAddViewShown.toggle()
}
})
.transition(.scale)
}
}
}
}
To avoid misunderstanding, the following is basically what I put for the pop-up view.
struct SMAddView: View {
@State private var name: String = "Title"
@State private var description: String = "Please Enter description."
private var createAction: (String, String) -> Void
private var closeAction: () -> Void
var body: some View {
VStack {
TextField("", text: $name)
TextEditor(text: $description)
Button(action: {
createAction(name, description)
name = "Title"
description = "Please enter description."
}) {
Text("Create")
}
Button(action: {
closeAction()
name = "Title"
description = "Please enter description."
}) {
Image(systemName: "xmark.circle")
}
}
}
init(onCreate create: @escaping (String, String) -> Void, onClose close: @escaping () -> Void) {
createAction = create
closeAction = close
}
}
Post not yet marked as solved
I'm tring to capture UIView or CALayer with CoreAnimation into UIImages on iOS.
this is how i capture it in UIView extension:
public func captureImage() -> UIImage?{
var image: UIImage?
UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale)
if let context = UIGraphicsGetCurrentContext() {
layer.presentation()?.render(in: context)
image = UIGraphicsGetImageFromCurrentImageContext()
context.restoreGState()
}
UIGraphicsEndImageContext()
return image
}
it does not work with CoreAnimation, the images it captures are the same, without any (animation) change.
the CALayer API Document shows:
/* Renders the receiver and its sublayers into 'ctx'. This method
* renders directly from the layer tree. Renders in the coordinate space
* of the layer.
*
* WARNING: currently this method does not implement the full
* CoreAnimation composition model, use with caution. */
/** Rendering properties and methods. **/
open func render(in ctx: CGContext)
is there some way to resolve it ?
Post not yet marked as solved
Hi there,
does Apple allow to embed Animojis in your app?
We are developing a learning app and want to use one specific animoji as a "brand ambassador" who is presenting the information. Was wondering whether there are any trademark issue with this or whether Apple is just fine with it?
Any experiences and thoughts are much appreciated! Stephan
Post not yet marked as solved
About a month ago I asked whether I could use HDR in SpriteKit. This wasn't a well-phrased question since HDR seems to mean different things in different questions, which probably led to my question going unanswered.
What I meant to ask was whether it's possible to use assets that have a color gamut that many modern devices are capable of displaying (XDR is somewhat standard among mid- to high-end devices). In other words: Is SpriteKit keeping up with the hardware?
If not, what framework options do I have that can quickly display large Rec. 2020 images? Do any of the Core frameworks offer this capability?
I'm trying to create a bottom sheet in swift ui that looks something like this
https://user-images.githubusercontent.com/33900517/172068237-4dd58374-b6e6-4340-a913-7085fb64b254.mp4
My issue is that I have an animated bottom sheet, but because it is ignoring the safe area, when I click into the textfield it does not expand with the keyboard.
How would I fix this so the view expands with the keyboard but the white at the bottom still goes beyond the safe area?
I.e. the containing view should ignore the safe area, and the content within should adhere to the safe area.
Here is the bottom sheet code
var body: some View {
GeometryReader { geometry in
VStack() {
self.content
}
.padding(.vertical, 34)
.padding(.horizontal, 16)
// .frame(width: geometry.size.width, height: geometry.size.height * heightRatio, alignment: .top)
.frame(width: geometry.size.width, height: self.maxHeight, alignment: .top)
.background(Color(.white))
.cornerRadius(Constants.radius)
.frame(height: geometry.size.height, alignment: .bottom)
.offset(y: max(self.offset + self.translation, 0))
.animation(.interactiveSpring())
.gesture(
DragGesture().updating(self.$translation) { value, state, _ in
state = value.translation.height
}.onEnded { value in
let snapDistance = self.maxHeight * Constants.snapRatio
guard abs(value.translation.height) > snapDistance else {
return
}
self.isOpen = value.translation.height < 0
}
)
}
.edgesIgnoringSafeArea([.bottom, .horizontal])
.shadow(color: Color(hue: 1.0, saturation: 0.0, brightness: 0.0, opacity: 0.08), radius: 12, y: -8)
}
Bottom sheet is closed
Bottom sheet open
Bottom sheet open and textfield is selected, keyboard is active
Post not yet marked as solved
Hello,
I have an @EnvironmentObject variable that publishes 30 times per second but the view that depends on that data must be limited to 20 frames per second. The publishing rate cannot be controlled, so I must control the rate at which SwiftUI refreshes that view in order to achieve the desired effect.
I tried using TimelineView(.periodic(from: .now, by: 1/20)), but the restriction gets ignored due to the published data; I also considered Combine's timer, but it isn't based on real time. Are there any other methods I can use to force SwiftUI to refresh certain views at certain real time intervals, in essence controlling its FPS?