* [ios] rename recycleslider to cycleslider
Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/9f8771bd Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/9f8771bd Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/9f8771bd Branch: refs/heads/0.12-dev Commit: 9f8771bdfb2a1c11063965c338b24cf123df9b9b Parents: ec1d008 Author: LiuHongfeng(GuJian) <larrywork...@gmail.com> Authored: Fri Apr 7 16:10:05 2017 +0800 Committer: LiuHongfeng(GuJian) <larrywork...@gmail.com> Committed: Fri Apr 7 16:10:05 2017 +0800 ---------------------------------------------------------------------- ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 16 +- .../Sources/Component/WXCycleSliderComponent.h | 18 + .../Sources/Component/WXCycleSliderComponent.m | 593 +++++++++++++++++++ .../Sources/Component/WXIndicatorComponent.m | 6 +- ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m | 2 +- 5 files changed, 623 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9f8771bd/ios/sdk/WeexSDK.xcodeproj/project.pbxproj ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index 16f0b53..fd4eac8 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -37,8 +37,8 @@ 2AE5B7561CABA04E0082FDDB /* WXEventModuleProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AE5B7551CABA04E0082FDDB /* WXEventModuleProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2AFEB17B1C747139000507FA /* WXInstanceWrap.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AFEB1791C747139000507FA /* WXInstanceWrap.h */; }; 2AFEB17C1C747139000507FA /* WXInstanceWrap.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AFEB17A1C747139000507FA /* WXInstanceWrap.m */; }; - 37D940681E9492C600A5C45F /* WXRecycleSliderComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 37D940661E9492C600A5C45F /* WXRecycleSliderComponent.m */; }; - 37D940691E9492C600A5C45F /* WXRecycleSliderComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 37D940671E9492C600A5C45F /* WXRecycleSliderComponent.h */; }; + 37B51EE41E97804D0040A743 /* WXCycleSliderComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 37B51EE21E97804D0040A743 /* WXCycleSliderComponent.h */; }; + 37B51EE51E97804D0040A743 /* WXCycleSliderComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 37B51EE31E97804D0040A743 /* WXCycleSliderComponent.m */; }; 591324A31D49B7F1004E89ED /* WXTimerModuleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 591324A21D49B7F1004E89ED /* WXTimerModuleTests.m */; }; 591DD3311D23AD5800BE8709 /* WXErrorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 591DD32F1D23AD5800BE8709 /* WXErrorView.m */; }; 591DD3321D23AD5800BE8709 /* WXErrorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 591DD3301D23AD5800BE8709 /* WXErrorView.h */; }; @@ -347,8 +347,8 @@ 2AE5B7551CABA04E0082FDDB /* WXEventModuleProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXEventModuleProtocol.h; sourceTree = "<group>"; }; 2AFEB1791C747139000507FA /* WXInstanceWrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXInstanceWrap.h; sourceTree = "<group>"; }; 2AFEB17A1C747139000507FA /* WXInstanceWrap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXInstanceWrap.m; sourceTree = "<group>"; }; - 37D940661E9492C600A5C45F /* WXRecycleSliderComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXRecycleSliderComponent.m; sourceTree = "<group>"; }; - 37D940671E9492C600A5C45F /* WXRecycleSliderComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXRecycleSliderComponent.h; sourceTree = "<group>"; }; + 37B51EE21E97804D0040A743 /* WXCycleSliderComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXCycleSliderComponent.h; sourceTree = "<group>"; }; + 37B51EE31E97804D0040A743 /* WXCycleSliderComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXCycleSliderComponent.m; sourceTree = "<group>"; }; 591324A21D49B7F1004E89ED /* WXTimerModuleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXTimerModuleTests.m; sourceTree = "<group>"; }; 591DD32F1D23AD5800BE8709 /* WXErrorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXErrorView.m; sourceTree = "<group>"; }; 591DD3301D23AD5800BE8709 /* WXErrorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXErrorView.h; sourceTree = "<group>"; }; @@ -1114,10 +1114,10 @@ 77E65A141C155EB5008B8775 /* WXTextComponent.m */, 77E65A171C155F25008B8775 /* WXScrollerComponent.h */, 77E65A181C155F25008B8775 /* WXScrollerComponent.m */, + 37B51EE21E97804D0040A743 /* WXCycleSliderComponent.h */, + 37B51EE31E97804D0040A743 /* WXCycleSliderComponent.m */, 2A44AB0F1C1AD5B00067A7EA /* WXSliderComponent.h */, 59D3CA461CFC3CC0008835DC /* WXSliderComponent.m */, - 37D940661E9492C600A5C45F /* WXRecycleSliderComponent.m */, - 37D940671E9492C600A5C45F /* WXRecycleSliderComponent.h */, 74CC7A1B1C2BC5F800829368 /* WXCellComponent.m */, 74CC7A1E1C2BF9DC00829368 /* WXListComponent.h */, 74CC7A1F1C2BF9DC00829368 /* WXListComponent.m */, @@ -1233,9 +1233,9 @@ 042013AD1E66CD6A001FC79C /* WXValidateProtocol.h in Headers */, C4D872221E5DDEDA00E39BC1 /* WXInnerLayer.h in Headers */, 2A919DA61E321F1F006EB6B5 /* WXBridgeMethod.h in Headers */, + 37B51EE41E97804D0040A743 /* WXCycleSliderComponent.h in Headers */, 77D161281C02DE1A0010B15B /* WXSDKManager.h in Headers */, 59CE27E81CC387DB000BE37A /* WXEmbedComponent.h in Headers */, - 37D940691E9492C600A5C45F /* WXRecycleSliderComponent.h in Headers */, 74BB5FB91DFEE81A004FC3DF /* WXMetaModule.h in Headers */, DCA0EF641D6EED6F00CB18B9 /* WXGlobalEventModule.h in Headers */, 2A837AB21CD9DE9200AEDF03 /* WXLoadingComponent.h in Headers */, @@ -1612,6 +1612,7 @@ 745ED2DB1C5F2C7E002DB5A8 /* WXView.m in Sources */, DC03ADB91D508719003F76E7 /* WXTextAreaComponent.m in Sources */, 59A596231CB6311F0012CD52 /* WXNavigatorModule.m in Sources */, + 37B51EE51E97804D0040A743 /* WXCycleSliderComponent.m in Sources */, 77D161211C02DDB40010B15B /* WXSDKEngine.m in Sources */, D33451091D3E19480083598A /* WXCanvasComponent.m in Sources */, 74A4BA971CB365D100195969 /* WXAppConfiguration.m in Sources */, @@ -1624,7 +1625,6 @@ 74D205211E091B8000128F44 /* WXCallJSMethod.m in Sources */, 59D3CA471CFC3CC0008835DC /* WXSliderComponent.m in Sources */, 77D1613D1C02DEA60010B15B /* WXJSCoreBridge.m in Sources */, - 37D940681E9492C600A5C45F /* WXRecycleSliderComponent.m in Sources */, C41E1A981DC1FD15009C7F90 /* WXDatePickerManager.m in Sources */, 77D1614C1C02E3790010B15B /* WXConvert.m in Sources */, 749DC27C1D40827B009E1C91 /* WXMonitor.m in Sources */, http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9f8771bd/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.h new file mode 100644 index 0000000..4b011dd --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.h @@ -0,0 +1,18 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import <Foundation/Foundation.h> +#import "WXComponent.h" + +@class WXIndicatorView; + +@interface WXCycleSliderComponent : WXComponent + +- (void)setIndicatorView:(WXIndicatorView *)indicatorView; + +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9f8771bd/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.m new file mode 100644 index 0000000..a8fc879 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Component/WXCycleSliderComponent.m @@ -0,0 +1,593 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "WXCycleSliderComponent.h" +#import "WXIndicatorComponent.h" +#import "WXComponent_internal.h" +#import "NSTimer+Weex.h" +#import "WXSDKManager.h" +#import "WXUtility.h" + +typedef NS_ENUM(NSInteger, Direction) { + DirectionNone = 1 << 0, + DirectionLeft = 1 << 1, + DirectionRight = 1 << 2 +}; + +@class WXRecycleSliderView; +@class WXIndicatorView; + +@protocol WXRecycleSliderViewDelegate <UIScrollViewDelegate> + +- (void)recycleSliderView:(WXRecycleSliderView *)recycleSliderView didScroll:(UIScrollView *)scrollView; +- (void)recycleSliderView:(WXRecycleSliderView *)recycleSliderView didScrollToItemAtIndex:(NSInteger)index; +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView; +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; + +@end + +@interface WXRecycleSliderView : UIView <UIScrollViewDelegate> + +@property (nonatomic, strong) WXIndicatorView *indicator; +@property (nonatomic, weak) id<WXRecycleSliderViewDelegate> delegate; + +@property (nonatomic, strong) UIScrollView *scrollView; +@property (nonatomic, strong) NSMutableArray *itemViews; +@property (nonatomic, assign) Direction direction; +@property (nonatomic, assign) NSInteger currentIndex; +@property (nonatomic, assign) NSInteger nextIndex; +@property (nonatomic, assign) CGRect currentItemFrame; +@property (nonatomic, assign) CGRect nextItemFrame; +@property (nonatomic, assign) BOOL infinite; + +- (void)insertItemView:(UIView *)view atIndex:(NSInteger)index; +- (void)removeItemView:(UIView *)view; + +@end + +@implementation WXRecycleSliderView + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + _currentIndex = 0; + _itemViews = [[NSMutableArray alloc] init]; + _scrollView = [[UIScrollView alloc] init]; + _scrollView.backgroundColor = [UIColor clearColor]; + _scrollView.delegate = self; + _scrollView.showsHorizontalScrollIndicator = NO; + _scrollView.showsVerticalScrollIndicator = NO; + _scrollView.scrollsToTop = NO; + [self addSubview:_scrollView]; + } + return self; +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + [self resetAllViewsFrame]; +} + +#pragma mark Private Methods +- (CGFloat)height { + return self.frame.size.height; +} + +- (CGFloat)width { + return self.frame.size.width; +} + +- (UIView *)getItemAtIndex:(NSInteger)index +{ + if (self.itemViews.count > index) { + return [self.itemViews objectAtIndex:index]; + }else{ + return nil; + } +} + +- (void)setCurrentIndex:(NSInteger)currentIndex +{ + if (currentIndex >= _itemViews.count || currentIndex < 0) { + currentIndex = 0; + } + _currentIndex = currentIndex; + if (_infinite) { + if (_direction == DirectionRight) { + self.nextItemFrame = CGRectMake(0, 0, self.width, self.height); + self.nextIndex = self.currentIndex - 1; + if (self.nextIndex < 0) + { + self.nextIndex = _itemViews.count - 1; + } + }else if (_direction == DirectionLeft) { + self.nextItemFrame = CGRectMake(self.width * 2, 0, self.width, self.height); + self.nextIndex = (self.currentIndex + 1) % _itemViews.count; + }else { + self.nextIndex = (self.currentIndex + 1) % _itemViews.count; + } + [self resetAllViewsFrame]; + } else { + [_scrollView setContentOffset:CGPointMake(_currentIndex * self.width, 0) animated:YES]; + } + [self resetIndicatorPoint]; + if (self.delegate && [self.delegate respondsToSelector:@selector(recycleSliderView:didScrollToItemAtIndex:)]) { + [self.delegate recycleSliderView:self didScrollToItemAtIndex:_currentIndex]; + } +} + +- (void)resetIndicatorPoint +{ + [self.indicator setPointCount:self.itemViews.count]; + [self.indicator setCurrentPoint:_currentIndex]; +} + +#pragma mark Scroll & Frames +- (void)setDirection:(Direction)direction { + if (_direction == direction) return; + _direction = direction; + if (_direction == DirectionNone) return; + if (_direction == DirectionRight) { + self.nextItemFrame = CGRectMake(0, 0, self.width, self.height); + self.nextIndex = self.currentIndex - 1; + if (self.nextIndex < 0) + { + self.nextIndex = _itemViews.count - 1; + } + UIView *view = [self getItemAtIndex:_nextIndex]; + if (view) { + view.frame = _nextItemFrame; + } + }else if (_direction == DirectionLeft){ + self.nextItemFrame = CGRectMake(self.width * 2, 0, self.width, self.height); + self.nextIndex = (self.currentIndex + 1) % _itemViews.count; + UIView *view = [self getItemAtIndex:_nextIndex]; + if (view) { + view.frame = _nextItemFrame; + } + } +} + +- (void)resetAllViewsFrame +{ + if (_infinite && _itemViews.count > 1) { + self.scrollView.frame = CGRectMake(0, 0, self.width, self.height); + self.scrollView.contentOffset = CGPointMake(self.width, 0); + if (self.itemViews.count > 1) { + self.scrollView.contentSize = CGSizeMake(self.width * 3, 0); + } else { + self.scrollView.contentSize = CGSizeZero; + } + _currentItemFrame = CGRectMake(self.width, 0, self.width, self.height); + for (int i = 0; i < self.itemViews.count; i++) { + UIView *view = [self.itemViews objectAtIndex:i]; + if (i != self.currentIndex && i != self.nextIndex) { + view.frame = CGRectMake(self.frame.size.width * 3, 0, self.width, self.height);; + } + } + [self getItemAtIndex:_currentIndex].frame = _currentItemFrame; + if (_itemViews.count == 2) { + _nextItemFrame = CGRectMake(self.width * 2, 0, self.width, self.height); + [self getItemAtIndex:_nextIndex].frame = _nextItemFrame; + } + } else { + self.scrollView.frame = self.bounds; + self.scrollView.contentSize = CGSizeMake(self.width * _itemViews.count, self.height); + self.scrollView.contentOffset = CGPointMake(_currentIndex * self.width, 0); + for (int i = 0; i < _itemViews.count; i ++) { + UIView *view = [_itemViews objectAtIndex:i]; + view.frame = CGRectMake(i * self.width, 0, self.width, self.height); + } + [self.scrollView setContentOffset:CGPointMake(_currentIndex * self.width, 0) animated:NO]; + } + [self resetIndicatorPoint]; +} + +- (void)nextPage { + if (_itemViews.count > 1) { + if (_infinite) { + [self.scrollView setContentOffset:CGPointMake(self.width * 2, 0) animated:YES]; + } else { + _currentIndex += 1; + if (_currentIndex - 1 < _itemViews.count) { + [self.scrollView setContentOffset:CGPointMake(_currentIndex * self.width, 0) animated:YES]; + } + } + } +} + +- (void)resetScrollView { + if (self.scrollView.contentOffset.x / self.width == 1) + { + return; + } + [self setCurrentIndex:self.nextIndex]; + self.scrollView.contentOffset = CGPointMake(self.width, 0); +} + +#pragma mark Public Methods + +- (void)setIndicator:(WXIndicatorView *)indicator +{ + _indicator = indicator; + [_indicator setPointCount:self.itemViews.count]; + [_indicator setCurrentPoint:_currentIndex]; +} + +- (void)insertItemView:(UIView *)view atIndex:(NSInteger)index +{ + if (![self.itemViews containsObject:view]) { + view.tag = self.itemViews.count; + if (index < 0) { + [self.itemViews addObject:view]; + } else { + [self.itemViews insertObject:view atIndex:index]; + } + } + + if (![self.scrollView.subviews containsObject:view]) { + if (index < 0) { + [self.scrollView addSubview:view]; + } else { + [self.scrollView insertSubview:view atIndex:index]; + } + } + [self layoutSubviews]; + [self setCurrentIndex:_currentIndex]; +} + +- (void)removeItemView:(UIView *)view +{ + if ([self.itemViews containsObject:view]) { + [self.itemViews removeObject:view]; + } + + if ([self.scrollView.subviews containsObject:view]) { + [view removeFromSuperview]; + } + [self layoutSubviews]; + [self setCurrentIndex:_currentIndex]; +} + +#pragma mark ScrollView Delegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView +{ + if (_infinite) { + CGFloat offX = scrollView.contentOffset.x; + self.direction = offX > self.width ? DirectionLeft : offX < self.width ? DirectionRight : DirectionNone; + } + if (self.delegate && [self.delegate respondsToSelector:@selector(recycleSliderView:didScroll:)]) { + [self.delegate recycleSliderView:self didScroll:self.scrollView]; + } +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView +{ + if (self.delegate && [self.delegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) { + [self.delegate scrollViewWillBeginDragging:self.scrollView]; + } +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate +{ + if (self.delegate && [self.delegate respondsToSelector:@selector(scrollViewDidEndDragging: willDecelerate:)]) { + [self.delegate scrollViewDidEndDragging:self.scrollView willDecelerate:decelerate]; + } +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + if (_infinite) { + [self resetScrollView]; + } else { + NSInteger index = _scrollView.contentOffset.x / self.width; + [self setCurrentIndex:index]; + } +} + +- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { + if (_infinite) { + [self resetScrollView]; + } else { + NSInteger index = _scrollView.contentOffset.x / self.width; + [self setCurrentIndex:index]; + } +} + +@end + +@interface WXCycleSliderComponent ()<WXRecycleSliderViewDelegate> + +@property (nonatomic, strong) WXRecycleSliderView *recycleSliderView; +@property (nonatomic, strong) NSTimer *autoTimer; +@property (nonatomic, assign) NSInteger currentIndex; +@property (nonatomic, assign) BOOL autoPlay; +@property (nonatomic, assign) NSUInteger interval; +@property (nonatomic, assign) NSInteger index; +@property (nonatomic, assign) CGFloat lastOffsetXRatio; +@property (nonatomic, assign) CGFloat offsetXAccuracy; +@property (nonatomic, assign) BOOL sliderChangeEvent; +@property (nonatomic, assign) BOOL sliderScrollEvent; +@property (nonatomic, assign) BOOL sliderScrollStartEvent; +@property (nonatomic, assign) BOOL sliderScrollEndEvent; +@property (nonatomic, assign) BOOL sliderStartEventFired; +@property (nonatomic, strong) NSMutableArray *childrenView; +@property (nonatomic, assign) BOOL scrollable; +@property (nonatomic, assign) BOOL infinite; + +@end + +@implementation WXCycleSliderComponent + +- (void) dealloc +{ + [self _stopAutoPlayTimer]; +} + +- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance +{ + if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) { + _sliderChangeEvent = NO; + _sliderScrollEvent = NO; + _interval = 3000; + _childrenView = [NSMutableArray new]; + _lastOffsetXRatio = 0; + + if (attributes[@"autoPlay"]) { + _autoPlay = [WXConvert BOOL:attributes[@"autoPlay"]]; + } + + if (attributes[@"interval"]) { + _interval = [WXConvert NSInteger:attributes[@"interval"]]; + } + + if (attributes[@"index"]) { + _index = [WXConvert NSInteger:attributes[@"index"]]; + } + _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES; + if (attributes[@"offsetXAccuracy"]) { + _offsetXAccuracy = [WXConvert CGFloat:attributes[@"offsetXAccuracy"]]; + } + _infinite = attributes[@"infinite"] ? [WXConvert BOOL:attributes[@"infinite"]] : YES; + self.cssNode->style.flex_direction = CSS_FLEX_DIRECTION_ROW; + } + return self; +} + +- (UIView *)loadView +{ + return [[WXRecycleSliderView alloc] init]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + _recycleSliderView = (WXRecycleSliderView *)self.view; + _recycleSliderView.delegate = self; + _recycleSliderView.scrollView.pagingEnabled = YES; + _recycleSliderView.exclusiveTouch = YES; + _recycleSliderView.scrollView.scrollEnabled = _scrollable; + _recycleSliderView.infinite = _infinite; + if (_autoPlay) { + [self _startAutoPlayTimer]; + } else { + [self _stopAutoPlayTimer]; + } +} + +- (void)layoutDidFinish +{ + _recycleSliderView.currentIndex = _index; +} + +- (void)viewDidUnload +{ + [_childrenView removeAllObjects]; +} + +- (void)insertSubview:(WXComponent *)subcomponent atIndex:(NSInteger)index +{ + if (subcomponent->_positionType == WXPositionTypeFixed) { + [self.weexInstance.rootView addSubview:subcomponent.view]; + return; + } + + // use _lazyCreateView to forbid component like cell's view creating + if(_lazyCreateView) { + subcomponent->_lazyCreateView = YES; + } + + if (!subcomponent->_lazyCreateView || (self->_lazyCreateView && [self isViewLoaded])) { + UIView *view = subcomponent.view; + + if(index < 0) { + [self.childrenView addObject:view]; + } + else { + [self.childrenView insertObject:view atIndex:index]; + } + + WXRecycleSliderView *recycleSliderView = (WXRecycleSliderView *)self.view; + if ([view isKindOfClass:[WXIndicatorView class]]) { + [recycleSliderView addSubview:view]; + return; + } + + subcomponent.isViewFrameSyncWithCalculated = NO; + + if (index == -1) { + [recycleSliderView insertItemView:view atIndex:index]; + } else { + NSInteger offset = 0; + for (int i = 0; i < [self.childrenView count]; ++i) { + if (index == i) break; + + if ([self.childrenView[i] isKindOfClass:[WXIndicatorView class]]) { + offset++; + } + } + [recycleSliderView insertItemView:view atIndex:index - offset]; + } + [recycleSliderView layoutSubviews]; + } +} + +- (void)willRemoveSubview:(WXComponent *)component +{ + UIView *view = component.view; + + if(self.childrenView && [self.childrenView containsObject:view]) { + [self.childrenView removeObject:view]; + } + + WXRecycleSliderView *recycleSliderView = (WXRecycleSliderView *)_view; + [recycleSliderView removeItemView:view]; + [recycleSliderView setCurrentIndex:0]; +} + +- (void)updateAttributes:(NSDictionary *)attributes +{ + if (attributes[@"autoPlay"]) { + _autoPlay = [WXConvert BOOL:attributes[@"autoPlay"]]; + if (_autoPlay) { + [self _startAutoPlayTimer]; + } else { + [self _stopAutoPlayTimer]; + } + } + + if (attributes[@"interval"]) { + _interval = [WXConvert NSInteger:attributes[@"interval"]]; + [self _stopAutoPlayTimer]; + + if (_autoPlay) { + [self _startAutoPlayTimer]; + } + } + + if (attributes[@"index"]) { + _index = [WXConvert NSInteger:attributes[@"index"]]; + self.currentIndex = _index; + self.recycleSliderView.currentIndex = _index; + } + + if (attributes[@"scrollable"]) { + _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES; + ((WXRecycleSliderView *)self.view).scrollView.scrollEnabled = _scrollable; + } + + if (attributes[@"offsetXAccuracy"]) { + _offsetXAccuracy = [WXConvert CGFloat:attributes[@"offsetXAccuracy"]]; + } + if (attributes[@"infinite"]) { + _infinite = [WXConvert BOOL:attributes[@"infinite"]]; + } +} + +- (void)addEvent:(NSString *)eventName +{ + if ([eventName isEqualToString:@"change"]) { + _sliderChangeEvent = YES; + } + if ([eventName isEqualToString:@"scroll"]) { + _sliderScrollEvent = YES; + } +} + +- (void)removeEvent:(NSString *)eventName +{ + if ([eventName isEqualToString:@"change"]) { + _sliderChangeEvent = NO; + } + if ([eventName isEqualToString:@"scroll"]) { + _sliderScrollEvent = NO; + } +} + +#pragma mark Public Methods + +-(void)setIndicatorView:(WXIndicatorView *)indicatorView +{ + NSAssert(_recycleSliderView, @""); + [_recycleSliderView setIndicator:indicatorView]; +} + +#pragma mark Private Methods + +- (void)_startAutoPlayTimer +{ + if (!self.autoTimer || ![self.autoTimer isValid]) { + __weak __typeof__(self) weakSelf = self; + self.autoTimer = [NSTimer wx_scheduledTimerWithTimeInterval:_interval/1000.0f block:^() { + [weakSelf _autoPlayOnTimer]; + } repeats:YES]; + [[NSRunLoop currentRunLoop] addTimer:self.autoTimer forMode:NSRunLoopCommonModes]; + } +} + +- (void)_stopAutoPlayTimer +{ + if (self.autoTimer && [self.autoTimer isValid]) { + [self.autoTimer invalidate]; + self.autoTimer = nil; + } +} + +- (void)_autoPlayOnTimer +{ + if (!_infinite && (_currentIndex == _recycleSliderView.itemViews.count - 1)) { + [self _stopAutoPlayTimer]; + }else { + [self.recycleSliderView nextPage]; + } +} + +#pragma mark ScrollView Delegate + +- (void)recycleSliderView:(WXRecycleSliderView *)recycleSliderView didScroll:(UIScrollView *)scrollView +{ + if (_sliderScrollEvent) { + CGFloat width = scrollView.frame.size.width; + CGFloat XDeviation = 0; + if (_infinite) { + XDeviation = - (scrollView.contentOffset.x - width); + } else { + XDeviation = - (scrollView.contentOffset.x - width * _currentIndex); + } + CGFloat offsetXRatio = (XDeviation / width); + if (fabs(offsetXRatio - _lastOffsetXRatio) >= _offsetXAccuracy) { + _lastOffsetXRatio = offsetXRatio; + [self fireEvent:@"scroll" params:@{@"offsetXRatio":[NSNumber numberWithFloat:offsetXRatio]} domChanges:nil]; + } + } +} + +- (void)recycleSliderView:(WXRecycleSliderView *)recycleSliderView didScrollToItemAtIndex:(NSInteger)index +{ + self.currentIndex = index; + if (_sliderChangeEvent) { + [self fireEvent:@"change" params:@{@"index":@(index)} domChanges:@{@"attrs": @{@"index": @(index)}}]; + } +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView +{ + [self _stopAutoPlayTimer]; +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate +{ + if (_autoPlay) { + [self _startAutoPlayTimer]; + } +} + +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9f8771bd/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m index b4af2af..2647d61 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m @@ -8,7 +8,7 @@ #import "WXIndicatorComponent.h" #import "WXSliderComponent.h" -#import "WXRecycleSliderComponent.h" +#import "WXCycleSliderComponent.h" #import "WXConvert.h" #import "WXSliderNeighborComponent.h" #import "WXSDKInstance.h" @@ -164,8 +164,8 @@ WXSliderComponent *parentSlider = (WXSliderComponent *)parent; [parentSlider setIndicatorView:_indicatorView]; } - if([parent isKindOfClass:[WXRecycleSliderComponent class]]) { - WXRecycleSliderComponent *parentSlider = (WXRecycleSliderComponent *)parent; + if([parent isKindOfClass:[WXCycleSliderComponent class]]) { + WXCycleSliderComponent *parentSlider = (WXCycleSliderComponent *)parent; [parentSlider setIndicatorView:_indicatorView]; }else if ([parent isKindOfClass:[WXSliderNeighborComponent class]]) { WXSliderNeighborComponent *parentSlider = (WXSliderNeighborComponent *)parent; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9f8771bd/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m index 37c9e34..7d43bf0 100644 --- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m +++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m @@ -86,7 +86,7 @@ [self registerComponent:@"video" withClass:NSClassFromString(@"WXVideoComponent")]; [self registerComponent:@"indicator" withClass:NSClassFromString(@"WXIndicatorComponent")]; [self registerComponent:@"slider" withClass:NSClassFromString(@"WXSliderComponent")]; - [self registerComponent:@"recycleslider" withClass:NSClassFromString(@"WXRecycleSliderComponent")]; + [self registerComponent:@"cycleslider" withClass:NSClassFromString(@"WXCycleSliderComponent")]; [self registerComponent:@"web" withClass:NSClassFromString(@"WXWebComponent")]; [self registerComponent:@"loading" withClass:NSClassFromString(@"WXLoadingComponent")]; [self registerComponent:@"loading-indicator" withClass:NSClassFromString(@"WXLoadingIndicator")];