how to programmatically show a colored disk behind a UIImageView, in swift on an iOS device - ios

I have an icon that I programmatically display.
How can I display a solid, colored disk behind the icon, at the same screen position?
Icon is opaque.
I will sometimes programmatically change screen position and disk's diameter and color.
Here's how I programmatically display the icon now.............
DispatchQueue.main.async
{
ViewController.wrist_band_UIImageView.frame = CGRect( x: screen_position_x,
y: screen_position_y,
width: App_class.screen_width,
height: App_class.screen_height)
}
UPDATE #1 for D.Mika below...
UPDATE #2 for D.Mika below...
import UIKit
import Foundation
class ViewController: UIViewController
{
static var circleView: UIView!
static let wrist_band_UIImageView: UIImageView = {
let theImageView = UIImageView()
theImageView.image = UIImage( systemName: "applewatch" )
theImageView.translatesAutoresizingMaskIntoConstraints = false
return theImageView
}()
override func viewDidLoad()
{
super.viewDidLoad()
view.addSubview( ViewController.wrist_band_UIImageView )
// Init disk image:
ViewController.circleView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
ViewController.circleView.backgroundColor = .red
ViewController.circleView.layer.cornerRadius = view.bounds.size.height / 2.0
ViewController.circleView.clipsToBounds = true
// Add view to view hierarchy below image view
ViewController.circleView.insertSubview(view, belowSubview: ViewController.wrist_band_UIImageView)
App_class.display_single_wearable()
}
}
class App_class
{
static var is_communication_established = false
static var total_packets = 0
static func display_single_wearable()
{
ViewController.wrist_band_UIImageView.frame = CGRect(x: 0, y: 0,
width: 100, height: 100)
ViewController.circleView.frame = CGRect( x: 0,
y: 0,
width: 100,
height: 100)
ViewController.circleView.layer.cornerRadius = 100
}
static func process_location_xy(text_location_xyz: String)
{}
} // App_class

You can display a colored circle using the following view:
circleView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
circleView.backgroundColor = .red
circleView.layer.cornerRadius = view.bounds.size.height / 2.0
circleView.clipsToBounds = true
// Add view to view hierarchy below image view
view.insertSubview(circleView, belowSubview: wrist_band_UIImageView)
You can change it's position and size by applying a new frame. But you have to change the layer's cornerRadius accordingly.
This is a simple example in a playground:
Edit:
I've modified the sample code to add the view the view hierarchy.
BUT, you still need to adjust the circle's frame, when you modify the image view's frame. (and the cornerRadius accordingly). For example
DispatchQueue.main.async
{
ViewController.wrist_band_UIImageView.frame = CGRect( x: screen_position_x,
y: screen_position_y,
width: App_class.screen_width,
height: App_class.screen_height)
circleView.frame = CGRect( x: screen_position_x,
y: screen_position_y,
width: App_class.screen_width,
height: App_class.screen_height)
circleView.layer.cornerRadius = App_class.screen_width
}
And you need to add a variable to the viewController holding the reference to the circle view, like:
var circleView: UIView!

The following answer works.
The answers from d.mika above did not work. Plus, he was insulting. ;-)
// Show red circle
let circlePath = UIBezierPath(arcCenter: CGPoint(x: 200, y: 400), radius: CGFloat(40), startAngle: CGFloat(0), endAngle: CGFloat(Double.pi * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
// Change the fill color
shapeLayer.fillColor = UIColor.red.cgColor
// You can change the stroke color
shapeLayer.strokeColor = UIColor.red.cgColor
// You can change the line width
shapeLayer.lineWidth = 3.0
view.layer.addSublayer(shapeLayer)

Related

How to add a bottom border in swift ios?

I am trying to add a bottom border to my tabs. Here is the code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .systemBackground
self.navigationItem.titleView = UIImageView(
image: UIImage(named: "Twitter")!.resize(25, 25)
)
let leftBarImage = UIImageView(
image: UIImage(named: "Profile")!.resize(35, 35)
)
leftBarImage.layer.borderWidth = 1
leftBarImage.layer.borderColor = UIColor.systemGray4.cgColor
leftBarImage.layer.cornerRadius = leftBarImage.frame.width / 2
leftBarImage.clipsToBounds = true
self.navigationItem.leftBarButtonItem = UIBarButtonItem(
customView: leftBarImage
)
let segmentedControl = UIStackView()
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
segmentedControl.axis = .horizontal
segmentedControl.alignment = .center
segmentedControl.distribution = .fillEqually
segmentedControl.backgroundColor = .green
segmentedControl.addBorder(
for: .Bottom,
color: UIColor.red.cgColor,
thickness: 20
)
for menuLabelText in ["For you", "Following"] {
let menuLabel = UILabel()
menuLabel.text = menuLabelText
menuLabel.textAlignment = .center
menuLabel.font = UIFont.boldSystemFont(ofSize: 16)
segmentedControl.addArrangedSubview(menuLabel)
}
self.view.addSubview(segmentedControl)
NSLayoutConstraint.activate([
segmentedControl.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
segmentedControl.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor)
])
}
}
And the border logic,
import UIKit
extension UIView {
enum BorderSide {
case Left, Right, Top, Bottom
}
func addBorder(for side: BorderSide, color: CGColor, thickness: CGFloat) {
let border = CALayer()
border.backgroundColor = color
switch side {
case .Left:
border.frame = CGRect(
x: frame.minX,
y: frame.minY,
width: thickness,
height: frame.height
)
break
case .Right:
border.frame = CGRect(
x: frame.maxX,
y: frame.minY,
width: thickness,
height: frame.height
)
break
case .Top:
border.frame = CGRect(
x: frame.minX,
y: frame.minY,
width: frame.width,
height: thickness
)
break
case .Bottom:
border.frame = CGRect(
x: frame.minX,
y: frame.maxY,
width: frame.width,
height: thickness
)
break
}
layer.addSublayer(border)
}
}
The border is not showing at all. Here is a screenshot:
You can see the green background but not the red border beneath. Any help would be appreciated. Thanks!
First, let's look at what's wrong with the code...
The addBorder(...) func in your UIView extension uses the view's frame -- so, let's put a print() statement right before we try to add the border, to see the the view's frame:
segmentedControl.backgroundColor = .green
// print the frame of segmentedControl to debug console
print("segmentedControl Frame in viewDidLoad():", segmentedControl.frame)
segmentedControl.addBorder(
for: .Bottom,
color: UIColor.red.cgColor,
thickness: 20
)
You will see this in the debug console:
segmentedControl Frame in viewDidLoad(): (0.0, 0.0, 0.0, 0.0)
So your extension tries to set the frame of the layer:
border.frame = CGRect(
x: frame.minX, // minX == 0
y: frame.maxY, // maxY == 0
width: frame.width, // width == 0
height: thickness. // thickness == 20 (passed in call)
)
As we see, we end up with a layer frame of (x: 0.0, y: 0.0, width: 0.0, height: 20.0) ... we won't see anything, because it has no width.
So, let's try adding the border in viewDidLayoutSubviews().
Note that we'll move the segmentedControl creation outside of viewDidLoad() so we can reference it elsewhere. And, we'll leave the addBorder() with red where it was, then call it again with blue in viewDidLayoutSubviews():
class ViewController: UIViewController {
// create it here, so we can reference it outside of viewDidLoad()
let segmentedControl = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .systemBackground
self.title = "Bad Layout"
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
segmentedControl.axis = .horizontal
segmentedControl.alignment = .center
segmentedControl.distribution = .fillEqually
segmentedControl.backgroundColor = .green
// print the frame of segmentedControl to debug console
print("segmentedControl Frame in viewDidLoad():", segmentedControl.frame)
segmentedControl.addBorder(
for: .Bottom,
color: UIColor.red.cgColor,
thickness: 20
)
for menuLabelText in ["For you", "Following"] {
let menuLabel = UILabel()
menuLabel.text = menuLabelText
menuLabel.textAlignment = .center
menuLabel.font = UIFont.boldSystemFont(ofSize: 16)
segmentedControl.addArrangedSubview(menuLabel)
}
self.view.addSubview(segmentedControl)
NSLayoutConstraint.activate([
segmentedControl.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
segmentedControl.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor)
])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// print the frame of segmentedControl to debug console
print("segmentedControl Frame in viewDidLayoutSubviews():", segmentedControl.frame)
segmentedControl.addBorder(
for: .Bottom,
color: UIColor.blue.cgColor,
thickness: 20
)
}
}
extension UIView {
enum BorderSide {
case Left, Right, Top, Bottom
}
func addBorder(for side: BorderSide, color: CGColor, thickness: CGFloat) {
let border = CALayer()
border.backgroundColor = color
switch side {
case .Left:
border.frame = CGRect(
x: frame.minX,
y: frame.minY,
width: thickness,
height: frame.height
)
break
case .Right:
border.frame = CGRect(
x: frame.maxX,
y: frame.minY,
width: thickness,
height: frame.height
)
break
case .Top:
border.frame = CGRect(
x: frame.minX,
y: frame.minY,
width: frame.width,
height: thickness
)
break
case .Bottom:
border.frame = CGRect(
x: frame.minX,
y: frame.maxY,
width: frame.width,
height: thickness
)
break
}
layer.addSublayer(border)
}
}
Now, we see two "print frame" outputs:
segmentedControl Frame in viewDidLoad(): (0.0, 0.0, 0.0, 0.0)
segmentedControl Frame in viewDidLayoutSubviews(): (0.0, 97.66666666666667, 393.0, 19.333333333333332)
Unfortunately, this is the result:
The blue layer is positioned way below the bottom of the stack view / labels.
That's happening because the extension is using frame.maxY -- which is frame.origin.y + frame.size.height -- and the frame's origin.y is 97.66666666666667 (it's top is below the navigation bar).
You could use the same addBorder() approach, by calling it after the views have been laid out (that is, after the frames have been set), and modifying the extension to use the view's bounds instead of frame:
case .Bottom:
border.frame = CGRect(
x: bounds.minX,
y: bounds.maxY,
width: bounds.width,
height: thickness
)
break
and we get this:
However... as should be obvious, this is really not a good approach. Worth noting also is that the layer appears outside the bounds of the view. So, if you were to add a subview constrained to the bottom of segmentedControl, the top of that view would be covered by the 20-point tall "border" layer.
My guess is that you are also going to want to be able to tap the labels... possible you also want to move that "border" to show only under the selected label... etc.
Do some searching / exploring how to subclass UIView so it handles all of that by itself.

Add subview on a parent drawn through UIBezierPath

I've a custom UITabBar. Its bar has a simple but customised shape: its height is bigger then default one, has rounded corners and (important) a shadow layer on the top.
The result is this:
Now I've to add an element that shows the selected section on the top of the bar, to achieve this:
The problem is that no matter the way I choose to add this element (add a subview to the bar or add a new sublayer) but the new element will always be drawn outside the corners. I suppose this is because I can't enable the clipping mask (if I enable the clipping mask I'll kill the shadow and also, more important, the bezierpath)
Do you have any tips for this?
Basically, the goal should be:
have an element that moves horizontally (animated) but cannot be drawn outside the parent (the tabbar)
Actually, the code to draw the custom tabBar is:
class CustomTabBar: UITabBar {
/// The layer that defines the custom shape
private var shapeLayer: CALayer?
/// The radius for the border of the bar
var borderRadius: CGFloat = 0
override func layoutSubviews() {
super.layoutSubviews()
// aspect and shadow
isTranslucent = false
backgroundColor = UIColor.white
tintColor = AZTheme.PaletteColor.primaryColor
shadowImage = nil
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.1
layer.shadowOffset = CGSize(width: 0, height: -1)
layer.shadowRadius = 10
}
override func draw(_ rect: CGRect) {
drawShape()
}
/// Draw and apply the custom shape to the bar
func drawShape() {
let shapeLayer = CAShapeLayer()
shapeLayer.path = createPath()
shapeLayer.fillColor = AZTheme.tabBarControllerBackgroundColor.cgColor
if let oldShapeLayer = self.shapeLayer {
self.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
} else {
self.layer.insertSublayer(shapeLayer, at: 0)
}
self.shapeLayer = shapeLayer
}
}
// MARK: - Private functions
extension CustomTabBar {
/// Return the custom shape for the bar
internal func createPath() -> CGPath {
let height: CGFloat = self.frame.height
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addArc(withCenter: CGPoint(x: borderRadius, y: 0), radius: borderRadius, startAngle: CGFloat.pi, endAngle: CGFloat.pi * (3/2), clockwise: true)
path.addLine(to: CGPoint(x: frame.width - borderRadius, y: -borderRadius))
path.addArc(withCenter: CGPoint(x: frame.width - borderRadius, y: 0), radius: borderRadius, startAngle: CGFloat.pi * (3/2), endAngle: 0, clockwise: true)
path.addLine(to: CGPoint(x: frame.width, y: height))
path.addLine(to: CGPoint(x: 0, y: height))
path.close()
return path.cgPath
}
}
I solved splitting the owner of custom shape from the owner of the shadow in 2 different views. So I'm using 3 views achieve the goal.
CustomTabBar: has default size and casts shadow with offset.
|
└ SelectorContainer: is a view with custom shape (BezierPath) that is
positioned on the top of the TabBar to graphically "extend" the view
and have the feeling of a bigger TabBar. It has rounded corners on
the top-right, top-left margin. MaskToBounds enabled.
|
└ Selector: simple view that change the its origin through animation.
See the result here
The code:
class CustomTabBar: UITabBar {
/// The corner radius value for the top-left, top-right corners of the TabBar
var borderRadius: CGFloat = 0
/// Who is containing the selector. Is a subview of the TabBar.
private var selectorParent: UIView?
/// Who moves itself following the current section. Is a subview of ```selectorParent```.
private var selector: UIView?
/// The height of the ```selector```
private var selectorHeight: CGFloat = 5
/// The number of sections handled by the TabBarController.
private var numberOfSections: Int = 0
override func layoutSubviews() {
super.layoutSubviews()
isTranslucent = false
backgroundColor = UIColor.white
tintColor = AZTheme.PaletteColor.primaryColor
shadowImage = nil
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.1
layer.shadowOffset = CGSize(width: 0, height: -1)
layer.shadowRadius = 10
}
}
// MARK: - Private functions
extension CustomTabBar {
/// Create the selector element on the top of the TabBar
func setupSelectorView(numberOfSections: Int) {
self.numberOfSections = numberOfSections
// delete previous subviews (if exist)
if let selectorContainer = self.selectorParent {
selectorContainer.removeFromSuperview()
self.selector?.removeFromSuperview()
self.selectorParent = nil
self.selector = nil
}
// SELECTOR CONTAINER
let selectorContainerRect: CGRect = CGRect(x: 0,
y: -borderRadius,
width: frame.width,
height: borderRadius)
let selectorContainer = UIView(frame: selectorContainerRect)
selectorContainer.backgroundColor = UIColor.white
selectorContainer.AZ_roundCorners([.topLeft, .topRight], radius: borderRadius)
selectorContainer.layer.masksToBounds = true
self.addSubview(selectorContainer)
// SELECTOR
let selectorRect: CGRect = CGRect(x: 0,
y: 0,
width: selectorContainer.frame.width / CGFloat(numberOfSections),
height: selectorHeight)
let selector = UIView(frame: selectorRect)
selector.backgroundColor = AZTheme.PaletteColor.primaryColor
selectorContainer.addSubview(selector)
// add views to hierarchy
self.selectorParent = selectorContainer
self.selector = selector
}
/// Animate the position of the selector passing the index of the new section
func animateSelectorTo(sectionIndex: Int) {
guard let selectorContainer = self.selectorParent, let selector = self.selector else { return }
selector.layer.removeAllAnimations()
let sectionWidth: CGFloat = selectorContainer.frame.width / CGFloat(numberOfSections)
let newCoord = CGPoint(x: sectionWidth * CGFloat(sectionIndex), y: selector.frame.origin.y)
UIView.animate(withDuration: 0.25, delay: 0, options: UIView.AnimationOptions.curveEaseOut, animations: { [weak self] in
self?.selector?.frame.origin = newCoord
}, completion: nil)
}
}

