From ab286307c335fb8efea12d339424e41e81856fe5 Mon Sep 17 00:00:00 2001 From: Daniel Burgess Date: Mon, 22 Aug 2016 10:46:32 -0400 Subject: [PATCH] Fix a bug causing keyboard view offset to be incorrect (#204) * Fix a bug causing keyboard view offset to be incorrect In some rare cases, if the height of the view is a fractional point (i.e., not a whole number), it would cause the views to not be offset despite the keyboard being shown on top of them. This does not happen with every fractional height. Different devices also behave a little differently in seemingly identical layouts, due to their pixel density being different. The base issue is that, due to floating point rounding errors, two values that _should_ be identical and pass the guard fail to do so, because the lack of precision results in them not being equal. By flooring the values, we can ignore really minor differences and ensure rounding errors don't cause this issue. * Unify bma_round methods to use correct calculation Thanks to @diegosanchezr for the suggested improvement. * Revert ChattoAdditions bma_round change Unfortunately, removing this in favor of the Chatto version broke size calculations, so putting it back... * Switch to using infix operator to check float comparison * Add utils to Chatto project --- Chatto/Chatto.xcodeproj/project.pbxproj | 4 +++ .../Collaborators/KeyboardTracker.swift | 2 +- Chatto/Source/Utils.swift | 32 +++++++++++++++++++ ChattoApp/Pods/Pods.xcodeproj/project.pbxproj | 4 +++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 Chatto/Source/Utils.swift diff --git a/Chatto/Chatto.xcodeproj/project.pbxproj b/Chatto/Chatto.xcodeproj/project.pbxproj index 0eb8a17..ce89096 100644 --- a/Chatto/Chatto.xcodeproj/project.pbxproj +++ b/Chatto/Chatto.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + B3B1B0FF1D6B40DF00D1183D /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B1B0FE1D6B40DF00D1183D /* Utils.swift */; }; C31E919A1BFF4CA300339585 /* BaseChatViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31E91991BFF4CA300339585 /* BaseChatViewControllerTests.swift */; }; C321C3961BE78835009803D1 /* CollectionChangesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C321C3951BE78835009803D1 /* CollectionChangesTests.swift */; }; C321DDA91BE9649F00DE88CC /* BaseChatItemPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C321DD941BE9649F00DE88CC /* BaseChatItemPresenter.swift */; }; @@ -48,6 +49,7 @@ /* Begin PBXFileReference section */ 55E85D821BE390BE001885AD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B3B1B0FE1D6B40DF00D1183D /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; C31E91991BFF4CA300339585 /* BaseChatViewControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseChatViewControllerTests.swift; sourceTree = ""; }; C321C3951BE78835009803D1 /* CollectionChangesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionChangesTests.swift; sourceTree = ""; }; C321DD941BE9649F00DE88CC /* BaseChatItemPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseChatItemPresenter.swift; sourceTree = ""; }; @@ -188,6 +190,7 @@ C3E905041BE0521700C662A2 /* Info.plist */, C342D0C01C638A2C008A4605 /* ReadOnlyOrderedDictionary.swift */, C36281EC1BF10086004D6BCE /* SerialTaskQueue.swift */, + B3B1B0FE1D6B40DF00D1183D /* Utils.swift */, C321DD931BE9649F00DE88CC /* Chat Items */, C3E904AE1BE0509E00C662A2 /* ChatController */, ); @@ -349,6 +352,7 @@ C36281EB1BF0F62F004D6BCE /* DummyChatItemPresenter.swift in Sources */, C3C7C3981CAC4BAC00A49929 /* ChatCollectionViewLayout.swift in Sources */, C3C7C39B1CAC4BAC00A49929 /* KeyboardTracker.swift in Sources */, + B3B1B0FF1D6B40DF00D1183D /* Utils.swift in Sources */, C342D0C11C638A2C008A4605 /* ReadOnlyOrderedDictionary.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Chatto/Source/ChatController/Collaborators/KeyboardTracker.swift b/Chatto/Source/ChatController/Collaborators/KeyboardTracker.swift index 51a9a98..6d42a6d 100644 --- a/Chatto/Source/ChatController/Collaborators/KeyboardTracker.swift +++ b/Chatto/Source/ChatController/Collaborators/KeyboardTracker.swift @@ -121,7 +121,7 @@ class KeyboardTracker { guard let rect = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() else { return 0 } guard rect.height > 0 else { return 0 } let rectInView = self.view.convertRect(rect, fromView: nil) - guard rectInView.maxY >= self.view.bounds.height else { return 0 } // Undocked keyboard + guard rectInView.maxY >=~ self.view.bounds.height else { return 0 } // Undocked keyboard return max(0, self.view.bounds.height - rectInView.minY - self.keyboardTrackerView.intrinsicContentSize().height) } diff --git a/Chatto/Source/Utils.swift b/Chatto/Source/Utils.swift new file mode 100644 index 0000000..b3f4885 --- /dev/null +++ b/Chatto/Source/Utils.swift @@ -0,0 +1,32 @@ +/* + The MIT License (MIT) + + Copyright (c) 2015-present Badoo Trading Limited. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +import Foundation + +private let scale = UIScreen.mainScreen().scale + +infix operator >=~ { } +func >=~ (lhs: CGFloat, rhs: CGFloat) -> Bool { + return round(lhs * scale) >= round(rhs * scale) +} diff --git a/ChattoApp/Pods/Pods.xcodeproj/project.pbxproj b/ChattoApp/Pods/Pods.xcodeproj/project.pbxproj index a667f10..a848555 100644 --- a/ChattoApp/Pods/Pods.xcodeproj/project.pbxproj +++ b/ChattoApp/Pods/Pods.xcodeproj/project.pbxproj @@ -66,6 +66,7 @@ AF937EAD0FD4F9788305ABD479F421A4 /* PhotosInputDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA74C6FA4698B48048CEF5C23B4D60FF /* PhotosInputDataProvider.swift */; }; B073E3DCBE4C1EAED2510C69D07A0D3B /* ExpandableTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96828BB92772CE300432BA86B596C687 /* ExpandableTextView.swift */; }; B1577264ED188FAC450DD92F624A2A6E /* PhotosInputCellProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3963A79061EE854E9B5C277DA6221143 /* PhotosInputCellProvider.swift */; }; + B377A57F1D68EC1A000CDED8 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = B377A57E1D68EC1A000CDED8 /* Utils.swift */; }; B48B02953333C95136DDA71CA56C9271 /* BaseChatItemPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C09AD9E0C73B2D8A414CFEFF5030462C /* BaseChatItemPresenter.swift */; }; B7E8E79188BA84E1E762C4DE0D543EFC /* SerialTaskQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD5EF621D4C97159780FBA704E1E7EE /* SerialTaskQueue.swift */; }; BB474BC0BBC8D55868A7734879874EAF /* BaseMessageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96402187D4C05CEFBCD217A5B52D41CE /* BaseMessageViewModel.swift */; }; @@ -195,6 +196,7 @@ AF5BD772CABAA008A4802F6B3A73307E /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B20598F484478DFEE1B31B07C6FA131F /* Pods-ChattoApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ChattoApp.release.xcconfig"; sourceTree = ""; }; B2DC506829E1BD918CEAF95D49131A91 /* PhotoMessageCollectionViewCellDefaultStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PhotoMessageCollectionViewCellDefaultStyle.swift; sourceTree = ""; }; + B377A57E1D68EC1A000CDED8 /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; B7FB07C7AA705C13B7F2884D8C4E4D52 /* PhotoMessageCollectionViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PhotoMessageCollectionViewCell.swift; sourceTree = ""; }; BA74C6FA4698B48048CEF5C23B4D60FF /* PhotosInputDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PhotosInputDataProvider.swift; sourceTree = ""; }; BB0F5037D43B05A9DB436F3D3E86BB28 /* BaseMessageCollectionViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BaseMessageCollectionViewCell.swift; sourceTree = ""; }; @@ -457,6 +459,7 @@ 583960CE463732577E956CF9184EA67C /* Chatto.h */, 84AE77E2DC8C81FA8C4ABB08CEF0A2C4 /* ReadOnlyOrderedDictionary.swift */, ADD5EF621D4C97159780FBA704E1E7EE /* SerialTaskQueue.swift */, + B377A57E1D68EC1A000CDED8 /* Utils.swift */, 80E8B3FFDB227A27832B4096E95169D8 /* Chat Items */, AEFF9D5C30902A421C4BC13E21B200C8 /* ChatController */, ); @@ -923,6 +926,7 @@ FF617A66DF56CFD5A7F3CD5304CD4AB9 /* ChatItemProtocolDefinitions.swift in Sources */, 1293F88DD2651FCAFE9468D3172AE4CD /* Chatto-dummy.m in Sources */, F438D6015DC57DA1095E60F73CCA5593 /* CollectionChanges.swift in Sources */, + B377A57F1D68EC1A000CDED8 /* Utils.swift in Sources */, 8AF84B9A19DF824F0F7905B1F0296E7B /* DummyChatItemPresenter.swift in Sources */, EFF30D10A961BF864CDA109C126EA611 /* KeyboardTracker.swift in Sources */, 3AB11E8EAF8141F7F0A1E2D93FC4F37F /* ReadOnlyOrderedDictionary.swift in Sources */,