TextView dynamic height and y-coordinate is not working - swift

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

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)

Swift 5: centerXAnchor won't center my frame in the view

I'm stuck at the Consolidation IV challenge from hackingwithswift.com.
Right now I'm trying to create a hangman game. I thought to place placeholder labels based on the length of the answer word. These placeholder labels would be placed inside a frame, which then would be placed in the center of the main view.
Unfortunately, the leading edge of the frame is placed centered. In my opinion, this is not a problem of constraints, but rather a problem of me creating the frame wrong.
My current code is
import UIKit
class ViewController: UIViewController {
var answer: String!
override func viewDidLoad() {
super.viewDidLoad()
// MARK: - declare all the labels here
let letterView = UIView()
letterView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(letterView)
// MARK: - set constraints to all labels, buttons etc.
NSLayoutConstraint.activate([
letterView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
letterView.centerXAnchor.constraint(equalTo: view.layoutMarginsGuide.centerXAnchor)
])
// MARK: - populate the letterView
// set the size of the placeholder
answer = "Atmosphäre"
let height = 60
let width = 25
// var width: Int
for placeholder in 0..<answer.count {
// create new label and give it a big font size
let placeholderLabel = UILabel()
placeholderLabel.text = "_"
placeholderLabel.font = UIFont.systemFont(ofSize: 36)
// calculate frame of this label
let frame = CGRect(x: placeholder * width, y: height, width: width, height: height)
placeholderLabel.frame = frame
// add label to the label view
letterView.addSubview(placeholderLabel)
}
}
}
The simulator screen looks just like this:
I already searched for answers on stackoverflow, but wasn't successful. I think I don't know what I'm exactly looking for.
The main problem, is that the letterView has no size, because no width or height constraints are applied to it.
To fix your code make the letterView big enough to contain the labels you've added as subviews by adding height and width constraints after the for loop:
for placeholder in 0..<answer.count {
...
}
NSLayoutConstraint.activate([
letterView.widthAnchor.constraint(equalToConstant: CGFloat(width * answer.count)),
letterView.heightAnchor.constraint(equalToConstant: CGFloat(height))
])
I'm not sure if you've covered this in your course yet, but a better way to go about this (which would take much less code), is to use a UIStackView as your letterView instead.
An extra thing to consider:
If you give the letterView a background color, you'll see that the labels are actually aligned outside of its bounds:
That's because you're setting each label's y position to be height, when it should probably be zero:
let frame = CGRect(x: placeholder * width, y: 0, width: width, height: height)
Correcting this places the labels within the bounds of the letterView:

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 add labels within a view programmatically

I'm experimenting with layout anchors, and I'm trying to replicate the following illustration: basically an outer view with an inner view. The inner view is anchored with constants to the outer view's bottom anchor and the leading anchor. This much is done.
However, I would then like to place a label inside the inner view, and be able to center the label/s in that view. Is this possible?
Ideally I could then go an alter the constants of the view later on, and the labels would still be correctly positioned.
Just some pointers in the right direction would be useful.
First create the view.
let innerView = UIView()
Then the labels.
let label1 = UILabel()
let label2 = UILabel()
Place the inner view inside the main view
view.addSubview(innerView)
After you add the innerView to the view.
You can provide a position and size to the inner view.
innerView.frame = CGRect(x: (self.view.frame.size.width) - (self.view.frame.size.width) + 10, y: (self.view.frame.size.height) - (self.view.frame.size.height) - 150, width: 500, height: 500)
Then add in the labels into the inner view
innerView.addSubview(label1)
innerView.addSubview(label2)
Then you can apply constraints to the labels inside the inner view and give it size
label1.frame = CGRect(x:100, y: 100, width: 200, height: 20)
label2.frame = CGRect(x:100, y: 100, width: 200, height: 20)
The quick pointer is to use UIStackView with
stack.addArrangedSubview(lbl)
distribution = fill
alignment = center
axis = vertical
You may also need to set lbl's alignment = center

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.