Customizing the UIImage View - swift4

How to programmatically change the borderWidth of a Image view which is on a UIView and present inside a prototypeCell
I have tried changing the borderWidth in interface Builder, but it is not working.1
looking forward for a better solution.2

you can try something like this
#IBOutlet weak var imageView: UIImageView!
// makes it circle if Width == Height
imageView.layer.cornerRadius = imageView.frame.width / 2
//Bordering
imageView.layer.borderColor = UIColor.black.cgColor
imageView.layer.borderWidth = 1

Related

Center ImageView in ScrollView with paging enabled - Swift

I need to create a paging ScrollView which shows a sequence of images.
I created a ScrollView in the main view of the Storyboard and set this constraints (to center the ScrollView in the view):
Constraint
Then I activated paging and disabled the "Content layout guides" option.
Next, in the view class I set up the UIScrollViewDelegate delegate and I wrote the following code to show 3 images (they are 3 colored squares):
class ViewController: UIViewController, UIScrollViewDelegate {
// Outlet
#IBOutlet weak var scrollview: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
scrollview.delegate = self;
let infoArray = ["01", "02", "03"];
for i in 0..<infoArray.count {
let imageView = UIImageView();
imageView.contentMode = .scaleToFill;
imageView.image = UIImage(named: infoArray[i]);
let xPos = CGFloat(i) * scrollview.bounds.size.width;
imageView.frame = CGRect(x: xPos, y: 0, width: scrollview.bounds.size.width, height: scrollview.bounds.size.height);
imageView.layer.borderWidth = 1;
scrollview.contentSize.width = scrollview.frame.size.width * CGFloat(i+1);
scrollview.contentSize.height = scrollview.frame.size.height;
scrollview.addSubview(imageView);
}
scrollview.layer.borderWidth = 1;
}
}
I have set that the images must have the same width and height as the scrollview. But these are larger in the simulator (and in my iPhone 11) and therefore the display is incorrect. I show you the sequence of the 3 squares:
Page 1
Page 2
Page 3
Page 4
I can't understand where I'm wrong. Why don't the 3 images take the size of the scrollview?
Why are there 4 pages?
Thanks for your help
Okay, here is how you do it:
Your scrollview is created in storyboard and its layout is set. Make sure content layout guides is unchecked in the size inspector and paging is checked in the attribute inspector.
Add a stackview as a subview to your scrollview (this will act as the content view). Pin your stackView to all 4 edges of the scrollView.
Set Height and Width Equal to the scrollView height and width. Set the Width priority to 250. (that indicates that the scrollview will scroll horizontally)
Set the stackView to horizontal axis, fill alignment and fillEqually distribution.
Now, go back to viewDidLoad and add the following code below. ScrollViewContentView is the stackView that acts as a contentView for the scrollView. Note that since stackView is set to fillEqually, you only need set one of the image's width constraint.
scrollViewContentView.addArrangedSubview(image1)
scrollViewContentView.addArrangedSubview(image2)
scrollViewContentView.addArrangedSubview(image3)
image1.translatesAutoresizingMaskIntoConstraints = false
image2.translatesAutoresizingMaskIntoConstraints = false
image3.translatesAutoresizingMaskIntoConstraints = false
image1.backgroundColor = .blue
image2.backgroundColor = .yellow
image3.backgroundColor = .red
image1.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
I think you need to state the frame of the scrollview before you declare the imageViews x positions or widths.
class ViewController: UIViewController, UIScrollViewDelegate {
// Outlet
#IBOutlet weak var scrollview: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
scrollview.frame = view.frame // declared here
scrollview.delegate = self;
let infoArray = ["01", "02", "03"];
for i in 0..<infoArray.count {
let imageView = UIImageView();
imageView.contentMode = .scaleToFill;
imageView.image = UIImage(named: infoArray[i]);
let xPos = CGFloat(i) * scrollview.bounds.size.width;
imageView.frame = CGRect(x: xPos, y: 0, width: scrollview.bounds.size.width, height: scrollview.bounds.size.height);
imageView.layer.borderWidth = 1;
scrollview.contentSize.width = scrollview.frame.size.width * CGFloat(i+1);
scrollview.contentSize.height = scrollview.frame.size.height;
scrollview.addSubview(imageView);
}
scrollview.layer.borderWidth = 1;
}
}

Adding UIView as a subview to a UIButton and bring it to front is not working properly