IOS - How to create Facebook reaction bar with blur background?

Although it may not be the week to replicate some design of Facebook, I would like to be able to design my own version of the reaction indicator view below.
I have three UIImageViews lined in the same positions as above. The problem is that, unlike Facebook, the background color may change (i.e is on top of a UIBlurEffect) and therefore I am unable to set the border color to white.
I thought it would make sense to set the borderColor like so:
imageViewOne.layer.borderColor = UIColor.clear.cgColor
imageViewOne.layer.borderWidth = 2
However, the underlying imageViewTwo is displayed in the border instead of the background color.
So far, I have this:
Would appreciate some help/ideas on how to make this work - I'm thinking of masks but not sure whether a. this is the correct solution and b. how to achieve the desired effect. To clarify, I am not able to set the border color as a constant as it will change with the UIBlurEffect.
In my opinion, there are 2 way to resolve your problem.
Create and use clipped image for Wow and Love like below Love image.
Another way is using mask property of UIView. Creating a mask image and apply it for mask property.
Mask image looks like.
Code for applying mask.
let imvLoveMask = UIImageView.init(image: UIImage.init(named: "MASK_IMAGE_NAME"));
imvLoveMask.frame = CGRect.init(x: 0, y: 0, width: imvLove.frame.size.width, height: imvLove.frame.size.height);
imvLove.mask = imvLoveMask;
Both of 2 above way can help you achieve what you want in the question. Background of icons in below image is an UIVisualEffectView.
In my opinion, the first way with clipped image is better and faster because you don't need to apply mask for your imageView. But if you don't want to create a clipped image for some reason, you can use the second way.
For more detail, you can take a look at my demo repo
You need to clip part of the image in order to let underlying content be visible in the gaps between images. See playground sample.
Add smile_1, smile_2, smile_3 images to playground resources. I took emoji images from https://emojipedia.org/facebook/.
import UIKit
import PlaygroundSupport
class EmojiView: UIView {
var imageView = UIImageView()
var imageInset = UIEdgeInsets(top: 3.0, left: 3.0, bottom: 3.0, right: 3.0)
var shapeLayer = CAShapeLayer()
var overlap: CGFloat = 0.0 {
didSet {
self.updateShape()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// MARK: UIView
override func awakeFromNib() {
super.awakeFromNib()
self.setup()
}
override func layoutSubviews() {
super.layoutSubviews()
self.imageView.frame = UIEdgeInsetsInsetRect(self.bounds, self.imageInset)
self.shapeLayer.frame = self.bounds
self.updateShape()
}
// MARK: Private
private func setup() {
self.addSubview(self.imageView)
self.layer.mask = self.shapeLayer
}
private func updateShape() {
let frame = self.bounds
let path = UIBezierPath(rect: frame)
// Cut off part of the image if overlap more then > 0
if 0 < self.overlap {
path.usesEvenOddFillRule = true
path.append(UIBezierPath(ovalIn: CGRect(x: -frame.width + self.overlap, y: 0.0, width: frame.width, height: frame.height)).reversing())
}
self.shapeLayer.path = path.cgPath
}
}
let overlap: CGFloat = 10 // Amount of pixels emojis overlap each other
// Create emoji views
let emojiView_1 = EmojiView(frame: CGRect(x: 5.0, y: 5.0, width: 40.0, height: 40.0))
emojiView_1.imageView.image = UIImage(named: "smile_1")
let emojiView_2 = EmojiView(frame: CGRect(x: emojiView_1.frame.maxX - overlap, y: 5.0, width: 40.0, height: 40.0))
emojiView_2.imageView.image = UIImage(named: "smile_2")
emojiView_2.overlap = overlap
let emojiView_3 = EmojiView(frame: CGRect(x: emojiView_2.frame.maxX - overlap, y: 5.0, width: 40.0, height: 40.0))
emojiView_3.imageView.image = UIImage(named: "smile_3")
emojiView_3.overlap = overlap
let holderView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: emojiView_3.frame.maxX + 5, height: 50.0))
// Add gradient layer
let gradientLayer = CAGradientLayer()
gradientLayer.frame = holderView.bounds
gradientLayer.colors = [UIColor.red.cgColor, UIColor.green.cgColor]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
holderView.layer.addSublayer(gradientLayer)
// Add emoji views
holderView.addSubview(emojiView_1)
holderView.addSubview(emojiView_2)
holderView.addSubview(emojiView_3)
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = holderView
use this :
self.imageViewOne.layer.cornerRadius = self.imageViewOne.layer.bounds.width/2
self.imageViewOne.layer.masksToBounds = true
Simple suggestion: As you are setting border color programatically, you have a control to change it, according to background color (if background color is solid (not a gradient)).
imageViewOne.layer.borderColor = imageViewOne.superview?.backgroundColor ?? UIColor.white
imageViewOne.layer.borderWidth = 2.0
Actually instead of masking, you can put your images in a view which has white background and round(set corner radius). Then you can put these views (which has white background and images in it) via settings their zPosition or on storyboard with view hierarchy.
I've prepared a little playground for you. You can see the result in the screenshot. I've put a view inside the containerViews instead you can use uiimageview etc. It's a bit ugly but solves your issue I guess it's up to you to decide how use it.
Here is the code, you can just copy and paste it to a new playground and test it.
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
var mainContainerView = UIView(frame: CGRect(x: 0, y: 0, width: 140, height: 80))
mainContainerView.backgroundColor = UIColor.white
var containerView = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
containerView.backgroundColor = UIColor.white
containerView.layer.cornerRadius = containerView.frame.width / 2
var innerView = UIView(frame: CGRect(x: 10, y: 10, width: 60, height: 60))
innerView.backgroundColor = UIColor.red
innerView.layer.cornerRadius = innerView.frame.width / 2
containerView.addSubview(innerView)
var containerView2 = UIView(frame: CGRect(x: 60, y: 0, width: 80, height: 80))
containerView2.backgroundColor = UIColor.yellow
containerView2.layer.cornerRadius = containerView2.frame.width / 2
var innerView2 = UIView(frame: CGRect(x: 10, y: 10, width: 60, height: 60))
innerView2.backgroundColor = UIColor.green
innerView2.layer.cornerRadius = innerView2.frame.width / 2
containerView2.addSubview(innerView2)
containerView.layer.zPosition = 2
containerView2.layer.zPosition = 1
mainContainerView.addSubview(containerView)
mainContainerView.addSubview(containerView2)
PlaygroundPage.current.liveView = mainContainerView

