As shown in the image how to add left side green border?
I want to add this type of border to UIview. I have tried to put this type of image inside view but that is not working in my case because it can't manage with dynamic height of the cell.
so please give me a proper solution to add layer to a view.
Edit:
private func addBorderImage() {
print("commit init")
guard let img = UIImage(named: "BorderLeft") else {
fatalError("Could not load image named \"stretch1\"!!!")
}
// create a resizable version
let stretchImg = img.resizableImage(withCapInsets: .init(top: 12.0, left: 0.0, bottom: 12.0, right: 0.0))
let imgView = UIImageView()
imgView.image = stretchImg.withRenderingMode(.alwaysTemplate)
imgView.tintColor = UIColor(named: "AccentColor")
imgView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(imgView)
let g = contentView.layoutMarginsGuide
NSLayoutConstraint.activate([
imgView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8.0),
imgView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: -10.0),
imgView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8.0),
imgView.widthAnchor.constraint(equalToConstant: 25.0),
])
}
and I am using png image but resizing is not working.
You can do this with a resizableImage.
We'll start with this image (clipped from your posted image):
It is 11 x 32
(pixels).
We can make it "stretchable" using func resizableImage(withCapInsets capInsets: UIEdgeInsets) -> UIImage
(docs) like this:
.resizableImage(withCapInsets: .init(top: 12.0, left: 0.0, bottom: 12.0, right: 0.0))
Now the top 12-pixels and bottom 12-pixels will not stretch ... only the middle part will:
Sample code:
class StretchTestVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
guard let img = UIImage(named: "stretch1") else {
fatalError("Could not load image!!!")
}
// create a resizable version
let stretchImg = img.resizableImage(withCapInsets: .init(top: 12.0, left: 0.0, bottom: 12.0, right: 0.0))
// now let's add 8 image views with increasing heights
var x: CGFloat = 40.0
var h: CGFloat = 60.0
for _ in 1...8 {
let imgView = UIImageView()
imgView.image = stretchImg
imgView.frame = .init(x: x, y: 100.0, width: 11.0, height: h)
view.addSubview(imgView)
x += 30.0
h += 50.0
}
}
}
Edit - really quick example with variable height table view cells...
class StretchCellViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let rowsInCell: [Int] = [
2, 3, 7, 5, 2, 4, 8, 5, 9, 6,
]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(tableView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
tableView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
tableView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
tableView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
])
tableView.register(StretchImageCell.self, forCellReuseIdentifier: StretchImageCell.identifier)
tableView.dataSource = self
tableView.delegate = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return rowsInCell.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: StretchImageCell.identifier, for: indexPath) as! StretchImageCell
c.fillData(numRows: rowsInCell[indexPath.row])
return c
}
}
class StretchImageCell: UITableViewCell {
static let identifier: String = "StretchImageCell"
private let stack = UIStackView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
guard let img = UIImage(named: "stretch1") else {
fatalError("Could not load image named \"stretch1\"!!!")
}
// create a resizable version
let stretchImg = img.resizableImage(withCapInsets: .init(top: 12.0, left: 0.0, bottom: 12.0, right: 0.0))
let imgView = UIImageView()
imgView.image = stretchImg
stack.axis = .vertical
stack.spacing = 8
imgView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(imgView)
stack.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(stack)
let g = contentView.layoutMarginsGuide
NSLayoutConstraint.activate([
imgView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8.0),
imgView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
imgView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8.0),
imgView.widthAnchor.constraint(equalToConstant: 11.0),
stack.topAnchor.constraint(equalTo: g.topAnchor),
stack.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 4.0),
stack.trailingAnchor.constraint(equalTo: g.trailingAnchor),
stack.bottomAnchor.constraint(equalTo: g.bottomAnchor),
])
for _ in 1...10 {
let v = UILabel()
v.font = .systemFont(ofSize: 24.0, weight: .light)
v.backgroundColor = .init(white: 0.95, alpha: 1.0)
stack.addArrangedSubview(v)
}
}
public func fillData(numRows: Int) {
// hide all the labels in the stack view
for v in stack.arrangedSubviews {
v.isHidden = true
}
// limit to 10 label rows
let n = min(10, numRows)
// now set label text and un-hide
for i in 0..<numRows {
if let v = stack.arrangedSubviews[i] as? UILabel {
v.text = "Label number: \(i+1)"
v.isHidden = false
}
}
}
}
Result: