Fix layout issues in timeline poll cells (PSB-125)

Fixes: #5326
Signed-off-by: Johannes Marbach <johannesm@element.io>
This commit is contained in:
Johannes Marbach
2022-07-05 08:18:21 +02:00
parent 437b2eafd6
commit ecc8532319
3 changed files with 95 additions and 1 deletions
@@ -27,6 +27,16 @@ class VectorHostingController: UIHostingController<AnyView> {
var isNavigationBarHidden: Bool = false
var hidesBackTitleWhenPushed: Bool = false
var forceZeroSafeAreaInsets: Bool {
get {
self.view.forceZeroSafeAreaInsets
}
set {
self.view.forceZeroSafeAreaInsets = newValue
}
}
private var theme: Theme
// MARK: Public
@@ -43,6 +53,7 @@ class VectorHostingController: UIHostingController<AnyView> {
init<Content>(rootView: Content) where Content: View {
self.theme = ThemeService.shared().theme
super.init(rootView: AnyView(rootView.vectorContent()))
self.view.swizzleSafeAreaMethodsIfNeeded()
}
required init?(coder aDecoder: NSCoder) {
@@ -103,3 +114,83 @@ class VectorHostingController: UIHostingController<AnyView> {
}
}
}
// Hack for forcing zero safe area insets on hosting views. This problem occurs when the hosting view is embedded
// in a table view. See https://stackoverflow.com/questions/61552497 for further info.
private var hasSwizzledSafeAreaMethods = false
private var forceZeroSafeAreaInsetsKey: Void?
private extension UIView {
var forceZeroSafeAreaInsets: Bool {
get {
return objc_getAssociatedObject(self, &forceZeroSafeAreaInsetsKey) as? Bool == true
}
set {
objc_setAssociatedObject(self, &forceZeroSafeAreaInsetsKey, newValue, .OBJC_ASSOCIATION_RETAIN)
}
}
@objc private var _safeAreaInsets: UIEdgeInsets {
return forceZeroSafeAreaInsets ? .zero : self._safeAreaInsets
}
@objc private var _safeAreaLayoutGuide: UILayoutGuide? {
return forceZeroSafeAreaInsets ? nil : self._safeAreaLayoutGuide
}
func swizzleSafeAreaMethodsIfNeeded() {
guard !hasSwizzledSafeAreaMethods else {
return
}
hasSwizzledSafeAreaMethods = true
guard let getSafeAreaInsets = class_getInstanceMethod(classForCoder.self, #selector(getter: UIView.safeAreaInsets)) else {
return
}
guard let _getSafeAreaInsets = class_getInstanceMethod(classForCoder.self, #selector(getter: UIView._safeAreaInsets)) else {
return
}
let getSafeAreaInsetsImplementation = method_getImplementation(getSafeAreaInsets)
let _getSafeAreaInsetsImplementation = method_getImplementation(_getSafeAreaInsets)
class_replaceMethod(
classForCoder,
#selector(getter: UIView.safeAreaInsets),
_getSafeAreaInsetsImplementation,
method_getTypeEncoding(getSafeAreaInsets))
class_replaceMethod(
classForCoder,
#selector(getter: UIView._safeAreaInsets),
getSafeAreaInsetsImplementation,
method_getTypeEncoding(_getSafeAreaInsets))
guard let getSafeAreaLayoutGuide = class_getInstanceMethod(classForCoder.self, #selector(getter: UIView.safeAreaLayoutGuide)) else {
return
}
guard let _getSafeAreaLayoutGuide = class_getInstanceMethod(classForCoder.self, #selector(getter: UIView._safeAreaLayoutGuide)) else {
return
}
let getSafeAreaLayoutGuideImplementation = method_getImplementation(getSafeAreaLayoutGuide)
let _getSafeAreaLayoutGuideImplementation = method_getImplementation(_getSafeAreaLayoutGuide)
class_replaceMethod(
classForCoder,
#selector(getter: UIView.safeAreaLayoutGuide),
_getSafeAreaLayoutGuideImplementation,
method_getTypeEncoding(getSafeAreaLayoutGuide))
class_replaceMethod(
classForCoder,
#selector(getter: UIView._safeAreaLayoutGuide),
getSafeAreaLayoutGuideImplementation,
method_getTypeEncoding(_getSafeAreaLayoutGuide))
}
}