NSScrollView subclass doesn't scroll - swift

I'm making a macOS app and i have created a simple NSScrollView subclass. However, the scrollview doesn't scroll.
When i set the property NSScrollView.hasHorizontalScroller or the property NSScrollView.hasVerticalScroller to true,
then the scrolling works. But i want the scrollbars to be hidden, so these properties will be set to false.
This is my swift (playground) code:
import Cocoa
import PlaygroundSupport
class MyScrollView: NSScrollView {
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
// fatalError("init(coder:) has not been implemented")
}
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
}
}
let scrollView = MyScrollView(frame: NSRect(x: 0, y: 0, width: 480, height: 240))
// scrollView.hasHorizontalScroller = true
// Image of 1280 x 854.
let img = NSImage(byReferencing: URL(fileURLWithPath: "/users/username/Pictures/some-image.jpg"))
let imgView = NSImageView(frame: NSRect(x: 0, y: 0, width: img.size.width, height: img.size.height))
imgView.image = img
scrollView.documentView = imgView
PlaygroundPage.current.liveView = scrollView
I have compared many properties with a normal NSScrollView, but i can't figure it out.
What am i doing wrong?
Thanks in advance.

Related

Swift - get random CGPoints from UIView

I am trying to get random CGPoints along the 'outer contour' of UIView so that I will be able to draw UIBezierPath line over obtained CGPoints. For example, get CGPoints from below red dots which I marked myself by hand. Any idea?
###Edit###
As per Sweeper's advice I am trying to add CAShapeLayer into my custom view but it returns nil when I am printing its path. Please could you point out what I am missing?
class ViewController: UIViewController {
let shapeLayer = CAShapeLayer()
override func viewDidLoad() {
super.viewDidLoad()
let view = BubbleView(frame: CGRect(x: self.view.frame.midX / 2, y: self.view.frame.midY/2, width: 150, height: 100))
view.backgroundColor = .gray
view.layer.cornerRadius = 30
self.view.addSubview(view)
}
}
class BubbleView: UIView {
var pathLayer: CAShapeLayer!
override func layoutSubviews() {
pathLayer = CAShapeLayer()
pathLayer.bounds = frame
self.layer.addSublayer(pathLayer)
print(pathLayer.path) // returns nil
}
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

How to split the background color of UIView in Swift?

I want to differentiate the background color in my app screen horizontally.
I have tried this, it's going nowhere.
var halfView1 = backgroundView.frame.width/2
backgroundView.backgroundColor.halfView1 = UIColor.black
backgroundView is an outlet from View object on storyboard
For example, half of the screen is blue and another half of the screen is red.
You should create a custom UIView class and override draw rect method
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(HorizontalView(frame: self.view.bounds))
}
}
class HorizontalView: UIView {
override func draw(_ rect: CGRect) {
super.draw(rect)
let topRect = CGRect(x: 0, y: 0, width: rect.size.width/2, height: rect.size.height)
UIColor.red.set()
guard let topContext = UIGraphicsGetCurrentContext() else { return }
topContext.fill(topRect)
let bottomRect = CGRect(x: rect.size.width/2, y: 0, width: rect.size.width/2, height: rect.size.height)
UIColor.green.set()
guard let bottomContext = UIGraphicsGetCurrentContext() else { return }
bottomContext.fill(bottomRect)
}
}
It is possible if you use a custom UIView and override the draw function, here's a Playground example :
import UIKit
import PlaygroundSupport
class CustomView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.green
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
super.draw(rect)
let bottomRect = CGRect(
origin: CGPoint(x: rect.origin.x, y: rect.height / 2),
size: CGSize(width: rect.size.width, height: rect.size.height / 2)
)
UIColor.red.set()
guard let context = UIGraphicsGetCurrentContext() else { return }
context.fill(bottomRect)
}
}
let view = CustomView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
PlaygroundPage.current.liveView = view

MacOS: Custom NSView won't show subviews

I have a View Controller and added a Subview to its View. The class of the Subview should also have some Subviews etc. Here is my code of my custom Class:
import Foundation
import Cocoa
class PercentageShower: NSView {
let percentageBar = NSView()
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
self.wantsLayer = true
self.layer?.backgroundColor = CGColor.black
let testsubview = NSView(frame: frameRect)
testsubview.wantsLayer = true
testsubview.layer?.backgroundColor = CGColor.init(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
self.addSubview(testsubview)
}
required init?(coder decoder: NSCoder) {
super.init(coder: decoder)
}
}
This is the ViewControllers code:
class Basics1ViewController: NSViewController {
let percentageShower = PercentageShower()
override func viewDidLoad() {
super.viewDidLoad()
// Set screen mesurements:
let screen = NSScreen.main
let screenWidth = (screen?.frame.width)!
let screenHeight = (screen?.frame.height)!
// Set Percentage View
percentageShower.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
self.view.addSubview(percentageShower)
}
}
This is just an example, but why isn't my red colored subview shown? I can see the black colored view itself but not it's subview. Looking forward to your help!

customize UIPageControl dots

I'm currently trying to customize the UIPageControl so it will fit my needs. However I seem to be having a problem when implementing some logic in the draw
What I want to do is to be able to user IBInspectable variables to draw out the UIPageControl however those seem to still be nil when the draw method is being called and when I try to implement my logic in the awakeFromNib for instance it won't work.
What I did so far is the following
class BoardingPager: UIPageControl {
#IBInspectable var size: CGSize!
#IBInspectable var borderColor: UIColor!
#IBInspectable var borderWidth: CGFloat! = 1
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.pageIndicatorTintColor = UIColor.clear
}
override func draw(_ rect: CGRect) {
super.draw(rect)
setDots()
}
func setDots() {
for i in (0..<self.numberOfPages) {
let dot = self.subviews[i]
if size != nil {
let dotFrame = CGRect(x: size.width/2, y: size.height/2, width: size.width, height: size.height)
dot.frame = dotFrame
}
if i != self.currentPage {
dot.layer.cornerRadius = dot.frame.size.height / 2
dot.layer.borderColor = borderColor.cgColor
dot.layer.borderWidth = borderWidth
}
}
}
}
Another problem I'm facing is that I want to remove/add a border when the current page changes.
I'm hoping someone will be able to help me out

How do you subclass UIView and add another UIView inside of it with the same frame

Hi I am trying to create a custom loading bar view by subclassing UIView. I want to create one UIView with a fixed frame, and another UIView that is inside of it. When I initialize the inner UIView, with the frame passed in by this method override init(frame: CGRect), the two views have different origins. I want the two views to be directly on top of each other to start out. I also want to be able to update the innerBar by calling this uploadBar.setLoadingPercentage(percent: 53.5)
Here is the code:
Creating the UploadBar
let uploadBar = UploadBar(frame: CGRect(x: 40, y: 40, width: 400, height: 40))
view.addSubview(uploadBar)
Subclassing UploadBar
import UIKit
class UploadBar: UIView {
var innerBar: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.white
innerBar = UIView(frame: frame)
innerBar.backgroundColor = UI.customBlue()
addSubview(innerBar)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setLoadingPercentage(percent: Double) {
// change innerBar's frame and redraw
}
}
For your inner view, you only require the width and height from the parent rect. The x and y should be zero relative to the parent view:
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.white
let innerRect = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
innerBar = UIView(frame: innerRect)
innerBar.backgroundColor = UI.customBlue()
addSubview(innerBar)
}