No Description

RNCSafeAreaView.m 2.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Simplified version of https://github.com/facebook/react-native/blob/master/React/Views/SafeAreaView/RCTSafeAreaView.m
  2. #import "RNCSafeAreaView.h"
  3. #import <React/RCTBridge.h>
  4. #import <React/RCTUIManager.h>
  5. static BOOL UIEdgeInsetsEqualToEdgeInsetsWithThreshold(UIEdgeInsets insets1, UIEdgeInsets insets2, CGFloat threshold) {
  6. return
  7. ABS(insets1.left - insets2.left) <= threshold &&
  8. ABS(insets1.right - insets2.right) <= threshold &&
  9. ABS(insets1.top - insets2.top) <= threshold &&
  10. ABS(insets1.bottom - insets2.bottom) <= threshold;
  11. }
  12. @implementation RNCSafeAreaView
  13. {
  14. UIEdgeInsets _currentSafeAreaInsets;
  15. BOOL _initialInsetsSent;
  16. }
  17. - (BOOL)isSupportedByOS
  18. {
  19. return [self respondsToSelector:@selector(safeAreaInsets)];
  20. }
  21. - (UIEdgeInsets)realOrEmulateSafeAreaInsets
  22. {
  23. #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
  24. if (self.isSupportedByOS) {
  25. if (@available(iOS 11.0, *)) {
  26. return self.safeAreaInsets;
  27. }
  28. }
  29. #endif
  30. return self.emulatedSafeAreaInsets;
  31. }
  32. - (UIEdgeInsets)emulatedSafeAreaInsets
  33. {
  34. UIViewController* vc = self.reactViewController;
  35. if (!vc) {
  36. return UIEdgeInsetsZero;
  37. }
  38. CGFloat topLayoutOffset = vc.topLayoutGuide.length;
  39. CGFloat bottomLayoutOffset = vc.bottomLayoutGuide.length;
  40. CGRect safeArea = vc.view.bounds;
  41. safeArea.origin.y += topLayoutOffset;
  42. safeArea.size.height -= topLayoutOffset + bottomLayoutOffset;
  43. CGRect localSafeArea = [vc.view convertRect:safeArea toView:self];
  44. UIEdgeInsets safeAreaInsets = UIEdgeInsetsMake(0, 0, 0, 0);
  45. if (CGRectGetMinY(localSafeArea) > CGRectGetMinY(self.bounds)) {
  46. safeAreaInsets.top = CGRectGetMinY(localSafeArea) - CGRectGetMinY(self.bounds);
  47. }
  48. if (CGRectGetMaxY(localSafeArea) < CGRectGetMaxY(self.bounds)) {
  49. safeAreaInsets.bottom = CGRectGetMaxY(self.bounds) - CGRectGetMaxY(localSafeArea);
  50. }
  51. return safeAreaInsets;
  52. }
  53. - (void)safeAreaInsetsDidChange
  54. {
  55. [self invalidateSafeAreaInsets];
  56. }
  57. - (void)invalidateSafeAreaInsets
  58. {
  59. UIEdgeInsets safeAreaInsets = [self realOrEmulateSafeAreaInsets];
  60. if (_initialInsetsSent && UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) {
  61. return;
  62. }
  63. _initialInsetsSent = YES;
  64. _currentSafeAreaInsets = safeAreaInsets;
  65. self.onInsetsChange(@{
  66. @"insets": @{
  67. @"top": @(safeAreaInsets.top),
  68. @"right": @(safeAreaInsets.right),
  69. @"bottom": @(safeAreaInsets.bottom),
  70. @"left": @(safeAreaInsets.left),
  71. }
  72. });
  73. }
  74. - (void)layoutSubviews
  75. {
  76. [super layoutSubviews];
  77. [self invalidateSafeAreaInsets];
  78. }
  79. @end