Skip to content
This repository has been archived by the owner on Jun 3, 2021. It is now read-only.

Commit

Permalink
Support orientation switch hot-layout. (#2512)
Browse files Browse the repository at this point in the history
* Support change orientation and relayout without reloading the whole page from js.

* Better support device orientation autorotate in Playground with demo http://editor.weex.io/p/wqyfavor/scroller/commit/37810078ef963388b699b5ad7d5e9881

* [iOS] Better use isKeepingRawCssStyles.
  • Loading branch information
wqyfavor authored and jianhan-he committed Jun 5, 2019
1 parent 7eaee85 commit 6cd5788
Show file tree
Hide file tree
Showing 24 changed files with 467 additions and 90 deletions.
6 changes: 0 additions & 6 deletions WeexSDK.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@ Pod::Spec.new do |s|
'weex_core/Source/base/base64',
'weex_core/Source/base/crash',
'weex_core/Source/base/utils',
'weex_core/Source/base/thread',
'weex_core/Source/base/third_party',
'weex_core/Source/base/message_loop',
'weex_core/Source/base/time_point.*',
'weex_core/Source/base/time_utils.*',
'weex_core/Source/base/time_unit.*',
'weex_core/Source/third_party/IPC',
'weex_core/Source/core/network/android/',
'weex_core/Source/include/JavaScriptCore/',
Expand Down
1 change: 1 addition & 0 deletions ios/playground/WeexDemo/AppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) NSString *latestVer;
@property (assign, nonatomic) BOOL allowRotation;

@end
10 changes: 10 additions & 0 deletions ios/playground/WeexDemo/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
return YES;
}

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (_allowRotation) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else {
return UIInterfaceOrientationMaskPortrait;
}
}

-(void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
{
if ([shortcutItem.type isEqualToString:QRSCAN]) {
Expand Down
2 changes: 2 additions & 0 deletions ios/playground/WeexDemo/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
Expand Down
37 changes: 37 additions & 0 deletions ios/playground/WeexDemo/WXDemoViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#import "DemoDefine.h"
#import "WXPrerenderManager.h"
#import "WXMonitor.h"
#import "AppDelegate.h"

@interface WXDemoViewController () <UIScrollViewDelegate, UIWebViewDelegate>
@property (nonatomic, strong) WXSDKInstance *instance;
Expand All @@ -52,6 +53,14 @@ - (instancetype)init
return self;
}

- (void)setInterfaceOrientation:(UIDeviceOrientation)orientation
{
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:orientation]
forKey:@"orientation"];
}
}

- (void)viewDidLoad
{
[super viewDidLoad];
Expand All @@ -71,6 +80,9 @@ - (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self updateInstanceState:WeexInstanceAppear];

AppDelegate* appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.allowRotation = _instance && [_instance isKeepingRawCssStyles];
}

- (void)viewDidDisappear:(BOOL)animated
Expand All @@ -79,6 +91,15 @@ - (void)viewDidDisappear:(BOOL)animated
[self updateInstanceState:WeexInstanceDisappear];
}

- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// restore to protrait
AppDelegate* appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.allowRotation = NO;
[self setInterfaceOrientation:UIDeviceOrientationPortrait];
}

- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
Expand Down Expand Up @@ -164,9 +185,13 @@ - (void)render
}
};

__weak WXSDKInstance* theInstance = _instance;
_instance.renderFinish = ^(UIView *view) {
WXLogDebug(@"%@", @"Render Finish...");
[weakSelf updateInstanceState:WeexInstanceAppear];

AppDelegate* appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.allowRotation = theInstance && [theInstance isKeepingRawCssStyles];
};

_instance.updateFinish = ^(UIView *view) {
Expand Down Expand Up @@ -250,6 +275,18 @@ - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error

}

# pragma mark - orientation

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if (_instance) {
CGFloat w = [UIScreen mainScreen].bounds.size.width;
CGFloat h = [UIScreen mainScreen].bounds.size.height;
[_instance setPageRequiredWidth:w height:h];
[_instance reloadLayout];
}
}

#pragma mark - localBundle
/*- (void)loadLocalBundle:(NSURL *)url
{
Expand Down
10 changes: 10 additions & 0 deletions ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,22 @@ namespace WeexCore
isWidthWrapContent:(BOOL)isWidthWrapContent
isHeightWrapContent:(BOOL)isHeightWrapContent;

// Set/Get GLOBAL device size which will affect all pages
+ (void)setDeviceSize:(CGSize)size;
+ (CGSize)getDeviceSize;

// DO NOT call this method directly, you should use WXSDKInstance
+ (void)setViewportWidth:(NSString*)pageId width:(CGFloat)width;

// DO NOT call this method directly, you should use WXSDKInstance
+ (void)setPageRequired:(NSString *)pageId width:(CGFloat)width height:(CGFloat)height;

+ (void)layoutPage:(NSString*)pageId forced:(BOOL)forced;

+ (void)closePage:(NSString*)pageId;

+ (BOOL)reloadPageLayout:(NSString*)pageId;

+ (void)layoutRenderObject:(void*)object size:(CGSize)size page:(NSString*)pageId;

+ (void*)copyRenderObject:(void*)source replacedRef:(NSString*)ref;
Expand Down Expand Up @@ -201,6 +207,10 @@ namespace WeexCore

+ (void)registerCoreEnv:(NSString*)key withValue:(NSString*)value;

+ (void)setPageArgument:(NSString*)pageId key:(NSString*)key value:(NSString*)value;

+ (BOOL)isKeepingRawCssStyles:(NSString*)pageId;

@end

#endif
60 changes: 44 additions & 16 deletions ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,12 @@ + (void)setDeviceSize:(CGSize)size
env->SetDeviceHeight(std::to_string(size.height));
}

+ (CGSize)getDeviceSize
{
WeexCore::WXCoreEnvironment* env = WeexCore::WXCoreEnvironment::getInstance();
return CGSizeMake(env->DeviceWidth(), env->DeviceHeight());
}

+ (void)setViewportWidth:(NSString*)pageId width:(CGFloat)width
{
if (platformBridge) {
Expand All @@ -1060,10 +1066,9 @@ + (void)setViewportWidth:(NSString*)pageId width:(CGFloat)width

+ (void)setPageRequired:(NSString *)pageId width:(CGFloat)width height:(CGFloat)height
{
/// Because env is global, pageId is not used now time.
WeexCore::WXCoreEnvironment* env = WeexCore::WXCoreEnvironment::getInstance();
env->SetDeviceWidth(std::to_string(width));
env->SetDeviceHeight(std::to_string(height));
if (platformBridge) {
platformBridge->core_side()->SetDeviceDisplayOfPage([pageId UTF8String] ?: "", (float)width, (float)height);
}
}

+ (void)layoutPage:(NSString*)pageId forced:(BOOL)forced
Expand All @@ -1087,6 +1092,14 @@ + (void)closePage:(NSString*)pageId
}
}

+ (BOOL)reloadPageLayout:(NSString*)pageId
{
if (platformBridge) {
return platformBridge->core_side()->RelayoutUsingRawCssStyles([pageId UTF8String] ?: "");
}
return false;
}

+ (void)_traverseTree:(WeexCore::RenderObject *)render index:(int)index pageId:(const char *)pageId
{
using namespace WeexCore;
Expand Down Expand Up @@ -1168,19 +1181,19 @@ + (void)removeRenderObjectFromMap:(NSString*)pageId object:(void*)object
}


+ (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:(WeexCore::RenderObject*)render
+ (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:(WeexCore::RenderObject*)render reserveStyles:(bool)reserveStyles
{
id data = styles[key];
if (data) {
ConvertToCString(data, ^(const char * value) {
if (value != nullptr) {
render->AddStyle([key UTF8String], value);
render->AddStyle([key UTF8String], value, reserveStyles);
}
});
}
}

+ (WeexCore::RenderObject*)_parseRenderObject:(NSDictionary *)data parent:(WeexCore::RenderObject *)parent index:(int)index pageId:(const std::string&)pageId
+ (WeexCore::RenderObject*)_parseRenderObject:(NSDictionary *)data parent:(WeexCore::RenderObject *)parent index:(int)index pageId:(const std::string&)pageId reserveStyles:(bool)reserveStyles
{
using namespace WeexCore;

Expand All @@ -1203,16 +1216,16 @@ + (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:

// margin/padding/borderWidth should be handled beforehand. Because maringLeft should override margin.
NSDictionary* styles = data[@"style"];
[self _parseStyleBeforehand:styles key:@"margin" render:render];
[self _parseStyleBeforehand:styles key:@"padding" render:render];
[self _parseStyleBeforehand:styles key:@"borderWidth" render:render];
[self _parseStyleBeforehand:styles key:@"margin" render:render reserveStyles:reserveStyles];
[self _parseStyleBeforehand:styles key:@"padding" render:render reserveStyles:reserveStyles];
[self _parseStyleBeforehand:styles key:@"borderWidth" render:render reserveStyles:reserveStyles];
[styles enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if ([key isEqualToString:@"margin"] || [key isEqualToString:@"padding"] || [key isEqualToString:@"borderWidth"]) {
return;
}
ConvertToCString(obj, ^(const char * value) {
if (value != nullptr) {
render->AddStyle([key UTF8String], value);
render->AddStyle([key UTF8String], value, reserveStyles);
}
});
}];
Expand All @@ -1227,10 +1240,10 @@ + (void)_parseStyleBeforehand:(NSDictionary *)styles key:(NSString *)key render:

int childIndex = 0;
for (NSDictionary* obj in data[@"children"]) {
[self _parseRenderObject:obj parent:render index:childIndex ++ pageId:pageId];
[self _parseRenderObject:obj parent:render index:childIndex ++ pageId:pageId reserveStyles:reserveStyles];
}

render->ApplyDefaultStyle();
render->ApplyDefaultStyle(reserveStyles);
render->ApplyDefaultAttr();

return render;
Expand All @@ -1255,8 +1268,9 @@ + (void)callAddElement:(NSString*)pageId parentRef:(NSString*)parentRef data:(NS
{
using namespace WeexCore;
const std::string page([pageId UTF8String] ?: "");
RenderObject* child = [self _parseRenderObject:data parent:nullptr index:0 pageId:page];
RenderManager::GetInstance()->AddRenderObject(page, [parentRef UTF8String] ?: "", index, child);
RenderManager::GetInstance()->AddRenderObject(page, [parentRef UTF8String] ?: "", index, [&] (RenderPage* pageInstance) -> RenderObject* {
return [self _parseRenderObject:data parent:nullptr index:0 pageId:page reserveStyles:pageInstance->reserve_css_styles()];
});
}

+ (void)callCreateBody:(NSString*)pageId data:(NSDictionary*)data
Expand All @@ -1267,7 +1281,7 @@ + (void)callCreateBody:(NSString*)pageId data:(NSDictionary*)data
pageInstance->set_before_layout_needed(false); // we do not need before and after layout
pageInstance->set_after_layout_needed(false);
pageInstance->set_platform_layout_needed(true);
return [self _parseRenderObject:data parent:nullptr index:0 pageId:page];
return [self _parseRenderObject:data parent:nullptr index:0 pageId:page reserveStyles:pageInstance->reserve_css_styles()];
});
}

Expand Down Expand Up @@ -1321,4 +1335,18 @@ + (void)registerCoreEnv:(NSString*)key withValue:(NSString*)value
WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->core_side()->RegisterCoreEnv([key UTF8String]?:"", [value UTF8String]?:"");
}

+ (void)setPageArgument:(NSString*)pageId key:(NSString*)key value:(NSString*)value
{
WeexCore::RenderManager::GetInstance()->setPageArgument([pageId UTF8String]?:"", [key UTF8String]?:"", [value UTF8String]?:"");
}

+ (BOOL)isKeepingRawCssStyles:(NSString*)pageId
{
RenderPage* page = RenderManager::GetInstance()->GetPage([pageId UTF8String] ?: "");
if (page == nullptr) {
return NO;
}
return page->reserve_css_styles();
}

@end
21 changes: 21 additions & 0 deletions ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,11 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code
**/
- (void)reload:(BOOL)forcedReload;

/**
* Refreshes current instance components' layout after setting custom view port/device width.
**/
- (void)reloadLayout;

/**
* Refreshes current instance with data.
*
Expand Down Expand Up @@ -350,11 +355,27 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code

@property (nonatomic ,strong) WXApmForInstance* apmInstance;

/**
* Raw css styles are dropped after applied to layout nodes in WeexCore.
* If a page needs hot refresh(without recreating instance and reload js) after screen orientation changes or
* after setting custom view-port-width/screen-width/, you need to call setPageNeedsRawCssStyles to store all css styles
* internally for later use. Or you can use MetaModule's setPageArguments method and provide "reserveCssStyles" as "true" before rendering the page.
*/
- (void)setPageKeepRawCssStyles;
- (BOOL)isKeepingRawCssStyles;

/**
* Set additional argument value for WeexCore
*/
- (void)setPageArgument:(NSString*)key value:(NSString*)value;

/**
* Application required Page Width and Height to prevent Weex use DeviceWidth directly.
*/
- (void)setPageRequiredWidth:(CGFloat)width height:(CGFloat)height;

- (void)setViewportWidth:(CGFloat)width;

/**
* Deprecated
*/
Expand Down
Loading

0 comments on commit 6cd5788

Please sign in to comment.