I have a UIButton, the background color is white.
#IBOutlet weak var buttonNewPost: UIButton! {
didSet {
buttonNewPost.layer.borderColor = UIColor(red:0.88, green:0.88, blue:0.88, alpha:1.0).cgColor
buttonNewPost.layer.cornerRadius = 5
buttonNewPost.backgroundColor = .white
}
}
I want to add an UIView to add a shadow to this rounded button:
let buttonShadow = UIView()
buttonShadow.frame.size.width = buttonNewPost.layer.bounds.width
buttonShadow.frame.size.height = buttonNewPost.layer.bounds.height
buttonShadow.backgroundColor = .clear
buttonShadow.dropShadowEdged = true
buttonShadow.isUserInteractionEnabled = false
buttonNewPost.addSubview(buttonShadow)
buttonShadow.bringSubviewToFront(buttonNewPost)
The result is like this:
Why is the UIButton not in the front with the white background color? When I change the backgroundcolor of the UIButton to blue:
Why is it like that? I just want a white button with a shadow
You can apply shadow directly to UIButton:-
#IBOutlet weak var Btn: UIButton! {
didSet {
Btn.layer.borderColor = UIColor(red:0.88, green:0.88, blue:0.88, alpha:1.0).cgColor
Btn.layer.cornerRadius = 5
Btn.backgroundColor = .white
}
}
Add below code to Viewdidload:-
Btn?.layer.borderColor = UIColor.black.cgColor
Btn?.layer.borderWidth = 1.0
Btn?.layer.cornerRadius = 20.0
Btn?.layer.shadowOpacity = 0.5
Btn?.layer.shadowColor = UIColor.red.cgColor
Btn?.layer.shadowRadius = 5.0
Btn?.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
After using this code you will get result like this

How to make a stretchable image view by scroll view

I have a scroll view and an imageView at the top, I want to pin and make a stretchable image view but if I add this image view to the view the image won't disappear when the user scroll down the view and if I add the image to the scroll view this won't be pinned at the top when the user scroll down.
So how can I pin the image at the top and then when the user scroll down the image will disappear.
Like that: http://blog.enabled.com.au/stretchy-layouts-on-ios/ but not with his framework.
class LocalsVC: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
setNavBarSettings()
scrollView.delegate = self
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
view.addSubview(imageView)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let y = 300 - (scrollView.contentOffset.y + 300)
let height = min(max(y, 60), 400)
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height)
}
Add the image to the scrollView and not to the view: scrollView.addSubview(imageView).

Can you give UIStackView borders?

I'm trying to give 5 separate UIStackViews in my ViewController borders. I gave each of them an IBOutlet and then called them in viewDidLoad to use the layer property but to no avail. Is it not possible to give stack views borders, programatically?
Code:
#IBOutlet weak var stackView1: UIStackView!
#IBOutlet weak var stackView2: UIStackView!
#IBOutlet weak var stackView3: UIStackView!
#IBOutlet weak var stackView4: UIStackView!
#IBOutlet weak var stackView5: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
stackView1.layer.borderWidth = 5
stackView2.layer.borderWidth = 5
stackView3.layer.borderWidth = 5
stackView4.layer.borderWidth = 5
stackView5.layer.borderWidth = 5
}
Unfortunately this can't be done. UIStackView is unusual in that it is a "non-rendering" view which performs layout (using Auto Layout constraints) but does not display itself. It has a layer like all UIViews, but it's ignored.
See the Apple doc under "Managing the Stack View's Appearance":
The UIStackView is a nonrendering subclass of UIView. It does not
provide any user interface of its own. Instead, it just manages the
position and size of its arranged views. As a result, some properties
(like backgroundColor) have no affect on the stack view. Similarly,
you cannot override layerClass, drawRect:, or drawLayer:inContext:
Its possible to do this by having views inside the stack view be the borders. This can be a lot of work and there might be certain situations that either won't work or have to be worked around so it might not be worth the effort. You'll need to nest the stack views so you can provide borders in both the horizontal and vertical directions. In my Bordered Stack Views blog post I go into more detail about this. But basically I have regular views have a background set to the color of my choosing and I give height or width constraints of 1 depending on the direction of the stack view's axis. Here is the full hierarchy of a 2x2 grid built in interface builder:
Resulting in this result:
Here's a link to my github repo of this example so you can see the storyboard file.
You can embed stackView inside a UIView, then set borders of that view (color, width, etc), and then constraint stackView to that UIView like top, left, right, height.
Here's a handy chunk of code I found and use:
extension UIView {
func addTopBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x:0,y: 0, width:self.frame.size.width, height:width)
self.layer.addSublayer(border)
}
func addRightBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x: self.frame.size.width - width,y: 0, width:width, height:self.frame.size.height)
self.layer.addSublayer(border)
}
func addBottomBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x:0, y:self.frame.size.height - width, width:self.frame.size.width, height:width)
self.layer.addSublayer(border)
}
func addLeftBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x:0, y:0, width:width, height:self.frame.size.height)
self.layer.addSublayer(border)
}
func addMiddleBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x:self.frame.size.width/2, y:0, width:width, height:self.frame.size.height)
self.layer.addSublayer(border)
}
}
Simply use on any view like this:
bottomControls.addMiddleBorderWithColor(color: buttonBorderColor, width: 3.0)
Source: How to add only a TOP border on a UIButton?
As indicated by others you cannot do this (for details see the answer by Clafou).
What you can do, however, is embed your stack view in another UIView; making modifications to the layer of the enclosing UIView.
I think the easiest way to do it is by using no more labels or views with hight/width equals one to represent borders , I mean it is even easier than that via making use of SPACING attribute of stack views themselves . Just fill your stack and its substances , then make spacing one for outer vertical stack , also make spacing one for inner horizontal stacks , you get perfect result . Lastly for sake of giving a specific color to borders I maintained this using background view for the outer stckview , it just has same constraint like stack with background color as you wish to borders , idea is when you make spacing the spacing takes color of view behind the stack , that's it :D , kindly check results as in attached image and let me know if anything not clear
I have multiple UIStackViews inside a UIStackView.
I wanted a top and bottom border only for ONE of the UIStackViews in the stack so I added the UIStackView in question to a UIView with the background color set to the color of the top & bottom border color I wanted and replaced the bordered UIStackView in the arrangedSubviews with the UIView.
import UIKit
import Foundation
let goldBorderedUIView = UIView()
lazy var mainStackView: UIStackView =
{
let mainStack = UIStackView(arrangedSubviews: [goldBorderedUIView, stack2, stack3, stack 4])
mainStack.translatesAutoresizingMaskIntoConstraints = false
mainStack.axis = .vertical
mainStack.spacing = 0.5
mainStack.distribution = .fillEqually
return mainStack
}()
func setupBorderdStack() {
NSLayoutConstraint.activate([
borderedStackView.leadingAnchor.constraint(equalTo: goldBorderedUIView.leadingAnchor),
borderedStackView.topAnchor.constraint(equalTo: goldBorderedUIView.topAnchor, constant: 5),
borderedStackView.trailingAnchor.constraint(equalTo: goldBorderedUIView.trailingAnchor),
borderedStackView.bottomAnchor.constraint(equalTo: goldBorderedUIView.bottomAnchor, constant: -5)
])
}
override func viewDidLoad() {
super.viewDidLoad()
setupBorderdStack()
}
use like this
loseWeight.layer.borderColor = UIColor.orange.cgColor
loseWeight.layer.borderWidth = 1
The simplest way I've found to add a border to a UIStackView is to extend the stack view class and then add two layered views: the bottom one being the same size as the stack view, and the one on top that's used mask out the inside of the border, which is slightly smaller.
Here's the extension in Swift 5:
extension UIStackView {
func addBorder(color: UIColor, backgroundColor: UIColor, thickness: CGFloat) {
let insetView = UIView(frame: bounds)
insetView.backgroundColor = backgroundColor
insetView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(insetView, at: 0)
let borderBounds = CGRect(
x: thickness,
y: thickness,
width: frame.size.width - thickness * 2,
height: frame.size.height - thickness * 2)
let borderView = UIView(frame: borderBounds)
borderView.backgroundColor = color
borderView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(borderView, at: 0)
}
}
Then you add the border with a call like this:
myStackView.addBorder(color: .lightGray, backgroundColor: .white, thickness: 2)

