调整视图大小时 textview 抖动

Posted

技术标签:

【中文标题】调整视图大小时 textview 抖动【英文标题】:textview shakes when resizing view 【发布时间】:2017-01-07 16:40:17 【问题描述】:

我正在调整 textview 所属视图的大小,当视图变大或变小时,文本会抖动。

上述文本视图的声明:

lazy var textview: UITextView = 
        let textView = UITextView()
        textView.text = ""
        textView.font = .systemFont(ofSize: 12, weight: UIFontWeightMedium)
        textView.isScrollEnabled = false
        textView.isEditable = false
        textView.isSelectable = true
        textView.isUserInteractionEnabled = true
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.textAlignment = .center
        textView.textColor = .lightGray
        textView.dataDetectorTypes = .link
        return textView
    ()

我正在调整视图的大小以适应这样的全屏

if let window = UIApplication.shared.keyWindow  
    let statusBarHeight = UIApplication.shared.statusBarFrame.size.height

    UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveLinear, animations: 

        self.frame = CGRect(x: 0, y: statusBarHeight, width: window.frame.width, height: window.frame.height - statusBarHeight)

        self.layer.cornerRadius = 0

        self.layoutIfNeeded()

    , completion: nil)

这样做后,视图会完美展开,但 textviews 文本会产生反弹效果,使动画看起来非常不专业......有什么建议吗?

编辑:似乎当我删除中心文本对齐选项时它工作正常。如何使它与对齐的文本中心一起工作?

【问题讨论】:

这不是问题的原因,但请注意您的代码没有意义。你为什么要更改框架调用layoutIfNeeded @matt 删除 layoutIfNeeded 会使动画变得松散平滑。我不知道为什么。谢谢 @matt 我应该删除 textviews 约束,为框架设置动画......然后读取它们吗?一切都很好,只是 textviews 文本产生了奇怪的弹跳效果 【参考方案1】:

编辑:我再次查看并尝试使用基于UIScrollView animation of height and contentOffset "jumps" content from bottom 的技术。

这是一个最小的工作示例,带有居中文本对齐的文本视图,对我有用!

我建议管理动画要么全部基于约束,要么全部基于帧。我尝试了一个版本,其中动画是通过更新容器视图框架来驱动的,但是在这种基于约束的方法中离开它开始花费太长时间。

希望这会为您指明正确的方向:)

import UIKit

class ViewController: UIViewController 

    lazy var textView: UITextView = 
        let textView = UITextView()
        textView.text = "testing text view"
        textView.textAlignment = .center
        textView.translatesAutoresizingMaskIntoConstraints = false
        return textView
    ()

    lazy var containerView: UIView = 
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    ()

    var widthConstraint: NSLayoutConstraint!
    var topAnchor: NSLayoutConstraint!

    override func viewDidLoad() 

        view.backgroundColor = .groupTableViewBackground

        // add container view and constraints
        view.addSubview(containerView)
        containerView.frame = view.bounds.insetBy(dx: 100, dy: 200)
        containerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        containerView.heightAnchor.constraint(equalToConstant: 100).isActive = true

        // keep reference to topAnchor and width as properties to animate
        topAnchor = containerView.topAnchor.constraint(lessThanOrEqualTo: view.topAnchor, constant: 100)
        widthConstraint = containerView.widthAnchor.constraint(equalToConstant: 300)
        topAnchor.isActive = true
        widthConstraint.isActive = true

        // add text view to container view and set constraints
        containerView.addSubview(textView)
        textView.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true
        textView.rightAnchor.constraint(equalTo: containerView.rightAnchor).isActive = true
        textView.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
        textView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
    

    @IBAction func toggleResize(_ sender: UIButton) 

        sender.isSelected = !sender.isSelected

        view.layoutIfNeeded()
        widthConstraint.constant = sender.isSelected ? view.bounds.width : 300
        topAnchor.constant = sender.isSelected ? 20 : 100

        // caculate the textView content offset for starting position based on
        // expected end position at end of the animation
        let xOffset = (textView.bounds.width - widthConstraint.constant) / 2
        textView.contentOffset = CGPoint(x: -xOffset, y: textView.contentOffset.y)

        UIView.animate(withDuration: 1) 
            self.view.layoutIfNeeded()
        
    

【讨论】:

离开self.layoutIfNeeded() 时更改动画不会改变任何内容。然后,删除 self.layoutIfNeeded() 不会使 textview 反弹,但整体动画看起来很笨拙......让它变得更糟......根本不流畅。还有其他想法吗?谢谢@MathewS 我正在更新的框架属于一个视图,其中包含一个文本视图和许多其他视图...我看不出如何不更改视图的大小而只更改文本视图会解决这个问题 我正在更新一个视图以占据整个框架,并且其中的 textview 正在调整大小......它只是有反弹效果......我不想有反弹效果,但实际上只是调整最外层视图的大小,并让内部视图根据约束自行调整大小 请使用附加代码更新您的问题,以提供有关正在发生的事情的更多上下文,目前这还不是一个足够完整的示例来理解正在发生的事情 我提供了所有相关代码。我有一个占用一些空间的视图。它有一个 textview、imageview ......里面有一些按钮。当我调整该视图的大小时......如上面的代码......一切都很顺利,除了textview中的文本反弹......因为它调整大小......我不确定提供哪些其他代码可能会有所帮助也许整个项目哈哈

以上是关于调整视图大小时 textview 抖动的主要内容,如果未能解决你的问题,请参考以下文章

在自动调整 TextView 大小时输入文本时 UITableView 闪烁/口吃

如何根据动态内容调整 textview 和 scrollview 内容大小

动态添加文本后Textview不调整大小?

如何调整textview的大小以不超出屏幕

在 ConstraintLayout 中自动调整多行文本视图的大小

如何根据应用程序小部件中文本视图中的小部件大小调整文本大小?