RPSystemBroadcastPickerView subviews odd behaviour when initial size not set - swift

I have view with RPSystemBroadcastPickerView view. In documentation apple shows example with assigning frame to this view like so:
https://developer.apple.com/documentation/replaykit/rpsystembroadcastpickerview?language=objc
When set frame + constraints, works as expected:
picker = RPSystemBroadcastPickerView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
but if i do initialize RPSystemBroadcastPickerView like this:
picker = RPSystemBroadcastPickerView()
subviews doesn't display properly.
Constraints for both cases:
picker.translatesAutoresizingMaskIntoConstraints = false
pickerViewContainerView.addSubview(picker)
picker.widthAnchor.constraint(equalTo: pickerViewContainerView.widthAnchor).isActive = true
picker.heightAnchor.constraint(equalTo: pickerViewContainerView.heightAnchor).isActive = true
picker.leadingAnchor.constraint(equalTo: pickerViewContainerView.leadingAnchor).isActive = true
picker.topAnchor.constraint(equalTo: pickerViewContainerView.topAnchor).isActive = true
Do i have to set initial frame for this view? Because usually if you create and position view using constraints you don't have to assign initial frame.
Can somebody explain this behavior please?
Thanks.

Yes, you have to set the initial frame. You can check the width and height when you instantiate without initial frame.
picker = RPSystemBroadcastPickerView()
print("Height : \(picker.frame.height)") // this will print as 0.0
print("Width : \(picker.frame.width)") // this will print as 0.0
Since, the picker view is of height and width 0.0 x 0.0, it is not visible and is not working
With the initial frame the width and height prints 50.0 x 50.0 and visible.
picker = RPSystemBroadcastPickerView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
print("Height : \(picker.frame.height)") // this will print as 50.0
print("Width : \(picker.frame.width)") // this will print as 50.0
That is why in the Apple Developer Documentation they suggested to use initial frame.

Related

Broken inline datePicker as InputView for TextField Swift iOS 14

I use new inline Date Picker that is available from iOS 13.4 as inputView for Text Field(before I used wheels). However, it looks broken as the height of inputView is constant: How it looks
I have tried changing the frame and disable AutoResizingMaskIntoConstraints. It didn't help. The way it should work is like a default inline datePicker. How dataPicker should look like
To sum up, I need to increase the height of custom InputView for UITextField.
I Guess it was limited by default height of inputView.
Just change the Size of it then works.
// You can change value as you want. I think same with screen width is better for me.
let scrWidth = UIScreen.main.bounds.width
textfield.inputView?.frame.size = CGSize(width: scrWidth, height: scrWidth)
// Changing CGRect also can work
textfieldinputView?.frame = CGRect(x: 0, y: 0, width: scrWidth , height: scrWidth)
Result like this
Interesting, when I tested on SE1, it showed up as normal without using above method, and the inputView size was 320*353.3
inputView on SE1
But the height of other devices larger than it will limited to some value (IDK what is the reference.)
The limitation here was 355.666667, and the size would be 414*355.6667
inputView on 11 Pro Max
So that's why I guess dataPicker just get cropped when scaled up.
let scrWidth = UIScreen.main.bounds.width
textField.inputView?.frame.size = CGSize(width: scrWidth, height: scrWidth + 50)
datePicker.frame = CGRect(x: 0, y: 0, width: scrWidth , height: scrWidth + 50)

How can i get the absolute position of an UISlider inside of a View

i have created a subview with a lot sliders in it
var sliderArea = UIView()
sliderArea = UIView(frame: CGRect(x: 300, y: 400, width: 500, height: 100)
view.addSubview(sliderArea)
mySlider1 = setUpSlider(sliderNr: 1, ypos: 30)
mySlider2 = setUpSlider(sliderNr: 2, ypos: 30)
mySlider3 = setUpSlider(sliderNr: 3, ypos: 30)
sliderArea.addSubview(mySlider1)
sliderArea.addSubview(mySlider2)
sliderArea.addSubview(mySlider3)
i have a lot of subviews similar to the "sliderArea" to be able to change my sliders quickly while the layout adopts automatically
now i need to know where the absolute position of each slider is to place buttons on top of it. i need to have all this buttons inside an extra view on top of it all. any ideas? thank you
You should convert your slider frame to window's coordinate system using this method of CGRect:
https://developer.apple.com/documentation/uikit/uiview/1622504-convert
Just pass nil as second parameter and it will return you an absolute frame.

How to make a stretchable header view collection view [Swift]

In my swift app I've a collection view and I want to creare a stretchable header view like this in table view: https://medium.com/if-let-swift-programming/how-to-create-a-stretchable-tableviewheader-in-ios-ee9ed049aba3
You already answered your question yourself with that article link, unless I miss something.
I will copy & paste for you and others that may have the same question, if it helps, because it even ships with a github link (kudos to Abhimuralidharan # Medium):
Create a tableview with the basic datasource and delegate methods which are required to simply load the table with some data.
Set the tableview’s contentInset property:
tableView.contentInset = UIEdgeInsetsMake(300, 0, 0, 0)
Here, I set the top value as 300 which is a calculated number which I will set as the initial normal height for the header imageview. Now, that we set the contentInset , the tableview’s frame will start at (0,0) and the first cell will start at (0,300).
Now, create an imageview with height 300 and add it to the current View above the tableview.
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 300)
imageView.image = UIImage.init(named: “poster”)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
view.addSubview(imageView)
Then, add the following code in the scrollview delegate method scrollViewDidScroll which gets called every time the tableview is scrolled.
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)
}
Compile and run the code. Full source code is available in github.

