ios - 垂直 ScrollView 不滚动(无情节提要)
问题描述
我需要帮助创建没有情节提要的滚动视图。这是我设置滚动视图的代码;我没有设置滚动视图的 contentSize,因为我希望滚动视图内容大小是动态的,取决于 TextView 中的文本量。我所做的是尝试将“contentView”添加到 Scroll View 并将我的所有 UI 元素添加到 contentView。任何帮助,将不胜感激。
import Foundation
import UIKit
import UITextView_Placeholder
class ComposerVC: UIViewController {
private var scrollView: UIScrollView = {
let scrollView = UIScrollView(frame: UIScreen.main.bounds)
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
private var contentView: UIView = {
let content = UIView()
content.translatesAutoresizingMaskIntoConstraints = false
return content
}()
private var title: UITextView = {
let title = UITextView()
title.translatesAutoresizingMaskIntoConstraints = false
title.placeholder = "Untitled"
title.textColor = UIColor(hexString: "#50E3C2")
title.font = UIFont(name: "Rubik-BoldItalic", size: 32)
title.backgroundColor = .clear
title.isScrollEnabled = false
return title
}()
private var divider: UIView = {
let divider = UIView()
divider.translatesAutoresizingMaskIntoConstraints = false
divider.backgroundColor = UIColor(hexString: "#50E3C2")
return divider
}()
private var content: UITextView = {
let title = UITextView()
title.translatesAutoresizingMaskIntoConstraints = false
title.placeholder = "Begin writing here..."
title.textColor = .white
title.font = UIFont(name: "Avenir-Book", size: 15)
title.backgroundColor = .clear
title.isScrollEnabled = false
return title
}()
override func viewDidLoad() {
setupUI()
setupUIConstraints()
title.delegate = self
}
private func setupUI() {
view.backgroundColor = UIColor(hexString: "#131415")
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(title)
contentView.addSubview(divider)
contentView.addSubview(content)
}
private func setupUIConstraints() {
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
title.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 95).isActive = true
title.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35).isActive = true
title.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35).isActive = true
divider.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 15).isActive = true
divider.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
divider.heightAnchor.constraint(equalToConstant: 1).isActive = true
divider.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.8).isActive = true
content.topAnchor.constraint(equalTo: divider.bottomAnchor, constant: 15).isActive = true
content.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35).isActive = true
content.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35).isActive = true
}
}
extension ComposerVC: UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
}
}
解决方案
几个提示:
- 不要将现有名称用于变量...按原样使用代码
private var title: UITextView
会导致问题(title
已经是视图控制器属性)。 - 使用暗示对象的 var 名称...例如
titleTextView
andcontentTextView
而不是title
andcontent
- 在开发过程中 - 特别是在您处理布局时 - 为您的 UI 元素提供对比背景颜色,以便您可以在运行时轻松查看它们的框架。
- 使用代码创建的视图时,设置
.clipsToBounds = true
...如果您没有看到您添加的任何子视图,您就知道框架/约束缺少某些东西。
我没有你的UITextView_Placeholder
导入,但这不应该影响这里的任何东西......
因此,首先,将您的更改viewDidLoad()
为:
override func viewDidLoad() {
setupUI()
setupUIConstraints()
titleTextView.delegate = self
// contrasting colors during development
scrollView.backgroundColor = .red
titleTextView.backgroundColor = .yellow
contentTextView.backgroundColor = .green
divider.backgroundColor = .blue
contentView.backgroundColor = .cyan
}
当你运行它时,你应该看到(滚动视图背景是红色的,这是没有占位符的东西):
它看起来是正确的,除了没有 cyan-colored contentView
。
现在,剪辑以下子视图contentView
:
private var contentView: UIView = {
let content = UIView()
content.translatesAutoresizingMaskIntoConstraints = false
// add this line
content.clipsToBounds = true
return content
}()
结果:
一切都去哪儿了?好吧,我们没有看到青色contentView
,现在我们没有看到它的任何子视图......如果我们使用Debug View Hierarchy
,我们可以发现contentView
高度为零。
通过约束第二个文本视图的底部来解决这个问题setupUIConstraints()
(我已将其重命名为contentTextView
而不是 just content
):
contentTextView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -95).isActive = true
我们得到:
现在青色的高度contentView
由其子视图的正确设置约束控制。
附带说明:正确设置约束并禁用文本视图的滚动,您不需要:
extension ComposerVC: UITextViewDelegate {
//func textViewDidChange(_ textView: UITextView) {
//...
//}
}
文本视图将自动调整其文本大小:
这是完整的编辑代码:
class ComposerVC: UIViewController {
private var scrollView: UIScrollView = {
let scrollView = UIScrollView(frame: UIScreen.main.bounds)
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
private var contentView: UIView = {
let content = UIView()
content.translatesAutoresizingMaskIntoConstraints = false
// add this line so we know if the constraints are set correctly
content.clipsToBounds = true
return content
}()
private var titleTextView: UITextView = {
let title = UITextView()
title.translatesAutoresizingMaskIntoConstraints = false
// title.placeholder = "Untitled"
title.textColor = UIColor(hexString: "#50E3C2")
title.font = UIFont(name: "Rubik-BoldItalic", size: 32)
title.backgroundColor = .clear
title.isScrollEnabled = false
return title
}()
private var divider: UIView = {
let divider = UIView()
divider.translatesAutoresizingMaskIntoConstraints = false
divider.backgroundColor = UIColor(hexString: "#50E3C2")
return divider
}()
private var contentTextView: UITextView = {
let title = UITextView()
title.translatesAutoresizingMaskIntoConstraints = false
// title.placeholder = "Begin writing here..."
title.textColor = .white
title.font = UIFont(name: "Avenir-Book", size: 15)
title.backgroundColor = .clear
title.isScrollEnabled = false
return title
}()
override func viewDidLoad() {
setupUI()
setupUIConstraints()
titleTextView.delegate = self
// contrasting colors during development
scrollView.backgroundColor = .red
titleTextView.backgroundColor = .yellow
contentTextView.backgroundColor = .green
divider.backgroundColor = .blue
contentView.backgroundColor = .cyan
}
private func setupUI() {
view.backgroundColor = UIColor(hexString: "#131415")
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(titleTextView)
contentView.addSubview(divider)
contentView.addSubview(contentTextView)
}
private func setupUIConstraints() {
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
titleTextView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 95).isActive = true
titleTextView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35).isActive = true
titleTextView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35).isActive = true
divider.topAnchor.constraint(equalTo: titleTextView.bottomAnchor, constant: 15).isActive = true
divider.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
divider.heightAnchor.constraint(equalToConstant: 1).isActive = true
divider.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.8).isActive = true
contentTextView.topAnchor.constraint(equalTo: divider.bottomAnchor, constant: 15).isActive = true
contentTextView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35).isActive = true
contentTextView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35).isActive = true
contentTextView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -95).isActive = true
}
}
extension ComposerVC: UITextViewDelegate {
// func textViewDidChange(_ textView: UITextView) {
// let fixedWidth = textView.frame.size.width
// let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
// textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
// }
}
推荐阅读
- reactjs - 无法从 combineReducer 获取另一个组件中的更新状态值
- hyperledger-iroha - 在不同的服务器上运行 Iroha 多个节点
- php - 如何删除 vscode 中 php 类中的“}”预期错误。我使用了这些代码
- java - 使用 Java 登录 Sharepoint 时连接重置
- php - 云上的卡蒙达
- javascript - 如何使用 javascript 删除具有云功能的 Firestore 集合
- oracle-sqldeveloper - 显示 EMPLOYEE 表中的 MAX 和 2nd MAX SALARY
- webstorm - Webstorm - 如何禁用“dfn”快捷方式?
- javascript - unsubscribe() 在这个 firebase auth 示例中做了什么?
- javascript - Vuetify,如何通过 v-data-table 中的双击事件获取行