How to Create a Fading Transition Between Colors in SwiftUI by Scott Andrew | October, 2022

Enjoy this step-by-step guide to making this fun project

Unsplash. Photo by Per Zalfa Imani

I like the look of an app that uses a background of average color when transitioning images. This beautiful technique can be created by calculating the average color of a given image. This example was created using images from Unsplash to create the desired effect:

gallery application

The final version of the project can be found on GitHub.

  1. Create a new SwifUI project
  2. change name ContentView To GalleryView,
  3. change name ContentView_Previews To GalleryView_Previews,
  4. Add the swiftui-introspect package from https://github.com/siteline/SwiftUI-Introspect.git
  5. Add images to the project’s resources. The names of the images in the sample project areImage 1, Image 2, Image 3, And Image 4,

The swiftui-introspection library would be to use UIScrollView he is behind Scrollview This much isPagingEnabled flag can be set true,

The average color code is not the original. There is code from https://christianselig.com/2021/04/efficient-average-color/. This code is quick and efficient. The author has a great explanation on how to build this code.

code a. is in UIImage Category that allows it to be called directly on the image. For example:image.findAverageColor()

One ImageEntry.swift The file needs to be created. A smaller structure to keep in the file would be UIImage, a UUID, and the average color. A simple constructor taking the name of the image will do all the work.

One design decision that was made is to keep the data as UIKit objects. This keeps the code from having to bounce back and forth between SwiftUI and UIKit until needed.

  1. create an array of ImageEntry Items to display in the gallery.
  2. wrap ScrollView inside one GeometryReader. GeometryReader Will be used to set the size of the image. The width of the view will also be needed to calculate the background color later.
  3. do ScrollView Horizontal, so it scrolls from side to side.
  4. images a. layout in LazyHStack,
  5. create Image From UIImage in stream ImageEntry,
  6. do Image Indented 24 units with rounded corners, fitted to the screen.
  7. do ScrollView paged.
  8. Is GeometryView Ignore the protected area of ​​the screen, so the entire screen is used for the layout. This will be important if a color background is added.

Now a basic gallery is created with no background. The gallery can be scrolled through, and the images fit the screen, maintaining their aspect ratio.

Need to know the offset of the transition ScrollView, To start, a custom view preference must be created to store the offset of the view.

make ScrollViewOffsetPreferenceKey.swift file.

value When it comes it’s already set reduce, nextValuewhich is 0, needs to be added value, This will cause the key to send an update message.

to keep track of ScrollViewoffset is, need to add an empty view ScrollView, It needs to notify the user interface as soon as the offset changes.

  1. Add a coordinate space called scroll to keep track of the position relative to the scroll view. (line 20)
  2. wrap LazyHStack In ZStack So the views can be layered ScrollView, (line 2)
  3. below LazyHStackOne GeometryReader is added which has a clear color view. (lines 3-6)
  4. On each redraw, get the position of the clear view relative to the scroll (ScrollView) coordinate space and store it ScrollViewPreferenceKey on a clear view. (lines 5-6)
  5. when the value is set to ScrollViewPreferenceKeyThe onPreferenceChange is called a modifier. The value is the latest offset of the Clear Color view. (lines 24-26)

When the application is run, the scroll view’s offset may change in the debug console as the gallery is swiped up.

Inside the scroll view, a clear view was created 0,0, As the user swipes left, the frame will change and become negative. The frame for clear view is relative to the frame of the scroll view. Since the clear view is at the parent position of the scroll view, the offset will match the result UIScrollView.contentOffsetbut negative.

From a design standpoint, it makes sense to ask one color to interpolate between itself and another. For this reason, the code has been put in the extension UIColor,

  1. getComponents a. There is a helper function to get the color components from UIColor, The code supports a white value with either RGBA or alpha.
  2. interpolate The function returns the color between the source (self) and the destination colors.

The calculation takes the remaining value of the source color and adds it to the amount of color for the next page. For example, if the source color red component = 1.0destination colored red component = 0.5, and the scroll is 25% to the next page. The calculation is as follows:

newRed = (1.0–0.25) * 1.0 + 0.25 * 0.5newRed = 0.76 * 1.0 + 0.25 * 0.5newRed = 0.76 + 0.125newRed = 0.885

Background Calculator is where the magic happens. Two things are needed for this to work:

  1. viewing width. This is the screen in the application.
  2. The array of averaged colors is in the same order as the images.

The calculator will be an observable object that illuminates the calculated background color.

  1. color Publisher with the last calculated background color
  2. width Width of our view needed for page count calculation
  3. colors Average color list
  4. When colors is set, color publisher is set to first color colors array
  5. calculateBackground(position:) Takes the offset and calculates the current background color

mostly happens in magic calculateBackground(position:) Celebration.

  1. fractionalPage Will be the current page with a fractional offset between the pages. For example, 0.5 page represents halfway between 0 and 1.
  2. page makes an integer from fractionalPage double. This will act as an index of the color of the current page.
  3. fromColor is the background color of the current page.
  4. If fractionalPage Calculate the new background color that is between the first and last page. If not, return the color of the current page. For example, if fractionalPage 1.5 and there are two pages, there is no page at index 2. This means that no calculation is required; The background will be the background of the current page, which is 1.

To calculate color between pages:

  1. calculate next page
  2. Get the percentage between pages, which is the fractional part of fractionalPage,
  3. Call interpolate To get the color between the current and the next page.

To put this together, three things need to be connected GalleryView file.

  1. A stateful object is added to hold an instance of BackgroundCalculator, As the calculator’s published color updates, the view will be redrawn. (line 9)
  2. wrap ScrollView one in ZStack (line 13)
  3. a Rectangle is added behind ScrollView whose foreground color is BackgroundCalculatorCalculate color. (line 14)
  4. In form of ScrollViewOffsetPrefrenceKeyCalculate the new background color based on the value of ScrollViewcurrent status of. The new position needs to be multiplied by -1. (line 39)
  5. when GalleryView Appears, the width of GalleryView and need to pass the list of average colors BackgroundCalculator, (lines 43-44)

Running the project at this point will show a colored background behind the images that transitions smoothly between colors.

I love this transition. I think it gives personality what can be a boring transition between ideas. I hope you will also like it and find its use in your application. The full project can be found on GitHub.

If you liked this article, please leave a comment.

Leave a Comment