草庐IT

ios - 当键盘可见时更改 Y 原点时出现奇怪的 UIView 行为

coder 2023-09-05 原文

上下文:

我有一个包含 UITextView 的 UIView。我想在键盘可见时向上移动 UIView。所以想法是change the Y position .

问题:

有时,当键盘仍然可见时,UIView 会返回到其初始 Y 位置。即使我专注于输入,它也不会再回来了。我真的不知道为什么。

插图 (gif):

https://d17oy1vhnax1f7.cloudfront.net/items/2K0z3P1j1x2f0X2X1B2v/ci.gif

PS:键盘在Gif中出现了3次。它是循环的,所以很难区分结束。

代码

我做了什么,首先我添加了通知观察者:

NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChangeFrame), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)

然后我定义了键盘切换处理程序:

func keyboardWillChangeFrame(notification: NSNotification) {

    let info = notification.userInfo!
    let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

    self.keyboardInfo["isVisible"] = self.view.frame.size.height - keyboardFrame.origin.y != 0
    self.keyboardInfo["height"] = keyboardFrame.size.height
    self.keyboardInfo["animationDuration"] = info[UIKeyboardAnimationDurationUserInfoKey] as! Double
    self.keyboardInfo["animationCurve"] = info[UIKeyboardAnimationCurveUserInfoKey] as! UInt

    if self.keyboardInfo["isVisible"] as! Bool {
        self.moveCommentInputUp()
    } else {
        self.moveCommentInputDown()
    }

}

之后,我定义了将评论输入 View 向上/向下移动的方法:

func moveCommentInputUp() {

    print("Moving up... ", self.commentFormView.frame.origin.y, " to ", self.view.frame.size.height - (self.keyboardInfo["height"] as! CGFloat) - self.commentFormView.frame.size.height)

    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(self.keyboardInfo["animationDuration"] as! TimeInterval)
    UIView.setAnimationCurve(UIViewAnimationCurve(rawValue: Int(self.keyboardInfo["animationCurve"] as! UInt))!)
    UIView.setAnimationBeginsFromCurrentState(true)

    ViewUtil.changeViewFrame(view: self.commentFormView, yPosition: self.view.frame.size.height - (self.keyboardInfo["height"] as! CGFloat) - self.commentFormView.frame.size.height)
    ViewUtil.removeShadowToView(self.commentFormLauncherButton)

    UIView.commitAnimations()

}

func moveCommentInputDown() {

    print("Moving down... ", self.commentFormView.frame.origin.y, " to ", self.view.frame.size.height)

    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(self.keyboardInfo["animationDuration"] as! TimeInterval)
    UIView.setAnimationCurve(UIViewAnimationCurve(rawValue: Int(self.keyboardInfo["animationCurve"] as! UInt))!)
    UIView.setAnimationBeginsFromCurrentState(true)

    ViewUtil.changeViewFrame(view: self.commentFormView, yPosition: self.view.frame.size.height)
    ViewUtil.addShadowToView(commentFormLauncherButton, position: CGSize(width: 0, height: 5))

    UIView.commitAnimations()

}

按钮的 Action 是

@IBAction func showCommentForm(_ sender: UIButton) {

    self.commentInput.becomeFirstResponder()

}

日志(请参阅 Gif)显示 View 从 568(屏幕底部)再次移动到 568

// The numbers show the initial and the final value of the keyboard Y position

// Click on button to focus the input
Moving up...  568.0  to  282.0
// Tap anywhere
Moving down...  282.0  to  568.0

// Click again on button to focus the input
Moving up...  568.0  to  282.0
///// Write "hhh". The view is gone, I don't know why.
// Tap anywhere
Moving down...  568.0  to  568.0    // The view seems to move from 568 to 568, hugh

// Click on button to focus the input
Moving up...  568.0  to  282.0      // This didn't work apparently
// Tap anywhere
Moving down...  568.0  to  568.0    // 568 to 568 again

我错过了什么吗?

系统:iOS 9、Xcode 8、Swift 3

最佳答案

好的,这是一个不需要 CocoaPods 的解决方案。

我的方法涉及在键盘出现和消失时设置 textField 底部约束的常量。这意味着您需要创建对文本字段底部约束的引用。

@IBOutlet weak var textFieldBottomConstraint: NSLayoutConstraint!

我开始在 viewDidLoad 中设置 NSNotification.Name.UIKeyboardWillShow 和 UIKeyboardWillHide 的观察者,而不是 UIKeyboardWillChangeFrame:

NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

接下来我设置选择器及其函数来设置文本字段底部约束的常量:

func handleKeyboardNotification(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let keyboardFrameValue = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)
        let keyboardFrame = keyboardFrameValue?.cgRectValue

        let isKeyboardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow

        textFieldBottomConstraint.constant = isKeyboardShowing ? keyboardFrame!.height + 4 : 4
        self.view.layoutIfNeeded()
    }
}

请注意,textFieldBottomConstraint 是底部约束的引用变量。

这样做的目的是让 textField 在键盘出现或消失时设置它的底部约束,并且不会遇到您遇到的奇怪故障。

希望这对您有所帮助,请不要犹豫,要求澄清!

致谢 YouTuber 让我们构建该应用程序吧!通过此视频提供解决方案:

https://www.youtube.com/watch?v=p8IaS5lmhuM

关于ios - 当键盘可见时更改 Y 原点时出现奇怪的 UIView 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39604177/

有关ios - 当键盘可见时更改 Y 原点时出现奇怪的 UIView 行为的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  3. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  4. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  5. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  6. ruby - 在 Ruby 中用键盘诅咒数组浏览 - 2

    我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作

  7. ruby - 即时确定方法的可见性 - 2

    我正在编写一个方法,它将在一个类中定义一个实例方法;类似于attr_accessor:classFoocustom_method(:foo)end我通过将custom_method函数添加到Module模块并使用define_method定义方法来实现它,效果很好。但我无法弄清楚如何考虑类(class)的可见性属性。例如,在下面的类中classFoocustom_method(:foo)privatecustom_method(:bar)end第一个生成的方法(foo)必须是公共(public)的,第二个(bar)必须是私有(private)的。我怎么做?或者,如何找到调用我的cust

  8. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  9. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  10. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

随机推荐