How to make a NSTextView scrollable ?
Problem:
Text View is displayed but is not scrollable. I have to resize the window to see more contents
Question:
How to make the text view scrollable.
Code:
class ViewController: NSViewController {
private let textView = NSTextView()
//MARK: Manage Views
override func viewDidLoad() {
super.viewDidLoad()
setupTextView()
}
private func setupTextView() {
textView.isEditable = false
view.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false
textView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
textView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
textView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}
NSTextView doesn't scroll, place the text view inside a NSScrollView. Class method scrollableTextView() of NSTextView returns a NSTextView in a NSScrollView.
private var textView:NSTextView?
private func setupTextView() {
let scrollView = NSTextView.scrollableTextView()
textView = scrollView.documentView as? NSTextView
textView?.isEditable = false
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
Related
I have 2 textfields as subViews of a contentView and the contentView is a subView of a scrollView. The textfields appear with no issue.But the problem I am having is when I tap or select the textfield to enter text neither a keyboard appears or the blue cursor, the textfields placeholder remains there. Is there something wrong with my constraints? How can I get the keyboard to appear and edit the text?
class SignInViewController: UIViewController {
private let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
private let contentView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let emailOrPhoneTextField: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Email or Phone Number"
textField.textAlignment = .center
textField.backgroundColor = .red
return textField
}()
private let passwordTextField: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Password"
textField.backgroundColor = .yellow
return textField
}()
override func viewDidLoad() {
super.viewDidLoad()
setupScrollView()
setupTextFields()
}
}
extension SignInViewController{
private func setupScrollView(){
view.addSubview(scrollView)
scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollView.addSubview(contentView)
contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
}
private func setupTextFields(){
contentView.addSubview(emailOrPhoneTextField)
contentView.addSubview(passwordTextField)
emailOrPhoneTextField.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
emailOrPhoneTextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 25).isActive = true
emailOrPhoneTextField.widthAnchor.constraint(equalTo: contentView.widthAnchor).isActive = true
emailOrPhoneTextField.heightAnchor.constraint(equalToConstant: 44).isActive = true
passwordTextField.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
passwordTextField.topAnchor.constraint(equalTo: emailOrPhoneTextField.bottomAnchor, constant: 25).isActive = true
passwordTextField.widthAnchor.constraint(equalTo: contentView.widthAnchor).isActive = true
passwordTextField.heightAnchor.constraint(equalToConstant: 44).isActive = true
}
}
Try this and check if it works:
extension ViewController{
private func setupScrollView(){
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(emailOrPhoneTextField)
contentView.addSubview(passwordTextField)
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor)
])
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.rightAnchor.constraint(equalTo: scrollView.rightAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
])
NSLayoutConstraint.activate([
emailOrPhoneTextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 50),
emailOrPhoneTextField.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
emailOrPhoneTextField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
])
NSLayoutConstraint.activate([
passwordTextField.topAnchor.constraint(equalTo: emailOrPhoneTextField.bottomAnchor, constant: 25),
passwordTextField.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
passwordTextField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
])
}
}
I have created a scroll view and I have tried many different methods as you can see below, however I always get the same outcome where the scroll view moves horizontally. I want it to move vertically, but it is not. Also, the text view shows the entire message in one line and does not use multiple lines as was happening before I added the scroll view.
import UIKit
import SafariServices
class MainView: UIViewController {
let transition = MainDropMenuAnimation()
let scrollView = UIScrollView()
let scrollViewView = UIView()
let factView = QuickFact()
let socialMediaSV = SocialMediaSV()
let logo = UIImageView()
let aboutUs = UITextView()
let dropMenuButton = UIButton(type: .custom)
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(patternImage: #imageLiteral(resourceName: "HomeBackground"))
addQuickFactView()
setupScrollView()
setupNavBar()
}
func setupNavBar() {
navigationItem.title = "Home"
navigationController?.navigationBar.barTintColor = .clear
dropMenuButton.setImage(#imageLiteral(resourceName: "dropMenuButton"), for: .normal)
dropMenuButton.addTarget(self, action: #selector(handleDropMenu), for: .touchUpInside)
dropMenuButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
dropMenuButton.widthAnchor.constraint(equalTo: dropMenuButton.heightAnchor).isActive = true
let leftButton = UIBarButtonItem(customView: dropMenuButton)
self.navigationItem.leftBarButtonItem = leftButton
}
#objc func handleDropMenu() {
let dropMenu = DropViewContainer()
dropMenu.modalPresentationStyle = .overCurrentContext
dropMenu.transitioningDelegate = self
present(dropMenu, animated: true)
}
func addQuickFactView() {
addChild(factView)
view.addSubview(factView.view)
factView.didMove(toParent: self)
factView.view.translatesAutoresizingMaskIntoConstraints = false
factView.view.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
factView.view.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
factView.view.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
factView.view.heightAnchor.constraint(equalToConstant: 200).isActive = true
}
func setupScrollView() {
setupView()
scrollView.contentSize.height = 3000
view.addSubview(scrollView)
positionScrollView()
}
func positionScrollView() {
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: factView.view.bottomAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
func setupView() {
setupLogo()
setupAboutUs()
setupSocialMediaSV()
scrollView.addSubview(scrollViewView)
positionView()
}
func positionView() {
scrollViewView.translatesAutoresizingMaskIntoConstraints = false
scrollViewView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
scrollViewView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
scrollViewView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
scrollViewView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
}
func setupLogo() {
logo.image = #imageLiteral(resourceName: "Logo")
scrollViewView.addSubview(logo)
positionLogo()
}
func positionLogo() {
logo.translatesAutoresizingMaskIntoConstraints = false
logo.widthAnchor.constraint(equalToConstant: 200).isActive = true
logo.heightAnchor.constraint(equalToConstant: 200).isActive = true
logo.centerXAnchor.constraint(equalTo: scrollViewView.centerXAnchor).isActive = true
logo.topAnchor.constraint(equalTo: scrollViewView.topAnchor, constant: 20).isActive = true
}
func setupAboutUs() {
let aboutUsText = (NSMutableAttributedString(string: "About Us\n", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 25)]))
aboutUsText.append(NSMutableAttributedString(string: "At Cleaner Together, we are commited to promoting recycling, reusing, and reducing (and of course composting), while spreading sanitization and cleanliness around the world. At the moment, we are just encouraging proper waste disposal, however with proper funding we have many projects we hope to accomplish.", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17), NSAttributedString.Key.foregroundColor: UIColor.black]))
aboutUs.attributedText = aboutUsText
aboutUs.textColor = .black
aboutUs.textAlignment = .left
aboutUs.isScrollEnabled = false
aboutUs.isEditable = false
aboutUs.backgroundColor = .init(white: 1.0, alpha: 0.5)
aboutUs.layer.cornerRadius = 20
scrollViewView.addSubview(aboutUs)
positionAboutUs()
}
func positionAboutUs() {
aboutUs.translatesAutoresizingMaskIntoConstraints = false
aboutUs.rightAnchor.constraint(equalTo: scrollViewView.rightAnchor, constant: -20).isActive = true
aboutUs.leftAnchor.constraint(equalTo: scrollViewView.leftAnchor, constant: 20).isActive = true
aboutUs.heightAnchor.constraint(equalToConstant: 200).isActive = true
aboutUs.topAnchor.constraint(equalTo: logo.bottomAnchor, constant: 20).isActive = true
}
func setupSocialMediaSV() {
addChild(socialMediaSV)
scrollViewView.addSubview(socialMediaSV.view)
socialMediaSV.didMove(toParent: self)
socialMediaSV.view.translatesAutoresizingMaskIntoConstraints = false
socialMediaSV.view.centerXAnchor.constraint(equalTo: scrollViewView.centerXAnchor).isActive = true
socialMediaSV.view.widthAnchor.constraint(equalToConstant: 240).isActive = true
socialMediaSV.view.topAnchor.constraint(equalTo: aboutUs.bottomAnchor, constant: 20).isActive = true
socialMediaSV.view.heightAnchor.constraint(equalToConstant: 40).isActive = true
}
}
extension MainView: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
transition.isPresenting = true
return transition
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
transition.isPresenting = false
return transition
}
}
You should check your constraints and make sure that your scroll view has correct contentSize.
Make scrollViewView left and right anchors also equalTo viewController's view. In func positionView()
I want to set my view to be a UITableView without adding to the main view, that is I don't want to call self.view.addSubview(tableView)
However, my loadView() does not seem to be working - the position and size of the tableView are ambiguous...
override func loadView() {
super.loadView()
let tv = UITableView(frame: self.view.frame)
tv.backgroundColor = Constants.Colors.translucentLightGrey
tv.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tv.dataSource = self
tv.delegate = self
tv.backgroundColor = .red
view = tv
tableView = tv
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true
tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -0).isActive = true
tableView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
}
How can I set the tableview as the view?
I am setting textfied and a button programmatically. The button is showing when we run the code but not textfield. is there any problem with constraints or any other please help.
let submitButton: UIButton = {
let btn = UIButton(type:.system)
btn.backgroundColor = .blue
btn.setTitle("Login", for: .normal)
btn.tintColor = .white
btn.layer.cornerRadius = 5
btn.clipsToBounds = true
btn.translatesAutoresizingMaskIntoConstraints = false
return btn
}()
let textBox: UITextView = {
let textView = UITextView()
textView.text = "we are learning iOs"
textView.font = UIFont.boldSystemFont(ofSize: 18)
textView.textAlignment = .center
textView.translatesAutoresizingMaskIntoConstraints = false
return textView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(textBox)
setupTexBoxLayout()
view.addSubview(submitButton)
setupSubmitBUttonLayout()
}
private func setupTexBoxLayout(){
textBox.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
textBox.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
textBox.widthAnchor.constraint(equalToConstant: 100).isActive = true
}
private func setupSubmitBUttonLayout(){
submitButton.topAnchor.constraint(equalTo: textBox.bottomAnchor, constant: 100).isActive = true
submitButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 100).isActive = true
}
}
I have checked your code and debug it.
You have not specified height for textview so it is not showing it.
You can check the below code. I have added height constraint to it and it is displaying your textfield.
If you do not specify a height for textfield then it will take 0 height by default.
private func setupTexBoxLayout(){
textBox.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
textBox.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
textBox.widthAnchor.constraint(equalToConstant: 300).isActive = true
textBox.heightAnchor.constraint(equalToConstant: 40).isActive = true
}
My UILabel is pinned to the top of the cell, just like UIImage but if the text below has f.e. 1 line (its also in UILabel) my top UILabel is in other place.
Here are my constraints and labels declaration. Thanks to anyone who will try to solve my problem :) I tried using sizeToFit method on my UILabels
var albumImage: UIImageView = {
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
view.contentMode = .scaleAspectFit
return view
}()
var albumName: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.numberOfLines = 0
view.sizeToFit()
return view
}()
var bandName: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.sizeToFit()
return view
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
drawLayout()
}
required init?(coder aDecoder: NSCoder) {
fatalError("ERROR")
}
func drawLayout(){
let guide = self.safeAreaLayoutGuide
//albumImage
addSubview(albumImage)
addSubview(albumName)
addSubview(bandName)
albumImage.heightAnchor.constraint(equalToConstant: 50).isActive = true
albumImage.widthAnchor.constraint(equalToConstant: 50).isActive = true
albumImage.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 8).isActive = true
albumImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 8).isActive = true
albumImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8).isActive = true
//albumTitle
albumName.topAnchor.constraint(equalTo: bandName.bottomAnchor).isActive = true
albumName.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8).isActive = true
albumName.leadingAnchor.constraint(equalTo: albumImage.trailingAnchor, constant: 8).isActive = true
albumName.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: -8).isActive = true
//bandName
bandName.topAnchor.constraint(equalTo: albumImage.topAnchor).isActive = true
bandName.leadingAnchor.constraint(equalTo: albumImage.trailingAnchor, constant: 8).isActive = true
}