Juanpe / SkeletonView

☠️ An elegant way to show users that something is happening and also prepare them to which contents they are awaiting
MIT License
12.62k stars 1.12k forks source link

Wrong animation at start of animation #549

Open creactit opened 1 year ago

creactit commented 1 year ago

Description

Hi, I have added skeleton on collectionview cell.

At start of animation I have two problems:

  1. On my cell the labels and button are centered but at start of skeleton I see the entering animation from left
  2. While step 1 is completed the skeleton animation it's wrong (forever top/down animation).

What type of issue is this? (place an x in one of the [ ])

Requirements (place an x in each of the [ ])

Bug Report

Filling out the following details about bugs will help us solve your issue sooner.

SkeletonView Environment:

SkeletonView version: 1.30.4 Xcode version: 14.2 Swift version: 5.7.2

Steps to reproduce:

Please replace this with the steps to reproduce the behavior.

  1. Create collectionview cell with centered label
  2. Apply skeleton at cell

Expected result:

Don't see animation from left to right Don't see incorrect animation

1 2 3
Serg-Pogrebnyak commented 1 year ago

same on my end, here a video with a bug cell created in a xib

https://github.com/Juanpe/SkeletonView/assets/33331545/a64edb00-f1c3-4a14-8bc4-6576fe148d5f

creactit commented 1 year ago

Yes the problem it's the same of top left cell

Serg-Pogrebnyak commented 1 year ago

and also in the video, you can see when the animation starts from the default gradient (from top to bottom) and then switches on the animation which was sent as a parameter (left to right)

Serg-Pogrebnyak commented 1 year ago

So, looks like I found the problem and fixed it on my end, here are my solution and description of why it's happening: All skeletons it's a layers, and they build on the fly recursively, as you know at some time application UI is not ready and as a result, skeletons layers has incorrect frame and bounds. In the library, they make swizzling of the UIView.layoutSubviews method, so when the system calls layoutSubviews it changes in the runtime on their, and at this time skeletons update their frame and bounds. But in viewWillAppear, we already have the final UI, but layoutSubviews will be called slightly late, that's why you will see the old position and animated change of the skeleton view.

To avoid this I made two things:

  1. In the func startTransition(transitionBlock: @escaping () -> Void) function, I added layoutIfNeeded() to build the finish UI and avoid animation change; Снимок экрана 2023-09-19 в 19 14 09
  2. In func recursiveShowSkeleton (skeletonConfig config: SkeletonConfig, root: UIView? = nil) and func recursiveUpdateSkeleton (skeletonConfig config: SkeletonConfig, root: UIView? = nil) functions I added the layoutSkeletonIfNeeded() function, this force call will update the frame and bounds set all skeletons in the correct position at THIS moment, and does not wait when the system calls layoutSubviews(), as a result when the controller will be presented, you will see correct position of your skeletons. Снимок экрана 2023-09-19 в 19 14 40