diff --git a/README.md b/README.md index bbd6ae55a27..02c62366e1b 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Hippy is now applied in [Tencent](http://www.tencent.com/) major apps such as Mo * Excellent performance with JS engine binding communication. * Build-in recyclable component with better performance. * Smoothly and gracefully migrate to Web browser. -* Fully supported Flex [Layout engine](./layout). +* Fully supported Flex [Layout engine](https://github.com/Tencent/taitank). ## 🔨 Getting started diff --git a/driver/js/packages/hippy-react/src/components/list-view.tsx b/driver/js/packages/hippy-react/src/components/list-view.tsx index db096880c59..b8e78583afd 100644 --- a/driver/js/packages/hippy-react/src/components/list-view.tsx +++ b/driver/js/packages/hippy-react/src/components/list-view.tsx @@ -494,20 +494,21 @@ class ListView extends React.Component { style = getFooterStyle(); } if (typeof renderPullFooter === 'function') { - pullFooter = ( - { - this.pullFooter = ref; - }} - onFooterPulling={onFooterPulling} - onFooterReleased={onFooterReleased} - > - { renderPullFooter() } - - ); + const footerProps: any = { + style, + key: 'pull-footer', + ref: (ref) => { + this.pullFooter = ref; + }, + }; + + if (typeof onFooterPulling === 'function') { + footerProps.onFooterPulling = onFooterPulling; + } + if (typeof onFooterPulling === 'function') { + footerProps.onFooterReleased = onFooterReleased; + } + pullFooter = {renderPullFooter()}; } return pullFooter; } diff --git a/driver/js/packages/hippy-react/src/components/waterfall-view.tsx b/driver/js/packages/hippy-react/src/components/waterfall-view.tsx index 77ea38be498..af2107f8677 100644 --- a/driver/js/packages/hippy-react/src/components/waterfall-view.tsx +++ b/driver/js/packages/hippy-react/src/components/waterfall-view.tsx @@ -458,18 +458,18 @@ class WaterfallView extends React.Component { ) { let pullFooter: JSX.Element | null = null; if (typeof renderPullFooter === 'function') { - pullFooter = ( - { - this.pullFooter = ref; - }} - onFooterPulling={onFooterPulling} - onFooterReleased={onFooterReleased} - > - { renderPullFooter() } - - ); + const footerProps: any = { + key: 'PullFooter', + ref: (ref) => { + this.pullFooter = ref; + }, + onFooterReleased, + }; + + if (typeof onFooterPulling === 'function') { + footerProps.onFooterPulling = onFooterPulling; + } + pullFooter = {renderPullFooter()}; } return pullFooter; } diff --git a/driver/js/packages/hippy-vue-native-components/src/ul-refresh.ts b/driver/js/packages/hippy-vue-native-components/src/ul-refresh.ts index f999ad686ca..39d37a954c4 100644 --- a/driver/js/packages/hippy-vue-native-components/src/ul-refresh.ts +++ b/driver/js/packages/hippy-vue-native-components/src/ul-refresh.ts @@ -24,6 +24,17 @@ function registerUlRefresh(Vue: any) { Vue.registerElement('hi-ul-refresh-wrapper', { component: { name: 'RefreshWrapper', + processEventData(event, nativeEventName, nativeEventParams) { + switch (nativeEventName) { + case 'onScroll': { + event.offsetX = nativeEventParams.contentOffset.x; + event.offsetY = nativeEventParams.contentOffset.y; + break; + } + default: + } + return event; + }, }, }); @@ -53,6 +64,7 @@ function registerUlRefresh(Vue: any) { render(h: any) { const on = getEventRedirector.call(this, [ 'refresh', + 'scroll', ]); return h('hi-ul-refresh-wrapper', { on, diff --git a/renderer/native/ios/renderer/component/listview/HippyNextBaseListItemView.h b/renderer/native/ios/renderer/component/listview/HippyNextBaseListItemView.h index 8a97cecbdf9..9a36f449309 100644 --- a/renderer/native/ios/renderer/component/listview/HippyNextBaseListItemView.h +++ b/renderer/native/ios/renderer/component/listview/HippyNextBaseListItemView.h @@ -26,8 +26,4 @@ @interface HippyNextBaseListItemView : HippyView -@property (nonatomic, strong) id type; -@property (nonatomic, assign) BOOL isSticky; - - @end diff --git a/renderer/native/ios/renderer/component/listview/HippyNextBaseListItemViewManager.m b/renderer/native/ios/renderer/component/listview/HippyNextBaseListItemViewManager.m index 02dd55cb986..929ae385e46 100644 --- a/renderer/native/ios/renderer/component/listview/HippyNextBaseListItemViewManager.m +++ b/renderer/native/ios/renderer/component/listview/HippyNextBaseListItemViewManager.m @@ -23,24 +23,27 @@ #import "HippyNextBaseListItemViewManager.h" #import "HippyNextBaseListItemView.h" #import "HippyShadowWaterfallItem.h" +#import "HippyNextShadowListItem.h" + @implementation HippyNextBaseListItemViewManager HIPPY_EXPORT_MODULE(ListViewItem) HIPPY_EXPORT_VIEW_PROPERTY(type, id) -HIPPY_EXPORT_VIEW_PROPERTY(isSticky, BOOL) HIPPY_EXPORT_VIEW_PROPERTY(onAppear, HippyDirectEventBlock) HIPPY_EXPORT_VIEW_PROPERTY(onDisappear, HippyDirectEventBlock) HIPPY_EXPORT_VIEW_PROPERTY(onWillAppear, HippyDirectEventBlock) HIPPY_EXPORT_VIEW_PROPERTY(onWillDisappear, HippyDirectEventBlock) +HIPPY_EXPORT_SHADOW_PROPERTY(sticky, BOOL) +HIPPY_EXPORT_SHADOW_PROPERTY(keepAlive, BOOL) - (UIView *)view { return [[HippyNextBaseListItemView alloc] init]; } - (HippyShadowView *)shadowView { - return [[HippyShadowWaterfallItem alloc] init]; + return [[HippyNextShadowListItem alloc] init]; } @end diff --git a/renderer/native/ios/renderer/component/listview/HippyNextBaseListView.mm b/renderer/native/ios/renderer/component/listview/HippyNextBaseListView.mm index d4934955238..13b0fe21380 100644 --- a/renderer/native/ios/renderer/component/listview/HippyNextBaseListView.mm +++ b/renderer/native/ios/renderer/component/listview/HippyNextBaseListView.mm @@ -33,6 +33,7 @@ #import "UIView+Hippy.h" #import "UIView+Render.h" #import "HippyShadowListView.h" +#import "HippyNextShadowListItem.h" static NSString *const kCellIdentifier = @"HippyListCellIdentifier"; static NSString *const kSupplementaryIdentifier = @"HippySupplementaryIdentifier"; @@ -41,6 +42,7 @@ @interface HippyNextBaseListView () { BOOL _isInitialListReady; NSArray *_previousVisibleCells; + NSMutableArray *_keepAliveCellViews; // cellViews that marked keep-Alive } @end @@ -265,17 +267,28 @@ - (void)collectionView:(UICollectionView *)collectionView - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { HippyNextBaseListViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellIdentifier forIndexPath:indexPath]; - HippyShadowView *shadowView = [self.dataSource cellForIndexPath:indexPath]; + HippyNextShadowListItem *shadowView = (HippyNextShadowListItem *)[self.dataSource cellForIndexPath:indexPath]; UIView *cellView = nil; UIView *cachedVisibleCellView = [_cachedWeakCellViews objectForKey:shadowView.hippyTag]; if (cachedVisibleCellView) { cellView = cachedVisibleCellView; + // Remove keep-Alive cellView if needed + if ([_keepAliveCellViews containsObject:cachedVisibleCellView] && shadowView.keepAlive == NO) { + [_keepAliveCellViews removeObject:cachedVisibleCellView]; + } HippyLogTrace(@"%@ 🟢 use cached visible cellView at {%ld - %ld} for %@", self.hippyTag, indexPath.section, indexPath.row, shadowView.hippyTag); } else { cellView = [self.uiManager createViewForShadowListItem:shadowView]; [_cachedWeakCellViews setObject:cellView forKey:shadowView.hippyTag]; + // Add keep-Alive cellView to cache if needed + if (shadowView.keepAlive) { + if (!_keepAliveCellViews) { + _keepAliveCellViews = [NSMutableArray array]; + } + [_keepAliveCellViews addObject:cellView]; + } HippyLogTrace(@"%@ 🟡 create cellView at {%ld - %ld} for %@", self.hippyTag, indexPath.section, indexPath.row, shadowView.hippyTag); } diff --git a/renderer/native/ios/renderer/component/listview/HippyNextBaseListViewDataSource.m b/renderer/native/ios/renderer/component/listview/HippyNextBaseListViewDataSource.m index 8bb04d095e4..700377a677d 100644 --- a/renderer/native/ios/renderer/component/listview/HippyNextBaseListViewDataSource.m +++ b/renderer/native/ios/renderer/component/listview/HippyNextBaseListViewDataSource.m @@ -24,10 +24,9 @@ #import "HippyNextBaseListViewDataSource.h" #import "HippyShadowView.h" #import "HippyShadowListView.h" +#import "HippyNextShadowListItem.h" -static NSString * const kStickyCellPropKey = @"sticky"; - @interface HippyNextBaseListViewDataSource () { NSMutableArray *_shadowHeaderViews; } @@ -42,9 +41,8 @@ - (void)setDataSource:(NSArray *)dataSource containBannerView NSMutableArray *shadowSectionCell = nil; BOOL isFirstIndex = YES; for (HippyShadowView *shadowView in dataSource) { - if ([self.itemViewName isEqualToString:shadowView.viewName]) { - NSNumber *sticky = shadowView.props[kStickyCellPropKey]; - if ([sticky boolValue]) { + if ([shadowView isKindOfClass:HippyNextShadowListItem.class]) { + if (((HippyNextShadowListItem *)shadowView).isSticky) { [shadowHeaders addObject:shadowView]; if (shadowSectionCell) { [shadowCells addObject:shadowSectionCell]; diff --git a/renderer/native/ios/renderer/component/listview/HippyNextShadowListItem.h b/renderer/native/ios/renderer/component/listview/HippyNextShadowListItem.h new file mode 100644 index 00000000000..93a54d9473d --- /dev/null +++ b/renderer/native/ios/renderer/component/listview/HippyNextShadowListItem.h @@ -0,0 +1,39 @@ +/*! + * iOS SDK + * + * Tencent is pleased to support the open source community by making + * Hippy available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#import "HippyShadowWaterfallItem.h" + +NS_ASSUME_NONNULL_BEGIN + +/// ListView item's shadow view +@interface HippyNextShadowListItem : HippyShadowWaterfallItem + +/// Whether item is stick to the top +@property (nonatomic, assign, getter=isSticky) BOOL sticky; + +/// Memory management property that sets item to exist for the lifetime of listView +@property (nonatomic, assign) BOOL keepAlive; + +@end + +NS_ASSUME_NONNULL_END diff --git a/renderer/native/ios/renderer/component/listview/HippyNextShadowListItem.m b/renderer/native/ios/renderer/component/listview/HippyNextShadowListItem.m new file mode 100644 index 00000000000..0fc642864d7 --- /dev/null +++ b/renderer/native/ios/renderer/component/listview/HippyNextShadowListItem.m @@ -0,0 +1,27 @@ +/*! + * iOS SDK + * + * Tencent is pleased to support the open source community by making + * Hippy available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "HippyNextShadowListItem.h" + +@implementation HippyNextShadowListItem + +@end