ios: i want to add border at top and bottom side in tableview

i have applied below code in viewdidload() but using this code border is arrive but it scrolling with table content.i want fix border at top and bottom side.
here my code is ->
let topBorder = CAShapeLayer()
let topPath = UIBezierPath()
topPath.move(to: CGPoint(x: 0, y: 0))
topPath.addLine(to: CGPoint(x: tblFilter.frame.width, y: 0))
topBorder.path = topPath.cgPath
topBorder.strokeColor = UIColor.red.cgColor
topBorder.lineWidth = 1.0
topBorder.fillColor = UIColor.red.cgColor
tblFilter.layer.addSublayer(topBorder)
let bottomBorder = CAShapeLayer()
let bottomPath = UIBezierPath()
bottomPath.move(to: CGPoint(x: 0, y: tblFilter.frame.height))
bottomPath.addLine(to: CGPoint(x: tblFilter.frame.width, y: tblFilter.frame.height))
bottomBorder.path = bottomPath.cgPath
bottomBorder.strokeColor = UIColor.red.cgColor
bottomBorder.lineWidth = 1.0
bottomBorder.fillColor = UIColor.red.cgColor
tblFilter.layer.addSublayer(bottomBorder)
give me suggetion and thanks
I am using below methods to add borders to any view. Please take a look if it helps you.
//MARK: - Add Border to View -
func addTopBorderWithColor(_ objView : UIView, color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x: 0, y: 0, width: objView.frame.size.width, height: width)
objView.layer.addSublayer(border)
}
func addBottomBorderWithColor(_ objView : UIView, color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x: 0, y: objView.frame.size.height - width, width: objView.frame.size.width, height: width)
objView.layer.addSublayer(border)
}
I have a method which uses few enums to achieve what you want to do. Please see objective c code below
-(void) addUIViewAt:(postionOfView) position OfView:(UIView *) view ofHeight:(int) height ofBackgroundColor:(UIColor *)backgroundColor{
UIView *viewForBorder = [[UIView alloc] init] ;
if (position == positionTop){
[viewForBorder setFrame:CGRectMake(view.bounds.origin.x
, view.bounds.origin.y, view.bounds.size.width, height)];
}
else if (position == positionBottom){
[viewForBorder setFrame:CGRectMake(view.bounds.origin.x
, view.bounds.size.height - height, view.bounds.size.width, height)];
}
else if (position == positionLeft){
[viewForBorder setFrame:CGRectMake(view.bounds.origin.x
, view.bounds.origin.y, height, view.bounds.size.height)];
}
else{
[viewForBorder setFrame:CGRectMake(view.bounds.size.width - height
, view.bounds.origin.y, height, view.bounds.size.height)];
}
[viewForBorder setBackgroundColor:backgroundColor];
[view addSubview:viewForBorder];
// viewForBorder.layer.zPosition = MAXFLOAT;
}
Also use these enums for the method above
/**
this used to detect the position of border overlay on a view
*/
typedef enum : NSUInteger {
positionTop,
positionRight,
positionLeft,
positionBottom,
} postionOfView;
Just feed this method with appropriate values