TextView dynamic height and y-coordinate is not working

Hello I am working on textview. I have a set content for it with attributed text. Based on which screen it will be played the textview height should be adjusted to fit screen width, I am using the frame as
mytextView.frame = CGrect(x: 0, y: 800, width: view.bounds.width, height: .greatestFiniteMagnitude)
the textview height is adjusted accordingly but I have two issues
1) textview always place at the top of the view and mixed up with other labels. I want the x:0 & y:800 for the textView
2) how to determine the modified height of the textview so as to set the constraint for scrollview (I don't want the textview to scroll, i.e. a fixed height to its contentsize)
please let me know why the frame x and y are not working?
thanks
thanks for the help joe, I did find an answer,
I changed in the viewdidload as
mytextView.frame = CGrect(x: 0, y: 800, width: view.bounds.width, height: 200)
and mytextView.isScrollenable = false
so that viewcontroller calculate what should be the actual height of the mytextView
and in
viewdidlayoutsubviews
i used contentsize to adjust the height of mytestView, also I used this height to determine what should be the scrolling height scrollView

NSAnimationContext does not animate frame size for NSButton

Using NSAnimationContext.runAnimationGroup(_:_:) as demonstrated in the NSAnimationContext documentation to animate both the frame origin and size works as expected for some view types (including NSImageView). However, it does not work as expected for an NSButton unless I add an explicit frame size change after the animation
Animating frame size for NSImageView
The following works as expected for an NSImageView. It is moved to the origin, and resized to 200x200:
NSAnimationContext.runAnimationGroup({(let context) -> Void in
context.duration = 2.0
// Get the animator for an NSImageView
let a = self.theImage.animator()
// Move and resize the NSImageView
a.frame = NSRect(x: 0, y: 0, width: 200, height: 200)
}) {
print("Animation done")
}
Animating frame size for NSButton
When performing the same with an NSButton, the button will move but not resize:
NSAnimationContext.runAnimationGroup({(let context) -> Void in
context.duration = 2.0
// Get the animator for an NSButton
let a = self.button.animator()
// Move and resize the NSImageView
a.frame = NSRect(x: 0, y: 0, width: 200, height: 200)
}) {
print("Animation done")
}
However, if I add the following line of code to the end, after all of the animation code, it works as expected!
self.button.frame = NSRect(x: 0, y: 0, width: 200, height: 200)
The final, working listing for NSButton is:
NSAnimationContext.runAnimationGroup({(let context) -> Void in
context.duration = 2.0
// Get the animator for an NSButton
let a = self.button.animator()
// Move and resize the NSImageView
a.frame = NSRect(x: 0, y: 0, width: 200, height: 200)
}) {
print("Animation done")
}
self.button.frame = NSRect(x: 0, y: 0, width: 200, height: 200)
I'm not looking a gift horse in the mouth here, but I don't understand why this is required for NSButton, or even what makes it work. Can anyone explain why explicitly setting the frame of the NSButton after the animation code makes the animation work?
I suspect this has something to do with implicit autolayout constraints being generated at runtime. After modifying the frame, the autolayout simply reverts it back to the original size.
I abandoned the original approach in favor of the following:
Create width and/or height constraints in Interface Builder. I use the default priority of 1000 (constraint is mandatory).
Create an outlet for the width and/or height NSLayoutConstraint. This was tricky in IB: I had to double-click the constraint in the measurements tab of the inspector which then opened the constraint object in the inspector. Then you can select the connections tab and connect the outlet.
In my NSViewController subclass I use anchors to define the new height or width: theWidthConstraint.constant = 200 followed by self.view.needsUpdateConstraints = true
This approach is much cleaner and more compatible with the autolayout system. In addition, it makes it easy to animate the entire layout change that results from the new autolayout:
NSAnimationContext.runAnimationGroup({(let context) -> Void in
context.duration = 1.0
self.theWidthConstraint.animator().constant = 200
// Other constraint modifications can go here
}) {
print("Animation done")
}