You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by bo...@apache.org on 2017/04/10 03:51:54 UTC

[6/9] incubator-weex git commit: * [ios] rename recycleslider to cycleslider

* [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) <La...@gmail.com>
Authored: Fri Apr 7 16:10:05 2017 +0800
Committer: LiuHongfeng(GuJian) <La...@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")];