I have a UIImageView, where I don't want the image to 'touch' the edge of the view, rather have some 'padding' around it. However, I have tried the following, and for some reason it doesnt change:
#IBOutlet weak var pictureOutletOne: UIImageView!
//set the image
pictureOutletOne.image = UIImage(named: itemOne)
//set the padding
pictureOutletOne.layoutMargins = UIEdgeInsetsMake(10, 10, 10, 10);
I have also tried:
pictureOutletOne.translatesAutoresizingMaskIntoConstraints = false
pictureOutletOne.layoutMargins = UIEdgeInsets(top: 10, left: 100, bottom: 10, right: 0)
I have read alot about this, but these are the solutions I have found, but they aren't working. Using Swift 3.
Thanks so much.
Swift 4.2 & 5
let imageView = UIImageView()
imageView.image = UIImage(named:
"image")?.withAlignmentRectInsets(UIEdgeInsets(top: -5, left: -5, bottom: -5,
right: -5))
Insets should be given in negative value
You can insert the imageView into a view and set constraints to sides, guaranteed approach :)
Override the alignmentRectInsets property in a new class:
class PaddedImageView: UIImageView {
override var alignmentRectInsets: UIEdgeInsets {
return UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10)
}
}
Swift 5.4 & Xcode 13
Here is a little helper extension I build:
extension UIImage {
func addPadding(_ padding: CGFloat) -> UIImage {
let alignmentInset = UIEdgeInsets(top: -padding, left: -padding,
bottom: -padding, right: -padding)
return withAlignmentRectInsets(alignmentInset)
}
}
let padding: CGFloat = 10
myImageView.contentMode = .scaleAspectFill
myImageView.image = UIImage(named: "myImage.png").resizableImage(withCapInsets: UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding), resizingMode: .stretch)
Swift 5
Adds padding to right and left of an image place in an image view.
let image = UIImage(systemName: "circle.fill")
let insets = UIEdgeInsets(top: 0, left: -15, bottom: 0, right: -15)
let imageView = UIImageView(image: image.withAlignmentRectInsets(insets))
Note: UIStackView honors alignment insets as contributors to an image view's intrinsic content size.
Use case example:
In my application, I have a vertical stack comprised of a small center-aligned UILabel stacked above a UIImageView in a UITableViewCell. Label width varies from cell to cell, varying respective vertical stack widths and shifting images' respective horizontal alignments. I.e. the images don't line up in the table.... By padding images with horizontal alignment insets, it forces vertical stack to have a consistent width greater than max expected label width, keeping images center-aligned vertically in the table.
Related
I have a custom button which works as a secure text toggle button - the image size is fine on larger iPhones, but on smaller Iphone8, iPhone 7 etc. The image is too big, see below.
I have tried adding constraints and modifying the CGrect of the button but this strangely has no effect on the size of the image.
I have tried a smaller image size but the image is just too small. Do I need different images for different device sizes or is there a way around this in code ?
Thanks
let button = UIButton(type: .custom)
//let button = UIButton(frame: CGRect(x: 0, y: 0, width: 50, height: self.frame.height))
setPasswordToggleImage(button)
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -10, bottom: 0, right: 0)
// Debug
//button.backgroundColor = .blue
//button.frame = CGRect(x: CGFloat(self.frame.size.width - 25), y: CGFloat(5), width: CGFloat(25), height: CGFloat(25))
button.addTarget(self, action: #selector(self.togglePasswordView), for: .touchUpInside)
self.rightView = button
self.rightViewMode = .always
button.alpha = 0.4
Creating correct assets for x1 x2 and x3 fixed the issue.
I would like to get rid of the spacing between the top of the UIButton image and the top border of the UIButton as well as the bottom of the UIButton image and the bottom border of the UIButton (refer to attached image).
I tried to use the below code however with no avail:
newFileButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
newFileButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
newFileButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
Any suggestions are much appreciated.
Regards,
Shadi.
The insets are at zero by default. To get rid of space on the inside, add negative insets.
newFileButton.imageEdgeInsets = UIEdgeInsets(top: -4, left: 0, bottom: -4, right: 0)
Can I write like the code below on Storyboard?
let button = UIButton()
button.titleLabel.center = CGPoint(x:button.titleLabel.center.x, y:button.titleLabel.center.y + 30)
Look into UIEdgeInsets and the UIButton property titleEdgeInsets.
button.titleLabelInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 30)
Depending on your exact needs and code, this should do what you need. (FYI - there is a imageEdgeInsets also.)
So the problem which I have is, the collection view, depending on what simulator I am using it displays either 3(iPhone 5) columns in one setting or 4 columns(iPhone 6) in another. I want the collection view to always displays 4 columns no matter how big or small the screen is. Here is some code I am using so far:
override func viewDidLoad() {
super.viewDidLoad()
let screenWidth = UIScreen.mainScreen().bounds.size.width
let screenHeight = UIScreen.mainScreen().bounds.size.height
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 100, height: 80)
collview1 = UICollectionView(frame: CGRectMake(0, 0, screenWidth, screenHeight), collectionViewLayout: layout)
[collview1.reloadData];
}
You'll want to change your layout.itemSize to a calculated value.
Something like:
layout.itemSize = CGSize(width: (screenWidth - spacing) / numberOfColumns, height: desiredHeight)
Spacing would be the total inter item spacing in a row plus the left and right insets.
DesiredHeight should probably be a calculated value to maintain the aspect ratio of your cells between devices.
Hopefully that's helpful.
I'm trying to make a UIButton that has a UIImage on either side (left and right) of the button's title. Ideally, the images would be pinned to the left and right sides of the button, and the title would be centered, but I can live with the images being right next to the title label I suppose. I have been able to add one image, which appears right before the title, but how would I add a second?
I know this is an old question but since no code was provided and someone asked for it I figured I would share my solution for this.
What I did was create a new class which subclasses a UIButton. I made sure that you can see all the changes you do instantly in your interface builder as well. So you can just drag in a UIButton. Specify the class to your own class and it will allow you to set the images and see it being drawn instantly
Here is what I did to achieve this
import UIKit
#IBDesignable
class AddProfilePictureView: UIButton {
#IBInspectable var leftHandImage: UIImage? {
didSet {
leftHandImage = leftHandImage?.withRenderingMode(.alwaysOriginal)
setupImages()
}
}
#IBInspectable var rightHandImage: UIImage? {
didSet {
rightHandImage = rightHandImage?.withRenderingMode(.alwaysTemplate)
setupImages()
}
}
func setupImages() {
if let leftImage = leftHandImage {
self.setImage(leftImage, for: .normal)
self.imageView?.contentMode = .scaleAspectFill
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: self.frame.width - (self.imageView?.frame.width)!)
}
if let rightImage = rightHandImage {
let rightImageView = UIImageView(image: rightImage)
rightImageView.tintColor = COLOR_BLUE
let height = self.frame.height * 0.2
let width = height
let xPos = self.frame.width - width
let yPos = (self.frame.height - height) / 2
rightImageView.frame = CGRect(x: xPos, y: yPos, width: width, height: height)
self.addSubview(rightImageView)
}
}
}
I would break it into two buttons within a collection view- it's very flexible and can work great for something like this.
Add a UIImageView with an image to the button by addSubview and another to the button by setImage, it can be adjusted with titleEdgeInsets and imageEdgeInsets.
if you need a code sample – let me know.
Hope it helps!
Swift 5, XCode 11.6
Please use the below code in your extension or in a custom UIButton class. I have used the below code in my custom class. The function will set left or right image respectively and align the text.
/// Sets a left and right image for a button
/// - Parameters:
/// - right: right image
/// - left: left image
func setImages(right: UIImage? = nil, left: UIImage? = nil) {
if let leftImage = left, right == nil {
setImage(leftImage, for: .normal)
imageEdgeInsets = UIEdgeInsets(top: 5, left: (bounds.width - 35), bottom: 5, right: 5)
titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: (imageView?.frame.width)!)
contentHorizontalAlignment = .left
}
if let rightImage = right, left == nil {
setImage(rightImage, for: .normal)
imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: (bounds.width - 35))
titleEdgeInsets = UIEdgeInsets(top: 0, left: (imageView?.frame.width)!, bottom: 0, right: 10)
contentHorizontalAlignment = .right
}
if let rightImage = right, let leftImage = left {
setImage(rightImage, for: .normal)
imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: (bounds.width - 35))
titleEdgeInsets = UIEdgeInsets(top: 0, left: (imageView?.frame.width)!, bottom: 0, right: 10)
contentHorizontalAlignment = .left
let leftImageView = UIImageView(frame: CGRect(x: bounds.maxX - 30,
y: (titleLabel?.bounds.midY)! - 5,
width: 20,
height: frame.height - 10))
leftImageView.image?.withRenderingMode(.alwaysOriginal)
leftImageView.image = leftImage
leftImageView.contentMode = .scaleAspectFit
leftImageView.layer.masksToBounds = true
addSubview(leftImageView)
}
}
Usage:
vegaButton.setImage(right: myImage) // for right image
vegaButton.setImage(left: myImage) // for left image
vegaButton.setImage(right: myImage, left: myImage) // for both images.