Why does putting an SF symbol in a UIImage and then in a SwiftUI Image View result in a blurry image?
When you use Image(systemName:)
the system draws to the screen using vector graphics, resulting in sharp, un-blurry renderings.
However, UIImage
, including, it seems UIImage(systemName:)
is a bitmapped image, at a set resolution. If you scale it up (as you're doing in your second block of code), you'll get blurriness, because you're not getting the benefits of the vector graphics.
Using a pattern like the following would allow you to conditionally display a Image(uiImage:)
or Image(systemName:)
and still use the same set of modifiers for each:
struct ContentView: View {
@State var displayedImage : UIImage?
var imageToDisplay: Image {
if let displayedImage = displayedImage {
return Image(uiImage: displayedImage)
} else {
return Image(systemName: "camera.circle")
}
}
var body: some View {
imageToDisplay
.resizable()
.scaledToFill()
.aspectRatio(contentMode: .fit)
.frame(width: 400, height: 400)
}
}
Change a SF Symbol size inside a UIButton
You can do it using SymbolConfiguration
like in the sample code below:
let largeConfig = UIImage.SymbolConfiguration(pointSize: 140, weight: .bold, scale: .large)
let largeBoldDoc = UIImage(systemName: "doc.circle.fill", withConfiguration: largeConfig)
button.setImage(largeBoldDoc, for: .normal)
How do I set the size of a SF Symbol in SwiftUI?
SF Symbols are similar to fonts, thus:
.font(.system(size: 60))
How to change the size of an SF icon in a UIButton
You can use the Default Symbol Configuration
settings on the UIButton in the Attributes Inspector
to accomplish the same thing. All Credit to Andrew Kirna below. Thanks dude!
Success!!! I finally figured out how to do this, thanks to a great article on SF Symbols. It was certainly buried in there.
It would be really nice to resize your button images in storyboard wouldn't it? I thought so at least.
Add IconButton.swift to your project in Xcode.
import UIKit
@IBDesignable
class IconButton: UIButton {
@IBInspectable var pointSize:CGFloat = 30.0
override func layoutSubviews() {
super.layoutSubviews()
if #available(iOS 13.0, *) {
let config = UIImage.SymbolConfiguration(pointSize: pointSize)
setPreferredSymbolConfiguration(config, forImageIn: .normal)
} else {
// Fallback on earlier versions
}
}
}Create a button in storyboard with an SF icon as the image.
Go to the identity inspector and make the class of your button IconButton
Go to the attribute inspector and enter in your point size. Note that this the
height of the icon
x
3/4. I wanted a 40 x 40 icon, so my point size was 30.See your icon update in storyboard and laugh happily that you didn't spend 3 hours figuring this out :D
Some credit to the great article: https://www.avanderlee.com/swift/sf-symbols-guide/
How do I set a weight to SF Symbols for iOS 13?
When using the font
modifier, set a weight to the font you're passing.
For example, if you want to use one of the default text styles (which I recommend, since they adapt to the user's Dynamic Type setting), you can do it like this:
Image(systemName: "arrow.right")
.font(Font.title.weight(.ultraLight))
If you want to specify a font size, you can do it like this:
Image(systemName: "arrow.right")
.font(Font.system(size: 60, weight: .ultraLight))
HStack with SF Symbols Image not aligned centered
This is what it's going on.
The Image
views are not resizing.
It looks like they're not aware of their intrinsic content size, or maybe it reports the wrong value.
To fix it:
struct ContentView : View {
var body: some View {
HStack(alignment: .center, spacing: 10.0) {
Image(systemName: "cloud.sun")
.resizable()
.aspectRatio(contentMode: .fit)
.background(Color.red)
Image(systemName: "cloud")
.resizable()
.aspectRatio(contentMode: .fit)
.background(Color.yellow)
Image(systemName: "cloud.bolt")
.resizable()
.aspectRatio(contentMode: .fit)
.background(Color.pink)
Text("Text").background(Color.green)
}
.frame(width: 250, height: 50)
.background(Color.gray)
.font(.title)
}
}
...make the Images
resizable, and also make sure the aspect ratio is set to .fit
, or they will stretch.
Set also frame on the HStack
or it will expand to fill the whole screen.
@MartinR suggested an even better solution - creating the images via UIImage
- see his comment below.
struct ContentView : View {
var body: some View {
HStack {
Image(uiImage: UIImage(systemName: "cloud.sun")!)
.background(Color.red)
Image(uiImage: UIImage(systemName: "cloud")!)
.background(Color.yellow)
Image(uiImage: UIImage(systemName: "cloud.bolt")!)
.background(Color.pink)
Text("Text").background(Color.green)
}
.background(Color.gray)
.font(.title)
}
}
Output:
How to change SF Symbol icon color in UIKit?
Use:
let icon = UIImageView(image: iconImage.withRenderingMode(.alwaysTemplate))
icon.tintColor = .red
Related Topics
How to Call a Method on a Uiview from Outside the Uiviewrepresentable in Swiftui
New' Is Unavailable: You Cannot Directly Instantiate an Stpissuingcardpin
Fail to Import Restkit with Cocoapods Dynamic Frameworks
How to Declare Exponent/Power Operator with New Precedencegroup in Swift 3
Swift Error Using Initialized Properties in Expressions Before Super.Init
Passing a Variable Through a Segue? Xcode 8 Swift 3
How to Save a Custom Class as an Attribute of a Coredata Entity in Swift 3
Swift Package Manager Unable to Compile Ncurses Installed Through Homebrew
Recursion Over a Swift Sliceable
How Does Appdelegate.Swift Replace Appdelegate.H and Appdelegate.M in Xcode 6.3
Rotate a Sprite to Sprite Position Not Exact in Spritekit with Swift
How to Parse Firestore Fieldvalue to Date in Swift
Implementing a Hash Combiner in Swift
Sharing File Data Between Applications in Swift/Ios
Why Specify [Unowned Self] in Blocks Where You Depend on Self Being There
Swiftui List View Not Updating After Core Data Entity Updated in Another View
What's Wrong with My #If Target_Os_Simulator Code for Realm Path Definition
Swift Generics Error: Cannot Convert Value of Type 'Type<T>' to Expected Argument Type 'Type<_>'