Skip to content

Commit d18895b

Browse files
authored
Merge pull request #63 from efremidze/glass
Added Glass Effect (v6.0.0)
2 parents 405baa5 + 99bea4b commit d18895b

File tree

11 files changed

+538
-124
lines changed

11 files changed

+538
-124
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Change log
22

3+
## [Version 6.0.0](https://github.com/efremidze/VisualEffectView/releases/tag/6.0.0)
4+
5+
- Added iOS 26+ glass effect support with automatic fallback
6+
- Added style-based API with `.systemBlur`, `.customBlur`, and `.glass` options
7+
38
## [Version 5.0.8](https://github.com/efremidze/VisualEffectView/releases/tag/5.0.8)
49

510
- Readded saturation

Example/ContentView.swift

Lines changed: 195 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,215 @@ import SwiftUI
1010
import VisualEffectView
1111

1212
struct ContentView: View {
13-
@State private var blurRadius: CGFloat = 0
13+
typealias VisualEffectStyle = VisualEffectView.VisualEffectStyle
14+
@State private var blurRadius: CGFloat = 18
15+
@State private var colorTintAlpha: CGFloat = 0.5
16+
@State private var saturation: CGFloat = 1.0
1417

1518
var body: some View {
16-
ZStack(alignment: .bottom) {
17-
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 16) {
18-
ForEach(Color.colors, id: \.self) { color in
19-
ZStack {
20-
Image(systemName: "swift")
21-
.resizable()
22-
.scaledToFit()
23-
.frame(width: 50, height: 100)
24-
.foregroundStyle(.black)
19+
ZStack {
20+
// Animated background
21+
AnimatedBackground()
22+
.ignoresSafeArea()
23+
24+
ScrollView {
25+
VStack(spacing: 32) {
26+
// Header
27+
VStack(spacing: 8) {
28+
Text("VisualEffectView")
29+
.font(.largeTitle)
30+
.fontWeight(.bold)
31+
Text("Dynamic blur effects with style-based API")
32+
.font(.subheadline)
33+
.foregroundStyle(.secondary)
34+
}
35+
.padding(.top, 20)
36+
37+
// Custom Blur Section
38+
VStack(alignment: .leading, spacing: 16) {
39+
Text("Custom Blur")
40+
.font(.title2)
41+
.fontWeight(.semibold)
42+
.padding(.horizontal, 4)
43+
44+
// Custom blur controls
45+
VStack(alignment: .leading, spacing: 16) {
46+
VStack(spacing: 12) {
47+
VStack(alignment: .leading, spacing: 4) {
48+
HStack {
49+
Text("Blur Radius")
50+
Spacer()
51+
Text("\(Int(blurRadius))")
52+
.foregroundStyle(.secondary)
53+
}
54+
Slider(value: $blurRadius, in: 0...30)
55+
}
56+
57+
VStack(alignment: .leading, spacing: 4) {
58+
HStack {
59+
Text("Tint Alpha")
60+
Spacer()
61+
Text(String(format: "%.2f", colorTintAlpha))
62+
.foregroundStyle(.secondary)
63+
}
64+
Slider(value: $colorTintAlpha, in: 0...1)
65+
}
66+
67+
VStack(alignment: .leading, spacing: 4) {
68+
HStack {
69+
Text("Saturation")
70+
Spacer()
71+
Text(String(format: "%.2f", saturation))
72+
.foregroundStyle(.secondary)
73+
}
74+
Slider(value: $saturation, in: 0...3)
75+
}
76+
}
77+
}
78+
.padding()
79+
.background {
80+
RoundedRectangle(cornerRadius: 16)
81+
.fill(.ultraThinMaterial)
82+
}
83+
84+
// Custom blur demo
85+
DemoCard(
86+
title: "Custom Blur",
87+
style: .customBlur,
88+
colorTint: .white,
89+
colorTintAlpha: colorTintAlpha,
90+
blurRadius: blurRadius,
91+
saturation: saturation
92+
)
93+
94+
// Color tint examples
95+
VStack(alignment: .leading, spacing: 12) {
96+
Text("Color Tint Examples")
97+
.font(.headline)
98+
.padding(.horizontal, 4)
99+
100+
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 12) {
101+
ForEach([
102+
("Red", Color.red),
103+
("Blue", Color.blue),
104+
("Green", Color.green),
105+
("Purple", Color.purple)
106+
], id: \.0) { name, color in
107+
DemoCard(
108+
title: name,
109+
style: .customBlur,
110+
colorTint: color,
111+
colorTintAlpha: colorTintAlpha,
112+
blurRadius: blurRadius,
113+
saturation: saturation,
114+
height: 120
115+
)
116+
}
117+
}
118+
}
119+
}
120+
121+
// Glass Effect Section
122+
VStack(alignment: .leading, spacing: 16) {
123+
Text("Glass Effect")
124+
.font(.title2)
125+
.fontWeight(.semibold)
126+
.padding(.horizontal, 4)
25127

26-
VisualEffect(
27-
colorTint: color,
28-
colorTintAlpha: 0.5,
29-
blurRadius: blurRadius
128+
DemoCard(
129+
title: "Glass Regular",
130+
style: .glass(.regular)
30131
)
31132
}
32133
}
134+
.padding()
135+
}
136+
}
137+
}
138+
}
139+
140+
// MARK: - Demo Card
141+
142+
struct DemoCard: View {
143+
let title: String
144+
let style: VisualEffectView.VisualEffectStyle
145+
var colorTint: Color?
146+
var colorTintAlpha: CGFloat = 0
147+
var blurRadius: CGFloat = 0
148+
var saturation: CGFloat = 1
149+
var height: CGFloat = 200
150+
151+
private var isCustomBlur: Bool {
152+
if case .customBlur = style { return true }
153+
return false
154+
}
155+
156+
var body: some View {
157+
ZStack {
158+
if isCustomBlur {
159+
VisualEffect(
160+
colorTint: colorTint,
161+
colorTintAlpha: colorTintAlpha,
162+
blurRadius: blurRadius,
163+
saturation: saturation
164+
)
165+
} else {
166+
VisualEffect(style: style)
167+
}
168+
}
169+
.frame(height: height)
170+
.clipShape(RoundedRectangle(cornerRadius: 20))
171+
.overlay {
172+
VStack(spacing: 8) {
173+
Text(title)
174+
.font(.headline)
175+
if isCustomBlur {
176+
Text("Blur: \(Int(blurRadius))")
177+
.font(.caption)
178+
.foregroundStyle(.secondary)
179+
}
33180
}
34-
.frame(maxWidth: .infinity, maxHeight: .infinity)
181+
.padding()
182+
}
183+
}
184+
}
185+
186+
// MARK: - Animated Background
187+
188+
struct AnimatedBackground: View {
189+
var body: some View {
190+
TimelineView(.animation) { timeline in
191+
let time = timeline.date.timeIntervalSinceReferenceDate
35192

36-
VStack {
37-
Slider(value: $blurRadius, in: 0...20)
193+
ZStack {
194+
LinearGradient(
195+
colors: [.blue, .purple, .pink, .orange],
196+
startPoint: .topLeading,
197+
endPoint: .bottomTrailing
198+
)
38199

39-
Text("Slide to blur")
40-
.font(.caption)
41-
.foregroundStyle(.secondary)
200+
// Animated shapes
201+
ForEach(0..<3, id: \.self) { index in
202+
Circle()
203+
.fill(
204+
LinearGradient(
205+
colors: [.white.opacity(0.2), .clear],
206+
startPoint: .top,
207+
endPoint: .bottom
208+
)
209+
)
210+
.frame(width: 200 + Double(index) * 100)
211+
.offset(
212+
x: cos(time / 5 + Double(index) * 2) * 100,
213+
y: sin(time / 5 + Double(index) * 2) * 100
214+
)
215+
}
42216
}
43-
.padding(.horizontal, 32)
44-
.padding(.bottom, 32)
45217
}
46218
}
47219
}
48220

49-
private extension Color {
50-
static let colors = [red, orange, yellow, green, teal, blue, purple, pink]
51-
}
221+
// MARK: - Preview
52222

53223
#Preview {
54224
ContentView()

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ let package = Package(
2323
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
2424
.target(name: "VisualEffectView")
2525
],
26-
swiftLanguageVersions: [.v5]
26+
swiftLanguageVersions: [.v5, .version("6")]
2727
)

README.md

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[![Swift](https://img.shields.io/badge/Swift-5.9+-orange.svg)](https://swift.org)
88
[![License](https://img.shields.io/github/license/efremidze/VisualEffectView.svg)](https://github.com/efremidze/VisualEffectView/blob/master/LICENSE)
99

10-
**VisualEffectView** is a blur effect library with tint color support. This library uses the [UIVisualEffectView](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/) to generate the blur.
10+
**VisualEffectView** is a dynamic blur effect library with tint color support and iOS 26+ glass effects. This library uses [UIVisualEffectView](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/) to generate the blur.
1111

1212
<img src="/Images/demo.gif" width="250" />
1313

@@ -23,25 +23,53 @@ $ pod try VisualEffectView
2323

2424
## Usage
2525

26-
Add an instance of VisualEffectView to your view.
26+
### UIKit
2727

2828
```swift
2929
import VisualEffectView
3030

3131
let visualEffectView = VisualEffectView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))
3232

33-
// Configure the view with tint color, blur radius, etc
34-
visualEffectView.colorTint = .redColor()
33+
// Customize the blur
34+
visualEffectView.colorTint = .red
3535
visualEffectView.colorTintAlpha = 0.2
3636
visualEffectView.blurRadius = 10
3737
visualEffectView.scale = 1
3838

3939
addSubview(visualEffectView)
4040
```
4141

42-
Depending on the desired effect, the effect may affect content layered behind the view or content added to the visual effect view’s contentView. After you add the visual effect view to the view hierarchy, add any subviews to the contentView property of the visual effect view. Do not add subviews directly to the visual effect view itself. Refer to the [UIVisualEffectView](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/) for more info.
42+
You can also use different styles:
4343

44-
For more examples, take a look at the example project.
44+
```swift
45+
// System blur
46+
visualEffectView.style = .systemBlur(.dark)
47+
48+
// Glass effect (iOS 26+)
49+
visualEffectView.style = .glass(.regular)
50+
51+
// Custom blur (default)
52+
visualEffectView.style = .customBlur
53+
```
54+
55+
### SwiftUI
56+
57+
```swift
58+
import VisualEffectView
59+
60+
struct ContentView: View {
61+
var body: some View {
62+
VisualEffect(colorTint: .white, colorTintAlpha: 0.5, blurRadius: 18, scale: 1)
63+
}
64+
}
65+
```
66+
67+
Or use the style-based API:
68+
69+
```swift
70+
VisualEffect(style: .glass(.regular))
71+
VisualEffect(style: .systemBlur(.dark))
72+
```
4573

4674
### Customization
4775

@@ -53,28 +81,23 @@ var scale: CGFloat // scale factor. default is 1
5381
var saturation: CGFloat // saturation factor. default is 1
5482
```
5583

56-
If you want `colorTintAlpha` to be different from `0`, make sure you always set it right after setting the `colorTint` or it may not be applied as expected.
57-
You also have to make sure you don't set `colorTintAlpha` if `colorTint` is `nil`.
84+
**Note:** Custom blur properties only work when `style` is `.customBlur`.
5885

59-
### Storyboard Support
60-
61-
Works great with storyboards and xibs.
86+
If you want `colorTintAlpha` to be different from `0`, make sure you always set it right after setting the `colorTint` or it may not be applied as expected. Don't set `colorTintAlpha` if `colorTint` is `nil`.
6287

63-
### SwiftUI Support
88+
### Content View
6489

65-
VisualEffectView supports SwiftUI.
90+
Add subviews to the `contentView` property, not directly to the visual effect view:
6691

6792
```swift
68-
import VisualEffectView
69-
70-
struct ContentView: View {
71-
var body: some View {
72-
VisualEffect(colorTint: .white, colorTintAlpha: 0.5, blurRadius: 10, scale: 1)
73-
}
74-
}
93+
visualEffectView.contentView.addSubview(label)
7594
```
7695

77-
Make sure that `colorTintAlpha` is not set when `colorTint` is `nil`.
96+
Refer to the [UIVisualEffectView](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/) documentation for more info.
97+
98+
### Storyboard Support
99+
100+
Works great with storyboards and xibs.
78101

79102
## Installation
80103

@@ -91,8 +114,16 @@ To install with [Carthage](https://github.com/Carthage/Carthage), simply add thi
91114
github "efremidze/VisualEffectView"
92115
```
93116

117+
### Swift Package Manager
118+
Add VisualEffectView as a dependency in your `Package.swift` file:
119+
```swift
120+
dependencies: [
121+
.package(url: "https://github.com/efremidze/VisualEffectView.git", from: "6.0.0")
122+
]
123+
```
124+
94125
### Manually
95-
1. Download and drop ```VisualEffectView.swift``` in your project.
126+
1. Download and drop the source files in your project.
96127
2. Congratulations!
97128

98129
## Communication
@@ -105,6 +136,8 @@ github "efremidze/VisualEffectView"
105136

106137
VisualEffectView utilizes a private UIKit API to do its magic. Use caution, submitting this code to the App Store adds the risk of being rejected!
107138

139+
The `.systemBlur()` and `.glass()` styles use only public APIs and are safe for App Store submission.
140+
108141
## Credits
109142

110143
https://github.com/collinhundley/APCustomBlurView

Sources/VisualEffectView/UIViewEffectView+Helpers.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// UIViewEffectViewiOS14.swift
2+
// UIVisualEffectView+Helpers.swift
33
// VisualEffectView
44
//
55
// Created by Lasha Efremidze on 9/14/20.

0 commit comments

Comments
 (0)