'Avoid UIImage fill color from bleeding into UIImageView
I want to fill a UIImage containing a transparent section, without the fill color bleeding outside the image, into the UIImageView (I.E. into the UIImageView space that exists because the image has a "Scale Aspect Fit" setting)
How can that be done?
I tried drawing masks/contexts, settings masksToBounds/clipsToBounds/isOpaque to true/false, but it bleeds (or the whole thing turns into one solid colored box).
What I want (notice how the inside is white, but around the image it's transparent and therefore main color. This screenshot is from the iOS 15 Settings app):
What I have as of now (image fill color bleeds outside image. This is my app):
Notes:
- I am using SF Symbols for the images
- The images have a transparent section inside, which is what I want to fill with a color other than the main background color of the UIImageView (while I want the UIImageView background to be transparent)
SF Symbols used:
checkmark.square.fill
divide.square.fill"
arrow.up.and.down.square.fill
questionmark.square.fill
arrow.right.square.fill
arrow.left.square.fill
Solution 1:[1]
What I ended up doing is add a container view for each icon, put the icon in the container, give a cornerRadius to the container, constraints from icon to container, background color to icon, and white background color to the containers. Here is some info:
// MARK: Properties
let myDataSource = [Const.Title.check,
Const.Title.factorize,
Const.Title.list,
Const.Title.random,
Const.Title.next,
Const.Title.previous]
let myImageSource = ["checkmark",
"divide",
"arrow.up.and.down",
"wand.and.stars",
"arrow.right",
"arrow.left"]
let tintColorsArray: [UIColor] = [
.systemGreen,
.systemBlue,
.systemPurple,
.systemOrange,
.systemTeal,
.systemTeal
]
// MARK: Table
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: menuCell) as! MainMenuTableViewCell
cell.myLabel.text = myDataSource[(indexPath as NSIndexPath).row]
let aConfig = UIImage.SymbolConfiguration(weight: .bold)
let aImage = UIImage(systemName: myImageSource[(indexPath as NSIndexPath).row], withConfiguration: aConfig)
cell.newImageView.image = aImage
cell.newImageView.tintColor = .white
cell.imageViewContainer.backgroundColor = tintColorsArray[(indexPath as NSIndexPath).row]
cell.imageViewContainer.layer.cornerRadius = 6
cell.accessoryType = .disclosureIndicator
return cell
}
Solution 2:[2]
SF symbols recognize the transparent enclosed shape inside as a separate shape that can be filled with color.
What are looking for is rendering mode to fill the checkmark shape (for example). By default SF symbols use monochrome rendering mode, you can use Palette rendering or Multicolor rendering (this is supported in SF symbols 2.0 partially and in 3.0 fully)
4 rendering modes monochrome, hierarchical, palette and multicolor respectively.
Warning: some SF symbols are copyrighted and can not be used, also Apple warns against making SF symbols look like system icons.
You can check copyright, rendering modes & color symbols using SF symbols app, you can download it from here https://developer.apple.com/sf-symbols/
EDIT:
for your specific case, and because all symbols you want to use have a rounded corner rectangle you can add a white rounded corner rectangle image (that is slightly smaller than original symbol) behind your UIImage.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |