tha*_*ris 155 uitextview ios autolayout nslayoutconstraint
我有一个完全使用自动布局编程的视图.我在视图中间有一个UITextView,上面和下面有项目.一切正常,但我希望能够在添加文本时扩展UITextView.当它扩展时,它应该将其下面的所有内容都推下来.
我知道如何以"弹簧和支柱"的方式做到这一点,但是有一种自动布局方式吗?我能想到的唯一方法是每次需要增长时删除并重新添加约束.
vit*_*ter 543
摘要:禁用文本视图的滚动,并且不限制其高度.
要以编程方式执行此操作,请将以下代码放入viewDidLoad
:
let textView = UITextView(frame: .zero, textContainer: nil)
textView.backgroundColor = .yellow // visual debugging
textView.isScrollEnabled = false // causes expanding height
view.addSubview(textView)
// Auto Layout
textView.translatesAutoresizingMaskIntoConstraints = false
let safeArea = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
textView.topAnchor.constraint(equalTo: safeArea.topAnchor),
textView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor),
textView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor)
])
Run Code Online (Sandbox Code Playgroud)
要在Interface Builder中执行此操作,请选择文本视图,取消选中"属性"检查器中的"滚动已启用",然后手动添加约束.
注意:如果您在文本视图的上方/下方有其他视图,请考虑使用a UIStackView
来安排所有视图.
Mic*_*lis 40
对于喜欢通过自动布局完成所有操作的人来说,这是一个解决方案:
在尺寸检查器中:
将内容压缩阻力优先级设置为1000.
通过单击约束中的"编辑"来降低约束高度的优先级.只需使它低于1000.
在属性检查器中:
小智 39
UITextView不提供intrinsicContentSize,因此您需要对其进行子类化并提供一个.要使其自动增长,请使layoutSubviews中的intrinsicContentSize无效.如果您使用默认contentInset以外的任何内容(我不建议这样做),您可能需要调整intrinsicContentSize计算.
@interface AutoTextView : UITextView
@end
Run Code Online (Sandbox Code Playgroud)
#import "AutoTextView.h"
@implementation AutoTextView
- (void) layoutSubviews
{
[super layoutSubviews];
if (!CGSizeEqualToSize(self.bounds.size, [self intrinsicContentSize])) {
[self invalidateIntrinsicContentSize];
}
}
- (CGSize)intrinsicContentSize
{
CGSize intrinsicContentSize = self.contentSize;
// iOS 7.0+
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f) {
intrinsicContentSize.width += (self.textContainerInset.left + self.textContainerInset.right ) / 2.0f;
intrinsicContentSize.height += (self.textContainerInset.top + self.textContainerInset.bottom) / 2.0f;
}
return intrinsicContentSize;
}
@end
Run Code Online (Sandbox Code Playgroud)
anc*_*jic 27
包含UITextView的视图将setBounds
通过AutoLayout 分配其大小.所以,这就是我所做的.superview最初设置了应有的所有其他约束,最后我为UITextView的高度设置了一个特殊约束,并将其保存在实例变量中.
_descriptionHeightConstraint = [NSLayoutConstraint constraintWithItem:_descriptionTextView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0.f
constant:100];
[self addConstraint:_descriptionHeightConstraint];
Run Code Online (Sandbox Code Playgroud)
在该setBounds
方法中,我然后更改了常量的值.
-(void) setBounds:(CGRect)bounds
{
[super setBounds:bounds];
_descriptionTextView.frame = bounds;
CGSize descriptionSize = _descriptionTextView.contentSize;
[_descriptionHeightConstraint setConstant:descriptionSize.height];
[self layoutIfNeeded];
}
Run Code Online (Sandbox Code Playgroud)
小智 15
我发现在你可能仍然需要将isScrollEnabled设置为true以允许合理的UI交互的情况下,这并不完全不常见.一个简单的例子就是当你想允许自动扩展文本视图但仍然将它的最大高度限制在UITableView中的合理范围内时.
这是我提出的UITextView的子类,它允许使用自动布局进行自动扩展,但是你仍然可以约束到最大高度,并根据高度管理视图是否可滚动.默认情况下,如果您以这种方式设置约束,视图将无限扩展.
import UIKit
class FlexibleTextView: UITextView {
// limit the height of expansion per intrinsicContentSize
var maxHeight: CGFloat = 0.0
private let placeholderTextView: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.backgroundColor = .clear
tv.isScrollEnabled = false
tv.textColor = .disabledTextColor
tv.isUserInteractionEnabled = false
return tv
}()
var placeholder: String? {
get {
return placeholderTextView.text
}
set {
placeholderTextView.text = newValue
}
}
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
isScrollEnabled = false
autoresizingMask = [.flexibleWidth, .flexibleHeight]
NotificationCenter.default.addObserver(self, selector: #selector(UITextInputDelegate.textDidChange(_:)), name: Notification.Name.UITextViewTextDidChange, object: self)
placeholderTextView.font = font
addSubview(placeholderTextView)
NSLayoutConstraint.activate([
placeholderTextView.leadingAnchor.constraint(equalTo: leadingAnchor),
placeholderTextView.trailingAnchor.constraint(equalTo: trailingAnchor),
placeholderTextView.topAnchor.constraint(equalTo: topAnchor),
placeholderTextView.bottomAnchor.constraint(equalTo: bottomAnchor),
])
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var text: String! {
didSet {
invalidateIntrinsicContentSize()
placeholderTextView.isHidden = !text.isEmpty
}
}
override var font: UIFont? {
didSet {
placeholderTextView.font = font
invalidateIntrinsicContentSize()
}
}
override var contentInset: UIEdgeInsets {
didSet {
placeholderTextView.contentInset = contentInset
}
}
override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize
if size.height == UIViewNoIntrinsicMetric {
// force layout
layoutManager.glyphRange(for: textContainer)
size.height = layoutManager.usedRect(for: textContainer).height + textContainerInset.top + textContainerInset.bottom
}
if maxHeight > 0.0 && size.height > maxHeight {
size.height = maxHeight
if !isScrollEnabled {
isScrollEnabled = true
}
} else if isScrollEnabled {
isScrollEnabled = false
}
return size
}
@objc private func textDidChange(_ note: Notification) {
// needed incase isScrollEnabled is set to true which stops automatically calling invalidateIntrinsicContentSize()
invalidateIntrinsicContentSize()
placeholderTextView.isHidden = !text.isEmpty
}
}
Run Code Online (Sandbox Code Playgroud)
作为奖励,支持包含类似于UILabel的占位符文本.
fum*_*007 11
我看到多个答案建议直接关闭scrollEnabled
。这是最好的解决方案。我\xe2\x80\x99m 写这个答案是为了解释它为什么有效。
UITextView
intrinsicContentSize
仅当 时才实现该属性scrollEnabled == NO
。getter 方法的反汇编如下所示:
- (CGSize)intrinsicContentSize {\n if (self.scrollEnabled) {\n return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);\n } else {\n // Calculate and return intrinsic content size based on current width.\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n这意味着您只需要确保文本视图的宽度受到足够的限制,然后您可以通过自动布局内容拥抱/压缩阻力优先级或直接在手动布局期间使用该值来利用固有内容高度。
\n不幸的是,这种行为没有记录在案。Apple 可以轻松地为我们省去一些麻烦\xe2\x80\xa6,无需额外的高度限制、子类化等。
\n您也可以在没有子类化的情况下完成UITextView
.看看我如何根据iOS 7的内容调整UITextView的大小?
使用此表达式的值:
[textView sizeThatFits:CGSizeMake(textView.frame.size.width, CGFLOAT_MAX)].height
Run Code Online (Sandbox Code Playgroud)
更新constant
了的textView
的高度UILayoutConstraint
.
归档时间: |
|
查看次数: |
90480 次 |
最近记录: |