Swift: Embed a scrollView in a custom UITableViewCell

I am working on this UITableViewCell customization to get something similar to a Facebook feed look.
I need a cell to contain 2 labels followed by a scroll view(to display some images). I have tried with having these 3 elements inside a uiView as such,
-Cell
--contentView
---UIView
----Label
----Label
----ScrollView
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var contentLabel: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var cardView: UIView!
I need the cells to adjust the height based on the length of the text.
Where I am stuck at is where the cell adjusts the height based on the text, but the scrollview that is displayed, is split into two cells.
Needless to say I am new to swift. This is the basic flow of what I have so far in cellForRowAtIndexPath
cell.dateLabel.text = somedatelabel
cell.contentLabel.text = someContent
let width = cell.scrollView.frame.width
let height = cell.scrollView.frame.height
var mainCardView = UIView(frame: CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.width, cell.frame.height))
var scrollview = UIScrollView(frame: CGRectMake(cell.contentLabel.frame.origin.x, cell.contentLabel.frame.origin.y+cell.contentLabel.frame.height, width, height))
scrollview.contentSize = CGSizeMake(width*2, height)
var imageOne = UIImageView(frame: CGRectMake(0, 0, width , height))
var imageTwo = UIImageView(frame: CGRectMake(width, 0, width, height))
imageOne.image = UIImage(named: "one.jpg")
imageTwo.image = UIImage(named: "two.jpg")
scrollview.addSubview(imageOne)
scrollview.addSubview(imageTwo)
scrollview.contentSize = CGSizeMake(width*2, height)
scrollview.contentMode = UIViewContentMode.ScaleAspectFit
mainCardView.addSubview(scrollview)
cell.cardView = mainCardView
cell.contentView.addSubview(mainCardView)
cell.layoutSubviews()
cell.layoutIfNeeded()
I also added this in viewDidLoad
tableView.estimatedRowHeight = 150.0
tableView.rowHeight = UITableViewAutomaticDimension
Any suggestions on how to size the cell so that scrollView is part of the contentView?