Custom progress view

I want to do a custom progress view for my iOS app, with 2 dots. Here is my code:
import UIKit
#IBDesignable
class StepProgressView: UIView {
#IBInspectable var progress: Float = 0
var progressColor = UIColor.blackColor()
var bgColor = UIColor.whiteColor()
override func layoutSubviews() {
self.backgroundColor = UIColor.clearColor()
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
let height = frame.height-8
let circle1 = UIView(frame: CGRect(x: frame.width*(1/3), y: 0, width: frame.height, height: frame.height))
circle1.backgroundColor = bgColor
circle1.layer.cornerRadius = frame.height/2
addSubview(circle1)
let circle2 = UIView(frame: CGRect(x: frame.width*(2/3), y: 0, width: frame.height, height: frame.height))
circle2.backgroundColor = bgColor
circle2.layer.cornerRadius = frame.height/2
addSubview(circle2)
let bgView = UIView(frame: CGRect(x: height/2, y: 4, width: frame.width-height/2, height: height))
bgView.backgroundColor = bgColor
bgView.layer.cornerRadius = height/2
addSubview(bgView)
let progressView = UIView(frame: CGRect(x: 0, y: 4, width: frame.width*CGFloat(progress), height: height))
progressView.backgroundColor = progressColor
progressView.layer.cornerRadius = height/2
addSubview(progressView)
}
}
The result:
However, as you can see, the circles aren't "filled" when the progression pass over one of them, and I don't know how to do that. I could create another view but I don't know how to handle the corner radius.
Can you help me ?
Thanks

Resources