diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm index 8ecba0ffa4..ebba65437b 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm @@ -1550,6 +1550,23 @@ + (void)install CGFloat h = MAX(screenSize.width, screenSize.height); env->SetDeviceWidth(std::to_string(w)); env->SetDeviceHeight(std::to_string(h)); + + __block UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero; + #if __IPHONE_11_0 + if (@available(iOS 11.0, *)) { + WXPerformBlockSyncOnMainThread(^{ + safeAreaInsets = [UIApplication sharedApplication].windows[0].safeAreaInsets; + }); + } + #endif + env->SetSafeAreaInsets(WXSafeAreaInsets{ + .top = safeAreaInsets.top, + .bottom = safeAreaInsets.bottom, + .left = safeAreaInsets.left, + .right = safeAreaInsets.right + }); + + env->AddOption("screen_width_pixels", std::to_string(w)); env->AddOption("screen_height_pixels", std::to_string(h)); diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index 6caf13e3dd..755f92a112 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -207,6 +207,16 @@ + (NSDictionary *)getEnvironment CGFloat deviceHeight = [self portraitScreenSize].height; CGFloat scale = [[UIScreen mainScreen] scale]; + __block UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero; + +#if __IPHONE_11_0 + if (@available(iOS 11.0, *)) { + WXPerformBlockSyncOnMainThread(^{ + safeAreaInsets = [UIApplication sharedApplication].windows[0].safeAreaInsets; + }); + } +#endif + NSMutableDictionary *data = [NSMutableDictionary dictionaryWithDictionary:@{ @"platform":platform, @"osName":platform, //osName is eaqual to platorm name in native @@ -219,7 +229,8 @@ + (NSDictionary *)getEnvironment @"deviceHeight":@(deviceHeight * scale), @"scale":@(scale), @"layoutDirection": [self getEnvLayoutDirection] == WXLayoutDirectionRTL ? @"rtl" : @"ltr", - @"scheme": currentScheme + @"scheme": currentScheme, + @"safeArea": @{@"top":@(safeAreaInsets.top), @"bottom":@(safeAreaInsets.bottom), @"left":@(safeAreaInsets.left), @"right":@(safeAreaInsets.right)} }]; if ([[[UIDevice currentDevice] systemVersion] integerValue] >= 11) { diff --git a/weex_core/Source/core/common/view_utils.h b/weex_core/Source/core/common/view_utils.h index 008f96ac8a..1d9f594aa0 100644 --- a/weex_core/Source/core/common/view_utils.h +++ b/weex_core/Source/core/common/view_utils.h @@ -35,6 +35,9 @@ namespace WeexCore { constexpr char NONE[] = "none"; constexpr char STATUS_BAR_HEIGHT[] = "status_bar_height"; + constexpr char SAFE_AREA_PREFIX[] = "env(safe-area-inset-"; + constexpr char SAFE_AREA_SURFIX[] = ")"; + template inline std::string to_string(const T &n) { @@ -108,6 +111,11 @@ namespace WeexCore { src.compare(src.size() - suffix.size(), suffix.size(), suffix) == 0; } + inline bool startWidth(const std::string &src, const std::string &suffix) { + return src.size() > suffix.size() && + src.compare(0, suffix.size(), suffix) == 0; + } + inline float transferWx(const std::string &stringWithWXPostfix, const float &viewport, const float &device_width) { std::string temp = stringWithWXPostfix; @@ -119,6 +127,25 @@ namespace WeexCore { return density * f * viewport / device_width; } + inline float transferSafeArea(const std::string &stringWithSafeArea, const float &viewport, + const float &device_width) { + std::string flag = stringWithSafeArea.substr(strlen(SAFE_AREA_PREFIX), stringWithSafeArea.size() - strlen(SAFE_AREA_PREFIX) - strlen(SAFE_AREA_SURFIX)); + float f = 0; + + if (flag.compare("top") == 0) { + f = WXCoreEnvironment::getInstance()->SafeAreaInsets().top; + } else if (flag.compare("bottom") == 0) { + f = WXCoreEnvironment::getInstance()->SafeAreaInsets().bottom; + } else if (flag.compare("left") == 0) { + f = WXCoreEnvironment::getInstance()->SafeAreaInsets().left; + } else if (flag.compare("right") == 0) { + f = WXCoreEnvironment::getInstance()->SafeAreaInsets().right; + } + + float density = getFloat(WXCoreEnvironment::getInstance()->GetOption(SCALE).c_str()); + return density * f * viewport / device_width; +} + inline static float getFloatByViewport(std::string src, const float &viewport, const float &device_width, const bool &round_off_deviation) { float ret = NAN; @@ -133,7 +160,12 @@ namespace WeexCore { ret = getFloat(transferWx(src, viewport, device_width), viewport, device_width, round_off_deviation); } else if (endWidth(src, PX)) { ret = getFloat(src.substr(0, src.size() - strlen(PX)), viewport, device_width, round_off_deviation); - } else { + } + else if (startWidth(src, SAFE_AREA_PREFIX) && endWidth(src, SAFE_AREA_SURFIX)) { + ret = getFloat(transferSafeArea(src, viewport, device_width), viewport, device_width, round_off_deviation); + } + + else { ret = getFloat(src, viewport, device_width, round_off_deviation); } return ret; diff --git a/weex_core/Source/core/config/core_environment.cpp b/weex_core/Source/core/config/core_environment.cpp index 5645d72ba0..14d3fa04af 100644 --- a/weex_core/Source/core/config/core_environment.cpp +++ b/weex_core/Source/core/config/core_environment.cpp @@ -62,6 +62,11 @@ namespace WeexCore { return true; } + bool WXCoreEnvironment::SetSafeAreaInsets(WXSafeAreaInsets insets) { + mSafeAreaInsets = insets; + return true; + } + const float WXCoreEnvironment::DeviceWidth() { return mDeviceWidth; } @@ -70,6 +75,10 @@ namespace WeexCore { return mDeviceHeight; } + const WXSafeAreaInsets WXCoreEnvironment::SafeAreaInsets() { + return mSafeAreaInsets; + } + const std::string WXCoreEnvironment::GetOption(const std::string &key) { std::map::iterator iter = mOptions.find(key); if (iter != mOptions.end()) { diff --git a/weex_core/Source/core/config/core_environment.h b/weex_core/Source/core/config/core_environment.h index 08546c404f..deca362b53 100644 --- a/weex_core/Source/core/config/core_environment.h +++ b/weex_core/Source/core/config/core_environment.h @@ -24,6 +24,13 @@ namespace WeexCore { +struct WXSafeAreaInsets { + double top; + double bottom; + double left; + double right; +}; + class WX_EXPORT WXCoreEnvironment { private: @@ -51,6 +58,8 @@ namespace WeexCore { float mDeviceWidth; float mDeviceHeight; + + WXSafeAreaInsets mSafeAreaInsets; std::map mOptions; @@ -73,6 +82,8 @@ namespace WeexCore { bool SetDeviceWidth(const std::string &width); bool SetDeviceHeight(const std::string &height); + + bool SetSafeAreaInsets(WXSafeAreaInsets insets); inline void set_device_height(float height) { mDeviceHeight = height; @@ -89,6 +100,8 @@ namespace WeexCore { const float DeviceWidth(); const float DeviceHeight(); + + const WXSafeAreaInsets SafeAreaInsets(); const std::string GetOption(const std::string &key);