├── README.md ├── TXCarouselViewDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── xinhualongmac.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── TXCarouselViewDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── zongshujidaowojia1.imageset │ │ ├── Contents.json │ │ ├── tu.png │ │ ├── tu@2x.png │ │ └── tu@3x.png │ ├── zongshujidaowojia2.imageset │ │ ├── Contents.json │ │ ├── tu.png │ │ ├── tu@2x.png │ │ └── tu@3x.png │ ├── zongshujidaowojia3.imageset │ │ ├── 0.png │ │ ├── 0@2x.png │ │ ├── 0@3x.png │ │ └── Contents.json │ ├── zongshujidaowojia4.imageset │ │ ├── 0.png │ │ ├── 0@2x.png │ │ ├── 0@3x.png │ │ └── Contents.json │ └── zongshujidaowojia5.imageset │ │ ├── 220.webp-(1).png │ │ ├── 220.webp-(1)@2x.png │ │ ├── 220.webp-(1)@3x.png │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── CarouselImageCell.h ├── CarouselImageCell.m ├── CarouselImageCell.xib ├── CarouselView │ ├── TXCarouselCellModel.h │ ├── TXCarouselCellModel.m │ ├── TXCarouselCollectionViewCell.h │ ├── TXCarouselCollectionViewCell.m │ ├── TXCarouselCollectionViewCell.xib │ ├── TXCarouselView.h │ ├── TXCarouselView.m │ ├── TXCarouselViewLayout.h │ └── TXCarouselViewLayout.m ├── Info.plist ├── TXTextTableViewCell.h ├── TXTextTableViewCell.m ├── TXTextTableViewCell.xib ├── ViewController.h ├── ViewController.m └── main.m ├── TXCarouselViewDemoTests ├── Info.plist └── TXCarouselViewDemoTests.m └── TXCarouselViewDemoUITests ├── Info.plist └── TXCarouselViewDemoUITests.m /README.md: -------------------------------------------------------------------------------- 1 | 前段时间,公司的大佬看中了新浪新闻首页卡片滚动的特效,如下图: 2 | 3 | ![新浪新闻卡片效果(网络来源)](https://upload-images.jianshu.io/upload_images/9610720-84968781a1077e85.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/360) 4 | 5 | 拿到效果图一看之下这个效果,这个效果不是那么好做。由于赶在年前就要上线,时间紧迫。没办法只有靠度娘了,多方查找之下,找到了一篇文章-[iOS新浪新闻首页卡片滚动特效实现浅谈](https://www.jianshu.com/p/5145da65f20f)。 6 | 7 | 当时一看,这个不就是大佬想要的效果么?心中顿时一阵窃喜。大致浏览了一下然后迅速拉到文章底下想看一下demo。结果傻眼了,别说demo了,连部分源码也没有,只提供了大致的思路。我靠,心中一阵拔凉。 8 | 9 |  然后重新阅读了一下[随行的羊](https://www.jianshu.com/u/f4cf2045e5e1)的文章。发现他的思路很明确。行吧,那没办法了, 只有先按照他的思路做。 10 | 11 | ###下面进入正题 12 | [随行的羊](https://www.jianshu.com/u/f4cf2045e5e1)采用了UICollectionView,那我也采用了这个吧,说干就干,下面我直接根据他的思路贴出部分代码,具体的demo 详见github地址:[TXCarouselView](https://link.jianshu.com/?t=https%3A%2F%2Fgithub.com%2FTianXin123654%2FTXCarouselView) 13 | 14 | 问题1:中间的滚动视图是一块一块移动的,停止时距离中间最近的卡片会自动滑动到中间,居中对齐。 15 | ``` 16 | - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity { 17 | CGFloat index = roundf((proposedContentOffset.x+ self.viewHeight / 2 - self.itemHeight / 2) / self.itemHeight); 18 | proposedContentOffset.x = self.itemHeight * index + self.itemHeight / 2 - self.viewHeight / 2; 19 | return proposedContentOffset; 20 | } 21 | ``` 22 | 问题2:中间的滚动视图在滑动的时候发现卡片是叠在一起的,中间的在上层,其他部分在下层,根据距离中间位置的远近来区别上下层。 23 | ``` 24 | - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { 25 | UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 26 | attributes.size = self.itemSize; 27 | CGFloat cY = self.collectionView.contentOffset.x + self.viewHeight / 2; 28 | CGFloat attributesY = self.itemHeight * indexPath.row + self.itemHeight / 2;// 29 | attributes.zIndex = -ABS(attributesY - cY); 30 | } 31 | ``` 32 | 问题3:中间的滚动视图在滑动的时候发现卡片大小不一致,中间的最大,越靠近边框越小。同样是在layoutAttributesForItemAtIndexPath中: 33 | ``` 34 | CGFloat scale = 1 - ABS(delta) / (self.itemHeight * 6.0) * cos(ratio * M_2_PI*0.9); 35 | attributes.transform = CGAffineTransformMakeScale(scale, scale); 36 | ``` 37 | 问题4:中间的滚动视图在滑动的时候发现滑动的距离和卡片移动的距离并不是成正比,而是按照不断变化的加速度移动的。 38 | ``` 39 | centerY = cY + sin(ratio * 1.31) * self.itemHeight * INTERSPACEPARAM*2.2+index1; 40 | 41 | ``` 42 | 问题5:中间的滚动视图滑到左右边缘时视图透明度改变。 43 | ``` 44 | 这个也可以根据的centerY来确定,attributes这个布局类中提供了 45 | @property (nonatomic) CGFloat alpha; 46 | 所以也可以实现。 47 | ``` 48 | 问题6:循环滚动方案的实现(额。这里我用的创建多组数据来实现的,因为cell有复用机制,所以创建多组数据也没有关系。只要能顺滑就行了) 49 | ``` 50 | self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO]; 51 | 52 | ``` 53 | 54 | 问题7:上下滑动表格时,中间的滚动视图要跟着一起滑动,上滑时向左移动,下滑时向右移动。 55 | ``` 56 | 这里用kvo监听一下就可以了 57 | [self.superScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; 58 | ``` 59 | 问题8:左右晃动手机时,中间的滚动视图要跟着一起滑动,向左晃动时卡片向左移动,向右晃动时卡片向右移动。 60 | >这个用苹果自带的加速计和陀螺仪就行了,但是其中有很多问题需要解决,但是细致调试之下完美解决了具体代码详见github地址:[TXCarouselView](https://link.jianshu.com/?t=https%3A%2F%2Fgithub.com%2FTianXin123654%2FTXCarouselView) 61 | 62 | 问题9:需要保证刚才提到的3种控制方式互不干扰。 63 | ``` 64 | @interface carouselCurrentState : NSObject 65 | @property (nonatomic, assign) BOOL isOverturnState; //是否进入翻转状态 66 | @property (nonatomic, assign) BOOL isDragState; //是否处于拖动状态 67 | @property (nonatomic, assign) BOOL isDidScroll; //是否处于滑动状态 68 | @property (nonatomic, assign) BOOL isCenter; //是否处于回到正中状态 69 | @property (nonatomic, assign) BOOL isRestrict; //是否处于限制重力感应 70 | @property (nonatomic, assign) CGFloat lastCarouselPoint;//上一个lastPoint 71 | 72 | @end 73 | 74 | @implementation carouselCurrentState 75 | @end 76 | ``` 77 | 问题10:拖动,滑动, 重力感应结束需要回到正中位置。 78 | ``` 79 | 1.拖动 80 | - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity { 81 | CGFloat index = roundf((proposedContentOffset.x+ self.viewHeight / 2 - self.itemHeight / 2) / self.itemHeight); 82 | proposedContentOffset.x = self.itemHeight * index + self.itemHeight / 2 - self.viewHeight / 2; 83 | return proposedContentOffset; 84 | } 85 | ``` 86 | ``` 87 | 2.tableview滑动结束时,需要回到初始位置,这里我试过用kvo监听superScrollView的滑动结束,但是没有找到方法。用通知就太low了,然后在朋友的建议下用了runLoop: 88 | - (void)creatUIRunloopObserver:(CFOptionFlags)flag { 89 | CFRunLoopRef runLoop = CFRunLoopGetCurrent(); 90 | CFStringRef runLoopMode = (__bridge CFStringRef)UITrackingRunLoopMode; 91 | CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, flag, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity _activity) { 92 | switch (_activity) { 93 | case kCFRunLoopEntry: { 94 | NSLog(@"即将进入Loop"); 95 | } 96 | break; 97 | case kCFRunLoopBeforeTimers: { 98 | NSLog(@"即将处理 Timer"); 99 | break; 100 | } 101 | case kCFRunLoopBeforeSources: 102 | NSLog(@"即将处理 Source"); 103 | break; 104 | case kCFRunLoopBeforeWaiting: 105 | NSLog(@"即将进入休眠"); 106 | break; 107 | case kCFRunLoopAfterWaiting: 108 | NSLog(@"刚从休眠中唤醒"); 109 | break; 110 | case kCFRunLoopExit: 111 | NSLog(@"UITracking 即将退出Loop"); 112 | self.currentState.isOverturnState = NO; 113 | self.currentState.isDragState = NO; 114 | self.currentState.isDidScroll = NO; 115 | self.currentState.isCenter = NO; 116 | self.currentState.isRestrict = NO; 117 | self.currentState.lastCarouselPoint = 0.0f; 118 | [self setSlideEnd]; 119 | break; 120 | default: 121 | break; 122 | } 123 | }); 124 | 125 | CFRunLoopAddObserver(runLoop, observer, runLoopMode); 126 | } 127 | 128 | ``` 129 | 好了,大部分的细节就不细说了,如果能给一个star就最好了。 130 | 131 | -------------------------------------------------------------------------------- /TXCarouselViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8F9E21AB20219AEA005BFD43 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21AA20219AEA005BFD43 /* AppDelegate.m */; }; 11 | 8F9E21AE20219AEA005BFD43 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21AD20219AEA005BFD43 /* ViewController.m */; }; 12 | 8F9E21B120219AEA005BFD43 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8F9E21AF20219AEA005BFD43 /* Main.storyboard */; }; 13 | 8F9E21B320219AEA005BFD43 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8F9E21B220219AEA005BFD43 /* Assets.xcassets */; }; 14 | 8F9E21B620219AEA005BFD43 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8F9E21B420219AEA005BFD43 /* LaunchScreen.storyboard */; }; 15 | 8F9E21B920219AEA005BFD43 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21B820219AEA005BFD43 /* main.m */; }; 16 | 8F9E21C320219AEB005BFD43 /* TXCarouselViewDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21C220219AEB005BFD43 /* TXCarouselViewDemoTests.m */; }; 17 | 8F9E21CE20219AEB005BFD43 /* TXCarouselViewDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21CD20219AEB005BFD43 /* TXCarouselViewDemoUITests.m */; }; 18 | 8F9E21E720219B6F005BFD43 /* TXCarouselCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8F9E21DC20219B6E005BFD43 /* TXCarouselCollectionViewCell.xib */; }; 19 | 8F9E21E820219B6F005BFD43 /* TXCarouselViewLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21DE20219B6E005BFD43 /* TXCarouselViewLayout.m */; }; 20 | 8F9E21E920219B6F005BFD43 /* TXCarouselCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21DF20219B6E005BFD43 /* TXCarouselCellModel.m */; }; 21 | 8F9E21EA20219B6F005BFD43 /* TXCarouselCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21E020219B6E005BFD43 /* TXCarouselCollectionViewCell.m */; }; 22 | 8F9E21EB20219B6F005BFD43 /* TXCarouselView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21E320219B6E005BFD43 /* TXCarouselView.m */; }; 23 | 8F9E21F020219C18005BFD43 /* CarouselImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21ED20219C17005BFD43 /* CarouselImageCell.m */; }; 24 | 8F9E21F120219C18005BFD43 /* CarouselImageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8F9E21EE20219C17005BFD43 /* CarouselImageCell.xib */; }; 25 | 8F9E21F520219DC8005BFD43 /* TXTextTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8F9E21F220219DC7005BFD43 /* TXTextTableViewCell.xib */; }; 26 | 8F9E21F620219DC8005BFD43 /* TXTextTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9E21F320219DC8005BFD43 /* TXTextTableViewCell.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 8F9E21BF20219AEB005BFD43 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 8F9E219E20219AEA005BFD43 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 8F9E21A520219AEA005BFD43; 35 | remoteInfo = TXCarouselViewDemo; 36 | }; 37 | 8F9E21CA20219AEB005BFD43 /* PBXContainerItemProxy */ = { 38 | isa = PBXContainerItemProxy; 39 | containerPortal = 8F9E219E20219AEA005BFD43 /* Project object */; 40 | proxyType = 1; 41 | remoteGlobalIDString = 8F9E21A520219AEA005BFD43; 42 | remoteInfo = TXCarouselViewDemo; 43 | }; 44 | /* End PBXContainerItemProxy section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 8F9E21A620219AEA005BFD43 /* TXCarouselViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TXCarouselViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 8F9E21A920219AEA005BFD43 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | 8F9E21AA20219AEA005BFD43 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | 8F9E21AC20219AEA005BFD43 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 51 | 8F9E21AD20219AEA005BFD43 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 52 | 8F9E21B020219AEA005BFD43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 53 | 8F9E21B220219AEA005BFD43 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | 8F9E21B520219AEA005BFD43 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 55 | 8F9E21B720219AEA005BFD43 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 8F9E21B820219AEA005BFD43 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 57 | 8F9E21BE20219AEB005BFD43 /* TXCarouselViewDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TXCarouselViewDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 8F9E21C220219AEB005BFD43 /* TXCarouselViewDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TXCarouselViewDemoTests.m; sourceTree = ""; }; 59 | 8F9E21C420219AEB005BFD43 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | 8F9E21C920219AEB005BFD43 /* TXCarouselViewDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TXCarouselViewDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 8F9E21CD20219AEB005BFD43 /* TXCarouselViewDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TXCarouselViewDemoUITests.m; sourceTree = ""; }; 62 | 8F9E21CF20219AEB005BFD43 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63 | 8F9E21DC20219B6E005BFD43 /* TXCarouselCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TXCarouselCollectionViewCell.xib; sourceTree = ""; }; 64 | 8F9E21DD20219B6E005BFD43 /* TXCarouselViewLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXCarouselViewLayout.h; sourceTree = ""; }; 65 | 8F9E21DE20219B6E005BFD43 /* TXCarouselViewLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXCarouselViewLayout.m; sourceTree = ""; }; 66 | 8F9E21DF20219B6E005BFD43 /* TXCarouselCellModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXCarouselCellModel.m; sourceTree = ""; }; 67 | 8F9E21E020219B6E005BFD43 /* TXCarouselCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXCarouselCollectionViewCell.m; sourceTree = ""; }; 68 | 8F9E21E120219B6E005BFD43 /* TXCarouselCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXCarouselCollectionViewCell.h; sourceTree = ""; }; 69 | 8F9E21E220219B6E005BFD43 /* TXCarouselView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXCarouselView.h; sourceTree = ""; }; 70 | 8F9E21E320219B6E005BFD43 /* TXCarouselView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXCarouselView.m; sourceTree = ""; }; 71 | 8F9E21E620219B6F005BFD43 /* TXCarouselCellModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXCarouselCellModel.h; sourceTree = ""; }; 72 | 8F9E21ED20219C17005BFD43 /* CarouselImageCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CarouselImageCell.m; sourceTree = ""; }; 73 | 8F9E21EE20219C17005BFD43 /* CarouselImageCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CarouselImageCell.xib; sourceTree = ""; }; 74 | 8F9E21EF20219C17005BFD43 /* CarouselImageCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CarouselImageCell.h; sourceTree = ""; }; 75 | 8F9E21F220219DC7005BFD43 /* TXTextTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TXTextTableViewCell.xib; sourceTree = ""; }; 76 | 8F9E21F320219DC8005BFD43 /* TXTextTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXTextTableViewCell.m; sourceTree = ""; }; 77 | 8F9E21F420219DC8005BFD43 /* TXTextTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXTextTableViewCell.h; sourceTree = ""; }; 78 | /* End PBXFileReference section */ 79 | 80 | /* Begin PBXFrameworksBuildPhase section */ 81 | 8F9E21A320219AEA005BFD43 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | 8F9E21BB20219AEB005BFD43 /* Frameworks */ = { 89 | isa = PBXFrameworksBuildPhase; 90 | buildActionMask = 2147483647; 91 | files = ( 92 | ); 93 | runOnlyForDeploymentPostprocessing = 0; 94 | }; 95 | 8F9E21C620219AEB005BFD43 /* Frameworks */ = { 96 | isa = PBXFrameworksBuildPhase; 97 | buildActionMask = 2147483647; 98 | files = ( 99 | ); 100 | runOnlyForDeploymentPostprocessing = 0; 101 | }; 102 | /* End PBXFrameworksBuildPhase section */ 103 | 104 | /* Begin PBXGroup section */ 105 | 8F9E219D20219AEA005BFD43 = { 106 | isa = PBXGroup; 107 | children = ( 108 | 8F9E21A820219AEA005BFD43 /* TXCarouselViewDemo */, 109 | 8F9E21C120219AEB005BFD43 /* TXCarouselViewDemoTests */, 110 | 8F9E21CC20219AEB005BFD43 /* TXCarouselViewDemoUITests */, 111 | 8F9E21A720219AEA005BFD43 /* Products */, 112 | ); 113 | sourceTree = ""; 114 | }; 115 | 8F9E21A720219AEA005BFD43 /* Products */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 8F9E21A620219AEA005BFD43 /* TXCarouselViewDemo.app */, 119 | 8F9E21BE20219AEB005BFD43 /* TXCarouselViewDemoTests.xctest */, 120 | 8F9E21C920219AEB005BFD43 /* TXCarouselViewDemoUITests.xctest */, 121 | ); 122 | name = Products; 123 | sourceTree = ""; 124 | }; 125 | 8F9E21A820219AEA005BFD43 /* TXCarouselViewDemo */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 8F9E21DB20219B3A005BFD43 /* CarouselView */, 129 | 8F9E21A920219AEA005BFD43 /* AppDelegate.h */, 130 | 8F9E21AA20219AEA005BFD43 /* AppDelegate.m */, 131 | 8F9E21AC20219AEA005BFD43 /* ViewController.h */, 132 | 8F9E21AD20219AEA005BFD43 /* ViewController.m */, 133 | 8F9E21EF20219C17005BFD43 /* CarouselImageCell.h */, 134 | 8F9E21ED20219C17005BFD43 /* CarouselImageCell.m */, 135 | 8F9E21EE20219C17005BFD43 /* CarouselImageCell.xib */, 136 | 8F9E21F420219DC8005BFD43 /* TXTextTableViewCell.h */, 137 | 8F9E21F320219DC8005BFD43 /* TXTextTableViewCell.m */, 138 | 8F9E21F220219DC7005BFD43 /* TXTextTableViewCell.xib */, 139 | 8F9E21AF20219AEA005BFD43 /* Main.storyboard */, 140 | 8F9E21B220219AEA005BFD43 /* Assets.xcassets */, 141 | 8F9E21B420219AEA005BFD43 /* LaunchScreen.storyboard */, 142 | 8F9E21B720219AEA005BFD43 /* Info.plist */, 143 | 8F9E21B820219AEA005BFD43 /* main.m */, 144 | ); 145 | path = TXCarouselViewDemo; 146 | sourceTree = ""; 147 | }; 148 | 8F9E21C120219AEB005BFD43 /* TXCarouselViewDemoTests */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 8F9E21C220219AEB005BFD43 /* TXCarouselViewDemoTests.m */, 152 | 8F9E21C420219AEB005BFD43 /* Info.plist */, 153 | ); 154 | path = TXCarouselViewDemoTests; 155 | sourceTree = ""; 156 | }; 157 | 8F9E21CC20219AEB005BFD43 /* TXCarouselViewDemoUITests */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 8F9E21CD20219AEB005BFD43 /* TXCarouselViewDemoUITests.m */, 161 | 8F9E21CF20219AEB005BFD43 /* Info.plist */, 162 | ); 163 | path = TXCarouselViewDemoUITests; 164 | sourceTree = ""; 165 | }; 166 | 8F9E21DB20219B3A005BFD43 /* CarouselView */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | 8F9E21E220219B6E005BFD43 /* TXCarouselView.h */, 170 | 8F9E21E320219B6E005BFD43 /* TXCarouselView.m */, 171 | 8F9E21E120219B6E005BFD43 /* TXCarouselCollectionViewCell.h */, 172 | 8F9E21E020219B6E005BFD43 /* TXCarouselCollectionViewCell.m */, 173 | 8F9E21DC20219B6E005BFD43 /* TXCarouselCollectionViewCell.xib */, 174 | 8F9E21DD20219B6E005BFD43 /* TXCarouselViewLayout.h */, 175 | 8F9E21DE20219B6E005BFD43 /* TXCarouselViewLayout.m */, 176 | 8F9E21E620219B6F005BFD43 /* TXCarouselCellModel.h */, 177 | 8F9E21DF20219B6E005BFD43 /* TXCarouselCellModel.m */, 178 | ); 179 | path = CarouselView; 180 | sourceTree = ""; 181 | }; 182 | /* End PBXGroup section */ 183 | 184 | /* Begin PBXNativeTarget section */ 185 | 8F9E21A520219AEA005BFD43 /* TXCarouselViewDemo */ = { 186 | isa = PBXNativeTarget; 187 | buildConfigurationList = 8F9E21D220219AEB005BFD43 /* Build configuration list for PBXNativeTarget "TXCarouselViewDemo" */; 188 | buildPhases = ( 189 | 8F9E21A220219AEA005BFD43 /* Sources */, 190 | 8F9E21A320219AEA005BFD43 /* Frameworks */, 191 | 8F9E21A420219AEA005BFD43 /* Resources */, 192 | ); 193 | buildRules = ( 194 | ); 195 | dependencies = ( 196 | ); 197 | name = TXCarouselViewDemo; 198 | productName = TXCarouselViewDemo; 199 | productReference = 8F9E21A620219AEA005BFD43 /* TXCarouselViewDemo.app */; 200 | productType = "com.apple.product-type.application"; 201 | }; 202 | 8F9E21BD20219AEB005BFD43 /* TXCarouselViewDemoTests */ = { 203 | isa = PBXNativeTarget; 204 | buildConfigurationList = 8F9E21D520219AEB005BFD43 /* Build configuration list for PBXNativeTarget "TXCarouselViewDemoTests" */; 205 | buildPhases = ( 206 | 8F9E21BA20219AEB005BFD43 /* Sources */, 207 | 8F9E21BB20219AEB005BFD43 /* Frameworks */, 208 | 8F9E21BC20219AEB005BFD43 /* Resources */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | 8F9E21C020219AEB005BFD43 /* PBXTargetDependency */, 214 | ); 215 | name = TXCarouselViewDemoTests; 216 | productName = TXCarouselViewDemoTests; 217 | productReference = 8F9E21BE20219AEB005BFD43 /* TXCarouselViewDemoTests.xctest */; 218 | productType = "com.apple.product-type.bundle.unit-test"; 219 | }; 220 | 8F9E21C820219AEB005BFD43 /* TXCarouselViewDemoUITests */ = { 221 | isa = PBXNativeTarget; 222 | buildConfigurationList = 8F9E21D820219AEB005BFD43 /* Build configuration list for PBXNativeTarget "TXCarouselViewDemoUITests" */; 223 | buildPhases = ( 224 | 8F9E21C520219AEB005BFD43 /* Sources */, 225 | 8F9E21C620219AEB005BFD43 /* Frameworks */, 226 | 8F9E21C720219AEB005BFD43 /* Resources */, 227 | ); 228 | buildRules = ( 229 | ); 230 | dependencies = ( 231 | 8F9E21CB20219AEB005BFD43 /* PBXTargetDependency */, 232 | ); 233 | name = TXCarouselViewDemoUITests; 234 | productName = TXCarouselViewDemoUITests; 235 | productReference = 8F9E21C920219AEB005BFD43 /* TXCarouselViewDemoUITests.xctest */; 236 | productType = "com.apple.product-type.bundle.ui-testing"; 237 | }; 238 | /* End PBXNativeTarget section */ 239 | 240 | /* Begin PBXProject section */ 241 | 8F9E219E20219AEA005BFD43 /* Project object */ = { 242 | isa = PBXProject; 243 | attributes = { 244 | LastUpgradeCheck = 0900; 245 | ORGANIZATIONNAME = "新华龙mac"; 246 | TargetAttributes = { 247 | 8F9E21A520219AEA005BFD43 = { 248 | CreatedOnToolsVersion = 9.0; 249 | ProvisioningStyle = Manual; 250 | }; 251 | 8F9E21BD20219AEB005BFD43 = { 252 | CreatedOnToolsVersion = 9.0; 253 | ProvisioningStyle = Automatic; 254 | TestTargetID = 8F9E21A520219AEA005BFD43; 255 | }; 256 | 8F9E21C820219AEB005BFD43 = { 257 | CreatedOnToolsVersion = 9.0; 258 | ProvisioningStyle = Automatic; 259 | TestTargetID = 8F9E21A520219AEA005BFD43; 260 | }; 261 | }; 262 | }; 263 | buildConfigurationList = 8F9E21A120219AEA005BFD43 /* Build configuration list for PBXProject "TXCarouselViewDemo" */; 264 | compatibilityVersion = "Xcode 8.0"; 265 | developmentRegion = en; 266 | hasScannedForEncodings = 0; 267 | knownRegions = ( 268 | en, 269 | Base, 270 | ); 271 | mainGroup = 8F9E219D20219AEA005BFD43; 272 | productRefGroup = 8F9E21A720219AEA005BFD43 /* Products */; 273 | projectDirPath = ""; 274 | projectRoot = ""; 275 | targets = ( 276 | 8F9E21A520219AEA005BFD43 /* TXCarouselViewDemo */, 277 | 8F9E21BD20219AEB005BFD43 /* TXCarouselViewDemoTests */, 278 | 8F9E21C820219AEB005BFD43 /* TXCarouselViewDemoUITests */, 279 | ); 280 | }; 281 | /* End PBXProject section */ 282 | 283 | /* Begin PBXResourcesBuildPhase section */ 284 | 8F9E21A420219AEA005BFD43 /* Resources */ = { 285 | isa = PBXResourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | 8F9E21E720219B6F005BFD43 /* TXCarouselCollectionViewCell.xib in Resources */, 289 | 8F9E21B620219AEA005BFD43 /* LaunchScreen.storyboard in Resources */, 290 | 8F9E21F520219DC8005BFD43 /* TXTextTableViewCell.xib in Resources */, 291 | 8F9E21B320219AEA005BFD43 /* Assets.xcassets in Resources */, 292 | 8F9E21F120219C18005BFD43 /* CarouselImageCell.xib in Resources */, 293 | 8F9E21B120219AEA005BFD43 /* Main.storyboard in Resources */, 294 | ); 295 | runOnlyForDeploymentPostprocessing = 0; 296 | }; 297 | 8F9E21BC20219AEB005BFD43 /* Resources */ = { 298 | isa = PBXResourcesBuildPhase; 299 | buildActionMask = 2147483647; 300 | files = ( 301 | ); 302 | runOnlyForDeploymentPostprocessing = 0; 303 | }; 304 | 8F9E21C720219AEB005BFD43 /* Resources */ = { 305 | isa = PBXResourcesBuildPhase; 306 | buildActionMask = 2147483647; 307 | files = ( 308 | ); 309 | runOnlyForDeploymentPostprocessing = 0; 310 | }; 311 | /* End PBXResourcesBuildPhase section */ 312 | 313 | /* Begin PBXSourcesBuildPhase section */ 314 | 8F9E21A220219AEA005BFD43 /* Sources */ = { 315 | isa = PBXSourcesBuildPhase; 316 | buildActionMask = 2147483647; 317 | files = ( 318 | 8F9E21F020219C18005BFD43 /* CarouselImageCell.m in Sources */, 319 | 8F9E21EA20219B6F005BFD43 /* TXCarouselCollectionViewCell.m in Sources */, 320 | 8F9E21EB20219B6F005BFD43 /* TXCarouselView.m in Sources */, 321 | 8F9E21E820219B6F005BFD43 /* TXCarouselViewLayout.m in Sources */, 322 | 8F9E21E920219B6F005BFD43 /* TXCarouselCellModel.m in Sources */, 323 | 8F9E21AE20219AEA005BFD43 /* ViewController.m in Sources */, 324 | 8F9E21B920219AEA005BFD43 /* main.m in Sources */, 325 | 8F9E21F620219DC8005BFD43 /* TXTextTableViewCell.m in Sources */, 326 | 8F9E21AB20219AEA005BFD43 /* AppDelegate.m in Sources */, 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | }; 330 | 8F9E21BA20219AEB005BFD43 /* Sources */ = { 331 | isa = PBXSourcesBuildPhase; 332 | buildActionMask = 2147483647; 333 | files = ( 334 | 8F9E21C320219AEB005BFD43 /* TXCarouselViewDemoTests.m in Sources */, 335 | ); 336 | runOnlyForDeploymentPostprocessing = 0; 337 | }; 338 | 8F9E21C520219AEB005BFD43 /* Sources */ = { 339 | isa = PBXSourcesBuildPhase; 340 | buildActionMask = 2147483647; 341 | files = ( 342 | 8F9E21CE20219AEB005BFD43 /* TXCarouselViewDemoUITests.m in Sources */, 343 | ); 344 | runOnlyForDeploymentPostprocessing = 0; 345 | }; 346 | /* End PBXSourcesBuildPhase section */ 347 | 348 | /* Begin PBXTargetDependency section */ 349 | 8F9E21C020219AEB005BFD43 /* PBXTargetDependency */ = { 350 | isa = PBXTargetDependency; 351 | target = 8F9E21A520219AEA005BFD43 /* TXCarouselViewDemo */; 352 | targetProxy = 8F9E21BF20219AEB005BFD43 /* PBXContainerItemProxy */; 353 | }; 354 | 8F9E21CB20219AEB005BFD43 /* PBXTargetDependency */ = { 355 | isa = PBXTargetDependency; 356 | target = 8F9E21A520219AEA005BFD43 /* TXCarouselViewDemo */; 357 | targetProxy = 8F9E21CA20219AEB005BFD43 /* PBXContainerItemProxy */; 358 | }; 359 | /* End PBXTargetDependency section */ 360 | 361 | /* Begin PBXVariantGroup section */ 362 | 8F9E21AF20219AEA005BFD43 /* Main.storyboard */ = { 363 | isa = PBXVariantGroup; 364 | children = ( 365 | 8F9E21B020219AEA005BFD43 /* Base */, 366 | ); 367 | name = Main.storyboard; 368 | sourceTree = ""; 369 | }; 370 | 8F9E21B420219AEA005BFD43 /* LaunchScreen.storyboard */ = { 371 | isa = PBXVariantGroup; 372 | children = ( 373 | 8F9E21B520219AEA005BFD43 /* Base */, 374 | ); 375 | name = LaunchScreen.storyboard; 376 | sourceTree = ""; 377 | }; 378 | /* End PBXVariantGroup section */ 379 | 380 | /* Begin XCBuildConfiguration section */ 381 | 8F9E21D020219AEB005BFD43 /* Debug */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | ALWAYS_SEARCH_USER_PATHS = NO; 385 | CLANG_ANALYZER_NONNULL = YES; 386 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 387 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 388 | CLANG_CXX_LIBRARY = "libc++"; 389 | CLANG_ENABLE_MODULES = YES; 390 | CLANG_ENABLE_OBJC_ARC = YES; 391 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 392 | CLANG_WARN_BOOL_CONVERSION = YES; 393 | CLANG_WARN_COMMA = YES; 394 | CLANG_WARN_CONSTANT_CONVERSION = YES; 395 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 396 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 397 | CLANG_WARN_EMPTY_BODY = YES; 398 | CLANG_WARN_ENUM_CONVERSION = YES; 399 | CLANG_WARN_INFINITE_RECURSION = YES; 400 | CLANG_WARN_INT_CONVERSION = YES; 401 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 402 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 403 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 404 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 405 | CLANG_WARN_STRICT_PROTOTYPES = YES; 406 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 407 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 408 | CLANG_WARN_UNREACHABLE_CODE = YES; 409 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 410 | CODE_SIGN_IDENTITY = "iPhone Developer"; 411 | COPY_PHASE_STRIP = NO; 412 | DEBUG_INFORMATION_FORMAT = dwarf; 413 | ENABLE_STRICT_OBJC_MSGSEND = YES; 414 | ENABLE_TESTABILITY = YES; 415 | GCC_C_LANGUAGE_STANDARD = gnu11; 416 | GCC_DYNAMIC_NO_PIC = NO; 417 | GCC_NO_COMMON_BLOCKS = YES; 418 | GCC_OPTIMIZATION_LEVEL = 0; 419 | GCC_PREPROCESSOR_DEFINITIONS = ( 420 | "DEBUG=1", 421 | "$(inherited)", 422 | ); 423 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 424 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 425 | GCC_WARN_UNDECLARED_SELECTOR = YES; 426 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 427 | GCC_WARN_UNUSED_FUNCTION = YES; 428 | GCC_WARN_UNUSED_VARIABLE = YES; 429 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 430 | MTL_ENABLE_DEBUG_INFO = YES; 431 | ONLY_ACTIVE_ARCH = YES; 432 | SDKROOT = iphoneos; 433 | }; 434 | name = Debug; 435 | }; 436 | 8F9E21D120219AEB005BFD43 /* Release */ = { 437 | isa = XCBuildConfiguration; 438 | buildSettings = { 439 | ALWAYS_SEARCH_USER_PATHS = NO; 440 | CLANG_ANALYZER_NONNULL = YES; 441 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 442 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 443 | CLANG_CXX_LIBRARY = "libc++"; 444 | CLANG_ENABLE_MODULES = YES; 445 | CLANG_ENABLE_OBJC_ARC = YES; 446 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 447 | CLANG_WARN_BOOL_CONVERSION = YES; 448 | CLANG_WARN_COMMA = YES; 449 | CLANG_WARN_CONSTANT_CONVERSION = YES; 450 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 451 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 452 | CLANG_WARN_EMPTY_BODY = YES; 453 | CLANG_WARN_ENUM_CONVERSION = YES; 454 | CLANG_WARN_INFINITE_RECURSION = YES; 455 | CLANG_WARN_INT_CONVERSION = YES; 456 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 457 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 458 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 459 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 460 | CLANG_WARN_STRICT_PROTOTYPES = YES; 461 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 462 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 463 | CLANG_WARN_UNREACHABLE_CODE = YES; 464 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 465 | CODE_SIGN_IDENTITY = "iPhone Developer"; 466 | COPY_PHASE_STRIP = NO; 467 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 468 | ENABLE_NS_ASSERTIONS = NO; 469 | ENABLE_STRICT_OBJC_MSGSEND = YES; 470 | GCC_C_LANGUAGE_STANDARD = gnu11; 471 | GCC_NO_COMMON_BLOCKS = YES; 472 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 473 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 474 | GCC_WARN_UNDECLARED_SELECTOR = YES; 475 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 476 | GCC_WARN_UNUSED_FUNCTION = YES; 477 | GCC_WARN_UNUSED_VARIABLE = YES; 478 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 479 | MTL_ENABLE_DEBUG_INFO = NO; 480 | SDKROOT = iphoneos; 481 | VALIDATE_PRODUCT = YES; 482 | }; 483 | name = Release; 484 | }; 485 | 8F9E21D320219AEB005BFD43 /* Debug */ = { 486 | isa = XCBuildConfiguration; 487 | buildSettings = { 488 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 489 | CODE_SIGN_STYLE = Manual; 490 | DEVELOPMENT_TEAM = PN6RFD28L4; 491 | INFOPLIST_FILE = TXCarouselViewDemo/Info.plist; 492 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 493 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 494 | PRODUCT_BUNDLE_IDENTIFIER = com.chongqing.government; 495 | PRODUCT_NAME = "$(TARGET_NAME)"; 496 | PROVISIONING_PROFILE = "15f7b97a-e4c4-45c0-8738-44631e37aab3"; 497 | PROVISIONING_PROFILE_SPECIFIER = ChongqingGovernmentDevelopmentPodfile; 498 | TARGETED_DEVICE_FAMILY = "1,2"; 499 | }; 500 | name = Debug; 501 | }; 502 | 8F9E21D420219AEB005BFD43 /* Release */ = { 503 | isa = XCBuildConfiguration; 504 | buildSettings = { 505 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 506 | CODE_SIGN_STYLE = Manual; 507 | DEVELOPMENT_TEAM = PN6RFD28L4; 508 | INFOPLIST_FILE = TXCarouselViewDemo/Info.plist; 509 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 510 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 511 | PRODUCT_BUNDLE_IDENTIFIER = com.chongqing.government; 512 | PRODUCT_NAME = "$(TARGET_NAME)"; 513 | PROVISIONING_PROFILE = "15f7b97a-e4c4-45c0-8738-44631e37aab3"; 514 | PROVISIONING_PROFILE_SPECIFIER = ChongqingGovernmentDevelopmentPodfile; 515 | TARGETED_DEVICE_FAMILY = "1,2"; 516 | }; 517 | name = Release; 518 | }; 519 | 8F9E21D620219AEB005BFD43 /* Debug */ = { 520 | isa = XCBuildConfiguration; 521 | buildSettings = { 522 | BUNDLE_LOADER = "$(TEST_HOST)"; 523 | CODE_SIGN_STYLE = Automatic; 524 | INFOPLIST_FILE = TXCarouselViewDemoTests/Info.plist; 525 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 526 | PRODUCT_BUNDLE_IDENTIFIER = com.tianxin.TXCarouselViewDemoTests; 527 | PRODUCT_NAME = "$(TARGET_NAME)"; 528 | TARGETED_DEVICE_FAMILY = "1,2"; 529 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TXCarouselViewDemo.app/TXCarouselViewDemo"; 530 | }; 531 | name = Debug; 532 | }; 533 | 8F9E21D720219AEB005BFD43 /* Release */ = { 534 | isa = XCBuildConfiguration; 535 | buildSettings = { 536 | BUNDLE_LOADER = "$(TEST_HOST)"; 537 | CODE_SIGN_STYLE = Automatic; 538 | INFOPLIST_FILE = TXCarouselViewDemoTests/Info.plist; 539 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 540 | PRODUCT_BUNDLE_IDENTIFIER = com.tianxin.TXCarouselViewDemoTests; 541 | PRODUCT_NAME = "$(TARGET_NAME)"; 542 | TARGETED_DEVICE_FAMILY = "1,2"; 543 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TXCarouselViewDemo.app/TXCarouselViewDemo"; 544 | }; 545 | name = Release; 546 | }; 547 | 8F9E21D920219AEB005BFD43 /* Debug */ = { 548 | isa = XCBuildConfiguration; 549 | buildSettings = { 550 | CODE_SIGN_STYLE = Automatic; 551 | INFOPLIST_FILE = TXCarouselViewDemoUITests/Info.plist; 552 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 553 | PRODUCT_BUNDLE_IDENTIFIER = com.tianxin.TXCarouselViewDemoUITests; 554 | PRODUCT_NAME = "$(TARGET_NAME)"; 555 | TARGETED_DEVICE_FAMILY = "1,2"; 556 | TEST_TARGET_NAME = TXCarouselViewDemo; 557 | }; 558 | name = Debug; 559 | }; 560 | 8F9E21DA20219AEB005BFD43 /* Release */ = { 561 | isa = XCBuildConfiguration; 562 | buildSettings = { 563 | CODE_SIGN_STYLE = Automatic; 564 | INFOPLIST_FILE = TXCarouselViewDemoUITests/Info.plist; 565 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 566 | PRODUCT_BUNDLE_IDENTIFIER = com.tianxin.TXCarouselViewDemoUITests; 567 | PRODUCT_NAME = "$(TARGET_NAME)"; 568 | TARGETED_DEVICE_FAMILY = "1,2"; 569 | TEST_TARGET_NAME = TXCarouselViewDemo; 570 | }; 571 | name = Release; 572 | }; 573 | /* End XCBuildConfiguration section */ 574 | 575 | /* Begin XCConfigurationList section */ 576 | 8F9E21A120219AEA005BFD43 /* Build configuration list for PBXProject "TXCarouselViewDemo" */ = { 577 | isa = XCConfigurationList; 578 | buildConfigurations = ( 579 | 8F9E21D020219AEB005BFD43 /* Debug */, 580 | 8F9E21D120219AEB005BFD43 /* Release */, 581 | ); 582 | defaultConfigurationIsVisible = 0; 583 | defaultConfigurationName = Release; 584 | }; 585 | 8F9E21D220219AEB005BFD43 /* Build configuration list for PBXNativeTarget "TXCarouselViewDemo" */ = { 586 | isa = XCConfigurationList; 587 | buildConfigurations = ( 588 | 8F9E21D320219AEB005BFD43 /* Debug */, 589 | 8F9E21D420219AEB005BFD43 /* Release */, 590 | ); 591 | defaultConfigurationIsVisible = 0; 592 | defaultConfigurationName = Release; 593 | }; 594 | 8F9E21D520219AEB005BFD43 /* Build configuration list for PBXNativeTarget "TXCarouselViewDemoTests" */ = { 595 | isa = XCConfigurationList; 596 | buildConfigurations = ( 597 | 8F9E21D620219AEB005BFD43 /* Debug */, 598 | 8F9E21D720219AEB005BFD43 /* Release */, 599 | ); 600 | defaultConfigurationIsVisible = 0; 601 | defaultConfigurationName = Release; 602 | }; 603 | 8F9E21D820219AEB005BFD43 /* Build configuration list for PBXNativeTarget "TXCarouselViewDemoUITests" */ = { 604 | isa = XCConfigurationList; 605 | buildConfigurations = ( 606 | 8F9E21D920219AEB005BFD43 /* Debug */, 607 | 8F9E21DA20219AEB005BFD43 /* Release */, 608 | ); 609 | defaultConfigurationIsVisible = 0; 610 | defaultConfigurationName = Release; 611 | }; 612 | /* End XCConfigurationList section */ 613 | }; 614 | rootObject = 8F9E219E20219AEA005BFD43 /* Project object */; 615 | } 616 | -------------------------------------------------------------------------------- /TXCarouselViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TXCarouselViewDemo.xcodeproj/xcuserdata/xinhualongmac.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /TXCarouselViewDemo.xcodeproj/xcuserdata/xinhualongmac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TXCarouselViewDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TXCarouselViewDemo 4 | // 5 | // Created by 新华龙mac on 2018/1/31. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TXCarouselViewDemo 4 | // 5 | // Created by 新华龙mac on 2018/1/31. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tu.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tu@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tu@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia1.imageset/tu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia1.imageset/tu.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia1.imageset/tu@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia1.imageset/tu@2x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia1.imageset/tu@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia1.imageset/tu@3x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tu.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tu@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tu@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia2.imageset/tu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia2.imageset/tu.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia2.imageset/tu@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia2.imageset/tu@2x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia2.imageset/tu@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia2.imageset/tu@3x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia3.imageset/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia3.imageset/0.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia3.imageset/0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia3.imageset/0@2x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia3.imageset/0@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia3.imageset/0@3x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "0.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "0@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "0@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia4.imageset/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia4.imageset/0.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia4.imageset/0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia4.imageset/0@2x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia4.imageset/0@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia4.imageset/0@3x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "0.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "0@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "0@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia5.imageset/220.webp-(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia5.imageset/220.webp-(1).png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia5.imageset/220.webp-(1)@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia5.imageset/220.webp-(1)@2x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia5.imageset/220.webp-(1)@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianXin123654/TXCarouselView/71a934ab33c14b48dd26738cad1a49f6382b9c17/TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia5.imageset/220.webp-(1)@3x.png -------------------------------------------------------------------------------- /TXCarouselViewDemo/Assets.xcassets/zongshujidaowojia5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "220.webp-(1).png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "220.webp-(1)@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "220.webp-(1)@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TXCarouselViewDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselImageCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TXCustomCarouselCell.h 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/11. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TXCarouselCellModel.h" 11 | @interface CarouselImageCell : UITableViewCell 12 | 13 | /** 14 | configData 15 | 16 | @param modelArray modelArray 17 | @param superScrollView superScrollView 18 | */ 19 | -(void)configData:(NSArray *)modelArray andSuperScrollView:(UIScrollView *)superScrollView; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselImageCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TXCustomCarouselCell.m 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/11. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import "CarouselImageCell.h" 10 | #import "TXCarouselView.h" 11 | 12 | @interface CarouselImageCell() 13 | @property (weak, nonatomic) IBOutlet TXCarouselView *carouselView; 14 | @property (weak, nonatomic) IBOutlet UILabel *title; 15 | @property (weak, nonatomic) IBOutlet UILabel *time; 16 | @property (weak, nonatomic) IBOutlet UILabel *infoLabel; 17 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *infoButtonWidthConstraint; 18 | @property (nonatomic, strong) NSMutableDictionary *carouselDict; 19 | @end 20 | 21 | @implementation CarouselImageCell 22 | 23 | - (void)awakeFromNib { 24 | [super awakeFromNib]; 25 | } 26 | 27 | -(void)configData:(NSArray *)modelArray andSuperScrollView:(UIScrollView *)superScrollView; 28 | { 29 | self.title.text = @"新时代,新地貌新时代,新地貌新时代,新地貌新时代,新地"; 30 | self.time.text = @"2018-01-31"; 31 | self.infoLabel.text = @"TX"; 32 | [self.carouselView setArrayData:modelArray andSuperScrollView:superScrollView]; 33 | [self.carouselView reloadCarouselView]; 34 | } 35 | 36 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 37 | [super setSelected:selected animated:animated]; 38 | 39 | // Configure the view for the selected state 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselImageCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 62 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselView/TXCarouselCellModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TXCarouselCellModel.h 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/10. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | @interface TXCarouselCellModel : NSObject 12 | @property (nonatomic, assign) NSInteger newsId; 13 | @property (nonatomic, strong) NSString *titleStr; 14 | @property (nonatomic, strong) NSString *imageUrl; 15 | @end 16 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselView/TXCarouselCellModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TXCarouselCellModel.m 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/10. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import "TXCarouselCellModel.h" 10 | 11 | @implementation TXCarouselCellModel 12 | -(void)setModel:(TXCarouselCellModel *)model{ 13 | 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselView/TXCarouselCollectionViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TXCustomCollectionViewCell.h 3 | // slidetext 4 | // 5 | // Created by 新华龙mac on 2018/1/16. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TXCarouselCellModel.h" 11 | @interface TXCarouselCollectionViewCell : UICollectionViewCell 12 | @property (weak, nonatomic) IBOutlet UIView *covierView; 13 | 14 | -(void)setCarouselCellModel:(TXCarouselCellModel *)model; 15 | 16 | @property(nonatomic,copy)void(^block)(void); 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselView/TXCarouselCollectionViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TXCustomCollectionViewCell.m 3 | // slidetext 4 | // 5 | // Created by 新华龙mac on 2018/1/16. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import "TXCarouselCollectionViewCell.h" 10 | 11 | @interface TXCarouselCollectionViewCell() 12 | @property (weak, nonatomic) IBOutlet UIImageView *imageView; 13 | @property (weak, nonatomic) IBOutlet UILabel *titleStr; 14 | 15 | @end 16 | 17 | @implementation TXCarouselCollectionViewCell 18 | 19 | - (void)awakeFromNib { 20 | [super awakeFromNib]; 21 | self.layer.shadowRadius = 6.0f; 22 | self.layer.shadowColor = [UIColor blackColor].CGColor; 23 | self.layer.shadowOpacity = 6.0f; 24 | self.layer.shadowOffset = CGSizeMake(0, 0); 25 | self.layer.masksToBounds = NO; 26 | 27 | UIPanGestureRecognizer *ges = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panSild)]; 28 | ges.delegate = self; 29 | [self addGestureRecognizer:ges]; 30 | } 31 | 32 | /** 33 | 解决手势冲突 34 | 35 | @param gestureRecognizer gestureRecognizer 36 | @param otherGestureRecognizer otherGestureRecognizer 37 | @return bool 38 | */ 39 | -(BOOL)gestureRecognizer:(UIGestureRecognizer*) gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer 40 | { 41 | if ([gestureRecognizer.view isKindOfClass:[UICollectionView class]]) { 42 | return NO; 43 | }else{ 44 | return YES; 45 | } 46 | } 47 | 48 | /** 49 | 手势滑动 50 | */ 51 | -(void)panSild 52 | { 53 | if (self.block) {self.block();} 54 | } 55 | 56 | /** 57 | 加载数据 58 | 59 | @param model TXCarouselCellModel 60 | */ 61 | -(void)setCarouselCellModel:(TXCarouselCellModel *)model{ 62 | self.imageView.image = [UIImage imageNamed:model.imageUrl]; 63 | self.titleStr.text = model.titleStr; 64 | } 65 | @end 66 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselView/TXCarouselCollectionViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselView/TXCarouselView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TXCarouselView.h 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/17. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TXCarouselCellModel.h" 11 | 12 | @interface TXCarouselView : UIView 13 | 14 | /** 15 | 配置数据(固定TXCarouselView) 16 | 17 | @param array TXCarouselCellModelArray 18 | */ 19 | -(void)setArrayData:(NSArray *)array; 20 | 21 | /** 22 | 配置数据(滑动TXCarouselView,加在ScrollViewv上时 需要传入) 23 | 24 | @param array TXCarouselCellModelArray 25 | @param superScrollView 父系ScrollView 26 | */ 27 | -(void)setArrayData:(NSArray *)array 28 | andSuperScrollView:(UIScrollView *)superScrollView; 29 | 30 | /** 31 | 刷新CarouselView 32 | */ 33 | -(void)reloadCarouselView; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselView/TXCarouselView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TXCarouselView.m 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/17. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import "TXCarouselView.h" 10 | #import "TXCarouselCollectionViewCell.h" 11 | #import "TXCarouselViewLayout.h" 12 | 13 | #import "TXCarouselCellModel.h" 14 | #import 15 | 16 | #define itemHight 0.8 17 | 18 | //当前 carousel 状态 19 | @interface carouselCurrentState : NSObject 20 | @property (nonatomic, assign) BOOL isOverturnState; //是否进入翻转状态 21 | @property (nonatomic, assign) BOOL isDragState; //是否处于拖动状态 22 | @property (nonatomic, assign) BOOL isDidScroll; //是否处于滑动状态 23 | @property (nonatomic, assign) BOOL isCenter; //是否处于回到正中状态 24 | @property (nonatomic, assign) BOOL isRestrict; //是否处于限制重力感应 25 | @property (nonatomic, assign) CGFloat lastCarouselPoint;//上一个lastPoint 26 | 27 | @end 28 | 29 | @implementation carouselCurrentState 30 | @end 31 | 32 | typedef void (^OpenAccelerometerUpdatesBlock)(CGFloat value); 33 | typedef void (^OpenGyroUpdatesBlock)(CGFloat value); 34 | 35 | @interface TXCarouselView ()< 36 | UICollectionViewDelegateFlowLayout, 37 | UICollectionViewDataSource, 38 | UICollectionViewDelegate, 39 | UIScrollViewDelegate 40 | > 41 | 42 | @property (nonatomic, strong) TXCarouselViewLayout *carouselViewLayout; 43 | @property (nonatomic, strong) carouselCurrentState *currentState;//当前 carousel 状态 44 | @property (nonatomic, strong) UIScrollView *superScrollView; 45 | @property (nonatomic, strong) CMMotionManager *motionManager; 46 | @property (nonatomic, strong) UICollectionView *collectionView; 47 | @property (nonatomic, strong) NSMutableArray *modelArray; 48 | @property (nonatomic, assign) CGFloat lasttimePoint; 49 | @property (nonatomic, assign) CGFloat gyrValue;//加速计值 50 | @property (nonatomic, assign) CGSize carouselSize; 51 | 52 | @end 53 | 54 | @implementation TXCarouselView 55 | 56 | #pragma mark - 生命周期 57 | - (instancetype)initWithCoder:(NSCoder *)coder 58 | { 59 | self = [super initWithCoder:coder]; 60 | if (self) { 61 | UIViewController *vc = [self getTopViewController]; 62 | for (id type1 in vc.view.subviews) { 63 | if ([type1 isKindOfClass:[UITableView class]]) { 64 | UITableView *table = (UITableView *)type1; 65 | UILongPressGestureRecognizer *tag = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(tapGes:)]; 66 | [table addGestureRecognizer:tag]; 67 | } 68 | } 69 | self.currentState = [[carouselCurrentState alloc]init]; 70 | self.currentState.isOverturnState = NO; 71 | self.currentState.isDragState = NO; 72 | self.currentState.isDidScroll = NO; 73 | self.currentState.isCenter = NO; 74 | self.currentState.isRestrict = NO; 75 | [self openMotionManager]; 76 | [self creatUIRunloopObserver:kCFRunLoopExit]; 77 | 78 | //如果tableview 加载多个TXCarouselView的时候,最好实现以下几个通知,当cell 消失的时候关闭当前cell 上的重力感应. 79 | //关闭当前消失cell上的重力感应, 80 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeAssignManager:) name:@"closeAssignManager" object:nil]; 81 | //开启当前出现cell上的重力感应, 82 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(openAssignManager:) name:@"openAssignManager" object:nil]; 83 | //限制重力感应 84 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(turnDowntGyroUpdates) name:@"turnDowntGyroUpdates" object:nil]; 85 | //解除限制重力感应 86 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startGyroUpdates) name:@"startGyroUpdates" object:nil]; 87 | 88 | } 89 | return self; 90 | } 91 | -(instancetype)initWithFrame:(CGRect)frame 92 | { 93 | self = [super initWithFrame:frame]; 94 | if (self) { 95 | 96 | } 97 | return self; 98 | } 99 | 100 | -(void)layoutSubviews 101 | { 102 | self.carouselSize = self.frame.size; 103 | [self createCollectionView]; 104 | [self.collectionView reloadData]; 105 | [self.collectionView layoutIfNeeded]; 106 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 107 | [self setpoint]; 108 | }); 109 | } 110 | 111 | -(void)setpoint{ 112 | [self.collectionView setContentOffset:CGPointMake(0, self.collectionView.contentOffset.y) animated:NO]; 113 | [self.collectionView setContentOffset:CGPointMake(0+((self.modelArray.count/2)*(self.carouselSize.height*itemHight)), self.collectionView.contentOffset.y) animated:NO]; 114 | self.currentState.lastCarouselPoint = 0; 115 | [self setSlideEnd]; 116 | } 117 | 118 | - (void)dealloc 119 | { 120 | _motionManager = nil; 121 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 122 | } 123 | 124 | #pragma mark - loadData 125 | -(void)setArrayData:(NSArray *)array{ 126 | [self.modelArray removeAllObjects]; 127 | //如果有数据情况下创建10轮数据用作无限循环(UIcllectView有复用机制不用担心数据过多引起卡顿) 128 | //我并没有采用正经的无线循环方式->(前后面加数据的方式,那是大神处理的事情,我暂时没有去采用那种方式) 129 | if (array.count<=0) { 130 | return; 131 | } 132 | [self.modelArray addObjectsFromArray:array]; 133 | NSInteger index = 10; 134 | for (int i = 0; i500) { 136 | return; 137 | } 138 | [self.modelArray addObjectsFromArray:self.modelArray]; 139 | } 140 | } 141 | 142 | -(void)setArrayData:(NSArray *)array andSuperScrollView:(UIScrollView *)superScrollView 143 | { 144 | 145 | [self.modelArray removeAllObjects]; 146 | if (array.count<=0) { 147 | return; 148 | } 149 | [self.modelArray addObjectsFromArray:array]; 150 | NSInteger index = 10; 151 | for (int i = 0; i(self.modelArray.count*self.frame.size.height*itemHight)-500){ 194 | CGPoint point = CGPointMake(0+(self.modelArray.count/2*self.frame.size.height*itemHight), 195 | self.collectionView.contentOffset.y); 196 | [self.collectionView setContentOffset:point animated:NO]; 197 | } 198 | 199 | } 200 | 201 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 202 | __weak typeof(self) weakSelf = self; 203 | TXCarouselCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TXCarouselCollectionViewCell" forIndexPath:indexPath]; 204 | [cell setCarouselCellModel:self.modelArray[indexPath.row]]; 205 | [cell setBlock:^{ 206 | weakSelf.currentState.isDragState = YES; 207 | weakSelf.currentState.isCenter = NO; 208 | }]; 209 | return cell; 210 | } 211 | 212 | #pragma mark - privately method 213 | /** 214 | 计算滑动的距离,然后计算collectionView的偏移量 215 | 216 | @param index index 217 | */ 218 | -(void)setSlideDistance:(CGFloat)index{ 219 | self.currentState.isCenter = NO; 220 | self.currentState.isDidScroll = YES; 221 | CGFloat indexContentOffset = self.collectionView.contentOffset.x; 222 | indexContentOffset+=((index-self.lasttimePoint))*0.8; 223 | [self.collectionView setContentOffset:CGPointMake(indexContentOffset, 0) animated:NO]; 224 | self.lasttimePoint = index; 225 | } 226 | 227 | /** 228 | 回到屏幕正中间 229 | */ 230 | -(void)setSlideEnd{ 231 | CGPoint collectionViewPoint = self.collectionView.contentOffset; 232 | if ( self.currentState.lastCarouselPoint == collectionViewPoint.x|| 233 | self.currentState.isDragState 234 | ) { 235 | return; 236 | } 237 | CGFloat viewHeight = CGRectGetWidth(self.collectionView.frame); 238 | CGFloat itemHeight = self.carouselSize.height*itemHight; 239 | CGFloat index = roundf((self.collectionView.contentOffset.x+ viewHeight / 2 - itemHeight / 2) /itemHeight); 240 | collectionViewPoint.x = itemHeight * index + itemHeight / 2 - viewHeight / 2; 241 | 242 | [self.collectionView setContentOffset:CGPointMake(collectionViewPoint.x, collectionViewPoint.y) animated:YES]; 243 | self.currentState.lastCarouselPoint = self.collectionView.contentOffset.x; 244 | self.currentState.isDidScroll = NO; 245 | } 246 | 247 | - (UIViewController*)getTopViewController { 248 | UIViewController *rootVc = [UIApplication sharedApplication].keyWindow.rootViewController; 249 | return [self topViewControllerWithRootViewController:rootVc]; 250 | } 251 | 252 | - (UIViewController *)topViewControllerWithRootViewController:(UIViewController*)rootViewController { 253 | if ([rootViewController isKindOfClass:[UITabBarController class]]) { 254 | UITabBarController* tabBarController = (UITabBarController*)rootViewController; 255 | return [self topViewControllerWithRootViewController:tabBarController.selectedViewController]; 256 | } else if ([rootViewController isKindOfClass:[UINavigationController class]]) { 257 | UINavigationController* nav = (UINavigationController*)rootViewController; 258 | return [self topViewControllerWithRootViewController:nav.visibleViewController]; 259 | } else if (rootViewController.presentedViewController) { 260 | UIViewController* presentedViewController = rootViewController.presentedViewController; 261 | return [self topViewControllerWithRootViewController:presentedViewController]; 262 | } else { 263 | return rootViewController; 264 | } 265 | } 266 | 267 | #pragma mark - 通知 268 | -(void)turnDowntGyroUpdates{ 269 | self.currentState.isRestrict = YES; 270 | } 271 | -(void)startGyroUpdates{ 272 | self.currentState.isRestrict = NO; 273 | } 274 | 275 | -(void)openAssignManager:(NSNotification *)notification{ 276 | [self openMotionManager]; 277 | } 278 | 279 | -(void)closeAssignManager:(NSNotification *)notification 280 | { 281 | [self closeAllManager]; 282 | 283 | } 284 | 285 | /** 286 | 手势优先级 287 | 288 | @param longGesture longGesture 289 | */ 290 | -(void)tapGes:(UILongPressGestureRecognizer *)longGesture{ 291 | self.currentState.isDragState = YES; 292 | if (longGesture.state == UIGestureRecognizerStateEnded){ 293 | self.currentState.isDragState = YES; 294 | } 295 | } 296 | 297 | /** 298 | 父视图滑动的距离 299 | 300 | @param notification notification 301 | */ 302 | -(void)slideDistance:(NSNotification *)notification{ 303 | NSString *str = notification.userInfo[@"scrollViewcontentOffset"]; 304 | CGFloat index = [str doubleValue]; 305 | [self setSlideDistance:index]; 306 | } 307 | 308 | /** 309 | 结束滑动后计算图片的正中偏移量 310 | 311 | @param notification isEnd 312 | */ 313 | -(void)setScrollViewSlideEnd:(NSNotification *)notification{ 314 | self.currentState.isDragState = NO; 315 | [self setSlideEnd]; 316 | } 317 | 318 | #pragma mark - 监听 319 | /** 320 | 建立对外层ScrollView的监听 321 | */ 322 | -(void)addSuperScrollViewKvo 323 | { 324 | [self.superScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; 325 | } 326 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context { 327 | if (object == self.superScrollView) { 328 | CGPoint point=[((NSValue *)[self.superScrollView  valueForKey:@"contentOffset"]) CGPointValue]; 329 | [self setSlideDistance:point.y]; 330 | } 331 | } 332 | - (void)creatUIRunloopObserver:(CFOptionFlags)flag { 333 | CFRunLoopRef runLoop = CFRunLoopGetCurrent(); 334 | CFStringRef runLoopMode = (__bridge CFStringRef)UITrackingRunLoopMode; 335 | CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, flag, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity _activity) { 336 | switch (_activity) { 337 | case kCFRunLoopEntry: { 338 | NSLog(@"即将进入Loop"); 339 | } 340 | break; 341 | case kCFRunLoopBeforeTimers: { 342 | NSLog(@"即将处理 Timer"); 343 | break; 344 | } 345 | case kCFRunLoopBeforeSources: 346 | NSLog(@"即将处理 Source"); 347 | break; 348 | case kCFRunLoopBeforeWaiting: 349 | NSLog(@"即将进入休眠"); 350 | break; 351 | case kCFRunLoopAfterWaiting: 352 | NSLog(@"刚从休眠中唤醒"); 353 | break; 354 | case kCFRunLoopExit: 355 | NSLog(@"UITracking 即将退出Loop"); 356 | self.currentState.isOverturnState = NO; 357 | self.currentState.isDragState = NO; 358 | self.currentState.isDidScroll = NO; 359 | self.currentState.isCenter = NO; 360 | self.currentState.isRestrict = NO; 361 | self.currentState.lastCarouselPoint = 0.0f; 362 | [self setSlideEnd]; 363 | break; 364 | default: 365 | break; 366 | } 367 | }); 368 | 369 | CFRunLoopAddObserver(runLoop, observer, runLoopMode); 370 | } 371 | 372 | 373 | #pragma mark - 重力感应 374 | -(void)openMotionManager{ 375 | __weak typeof(self) weakSelf = self; 376 | [self startGyroUpdates:^(CGFloat value) { 377 | weakSelf.gyrValue = value; 378 | 379 | }]; 380 | [self startAccelerometerUpdates:^(CGFloat value) { 381 | //1.进入翻转状态 382 | if (fabs(value)>0.05){ 383 | weakSelf.currentState.isOverturnState = YES; 384 | }else{ 385 | weakSelf.currentState.isOverturnState = NO; 386 | if (!weakSelf.currentState.isDragState&& 387 | !weakSelf.currentState.isDidScroll&& 388 | !weakSelf.currentState.isCenter) { 389 | self.currentState.isCenter = YES; 390 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 391 | [weakSelf setSlideEnd]; 392 | }); 393 | } 394 | } 395 | [weakSelf setGyroUpdatesValue]; 396 | }]; 397 | } 398 | 399 | -(void)setGyroUpdatesValue 400 | { 401 | if (self.currentState.isDragState|| 402 | !self.currentState.isOverturnState|| 403 | self.currentState.isDidScroll|| 404 | self.currentState.isRestrict) { 405 | return; 406 | } 407 | 408 | NSLog(@"重力感应开始滑动"); 409 | self.currentState.isCenter = NO; 410 | CGFloat indexContentOffset = self.collectionView.contentOffset.x; 411 | [self.collectionView setContentOffset:CGPointMake(indexContentOffset+self.gyrValue*3, 0) animated:NO]; 412 | 413 | } 414 | 415 | -(void)startAccelerometerUpdates:(OpenAccelerometerUpdatesBlock)result{ 416 | if (![self.motionManager isAccelerometerAvailable]) { 417 | NSLog(@"陀螺仪不可用"); 418 | return; 419 | } 420 | [self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) { 421 | result(accelerometerData.acceleration.x); 422 | }]; 423 | } 424 | 425 | - (void)startGyroUpdates:(OpenGyroUpdatesBlock)result{ 426 | 427 | if (![self.motionManager isGyroAvailable]) { 428 | NSLog(@"加速计不可用"); 429 | return; 430 | } 431 | [self.motionManager startGyroUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMGyroData * _Nullable gyroData, NSError * _Nullable error) { 432 | result(gyroData.rotationRate.y); 433 | }]; 434 | } 435 | 436 | //关闭陀螺仪 437 | -(void)closeAccelerometerUpdates{ 438 | [self.motionManager stopAccelerometerUpdates]; 439 | } 440 | 441 | //关闭加速计 442 | -(void)closeGyroUpdates{ 443 | [self.motionManager stopGyroUpdates]; 444 | } 445 | 446 | //关闭所有 447 | -(void)closeAllManager{ 448 | [self.motionManager stopAccelerometerUpdates]; 449 | [self.motionManager stopGyroUpdates]; 450 | } 451 | 452 | #pragma mark - Lazy 453 | -(CMMotionManager *)motionManager { 454 | if (!_motionManager) { 455 | _motionManager = [[CMMotionManager alloc] init]; 456 | _motionManager.deviceMotionUpdateInterval = 0.1; 457 | } 458 | return _motionManager; 459 | } 460 | 461 | -(TXCarouselViewLayout *)carouselViewLayout{ 462 | if (!_carouselViewLayout) { 463 | CGFloat itemsHeight = self.carouselSize.height*itemHight; 464 | _carouselViewLayout = [[TXCarouselViewLayout alloc] init]; 465 | _carouselViewLayout.itemSize = CGSizeMake(itemsHeight, itemsHeight); 466 | _carouselViewLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 467 | } 468 | return _carouselViewLayout; 469 | } 470 | 471 | -(void)createCollectionView{ 472 | if (!self.collectionView) { 473 | self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width,self.frame.size.height ) collectionViewLayout:self.carouselViewLayout]; 474 | self.collectionView.dataSource = self; 475 | self.collectionView.delegate = self; 476 | self.collectionView.pagingEnabled = NO; 477 | self.collectionView.showsVerticalScrollIndicator = NO; 478 | self.collectionView.showsHorizontalScrollIndicator = NO; 479 | [self.collectionView registerNib:[UINib nibWithNibName:@"TXCarouselCollectionViewCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:@"TXCarouselCollectionViewCell"]; 480 | self.collectionView.backgroundColor = [UIColor whiteColor]; 481 | [self addSubview:self.collectionView]; 482 | } 483 | } 484 | 485 | -(NSMutableArray *)modelArray 486 | { 487 | if (!_modelArray) { 488 | _modelArray = [[NSMutableArray alloc]init]; 489 | } 490 | return _modelArray; 491 | } 492 | 493 | @end 494 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselView/TXCarouselViewLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // TXCarouselViewLayout.h 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/17. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TXCarouselViewLayout : UICollectionViewLayout 12 | @property (nonatomic) CGSize itemSize; 13 | @property (nonatomic) NSInteger visibleCount; 14 | @property (nonatomic) UICollectionViewScrollDirection scrollDirection; 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/CarouselView/TXCarouselViewLayout.m: -------------------------------------------------------------------------------- 1 | // 2 | // TXCarouselViewLayout.m 3 | // HJCarouselDemo 4 | // 5 | // Created by 新华龙mac on 2018/1/17. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import "TXCarouselViewLayout.h" 10 | 11 | #define INTERSPACEPARAM 0.90 12 | @interface TXCarouselViewLayout () 13 | @property (nonatomic, assign) CGFloat viewHeight; 14 | @property (nonatomic, assign) CGFloat itemHeight; 15 | @property (nonatomic, assign) CGFloat lastDirectionIndex; 16 | @property (nonatomic, assign) CGFloat slidDistance; 17 | @property (nonatomic, strong) NSIndexPath *lastIndexOne; 18 | @end 19 | 20 | @implementation TXCarouselViewLayout 21 | 22 | - (void)prepareLayout { 23 | [super prepareLayout]; 24 | self.visibleCount = 7; 25 | self.viewHeight = CGRectGetWidth(self.collectionView.frame); 26 | self.itemHeight = self.itemSize.width; 27 | } 28 | 29 | - (CGSize)collectionViewContentSize { 30 | NSInteger cellCount = [self.collectionView numberOfItemsInSection:0]; 31 | if (self.scrollDirection == UICollectionViewScrollDirectionVertical) { 32 | return CGSizeMake(CGRectGetWidth(self.collectionView.frame), cellCount * self.itemHeight); 33 | } 34 | return CGSizeMake(cellCount * self.itemHeight, CGRectGetHeight(self.collectionView.frame)); 35 | } 36 | 37 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { 38 | NSInteger cellCount = [self.collectionView numberOfItemsInSection:0]; 39 | CGFloat centerY = self.collectionView.contentOffset.x + self.viewHeight / 2; 40 | NSInteger index = centerY / self.itemHeight; 41 | NSInteger count = (self.visibleCount - 1) / 2; 42 | NSInteger minIndex = MAX(0, (index - count)); 43 | NSInteger maxIndex = MIN((cellCount - 1), (index + count)); 44 | NSMutableArray *array = [NSMutableArray array]; 45 | for (NSInteger i = minIndex; i <= maxIndex; i++) { 46 | NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; 47 | UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath]; 48 | [array addObject:attributes]; 49 | } 50 | return array; 51 | } 52 | 53 | - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { 54 | UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 55 | attributes.size = self.itemSize; 56 | CGFloat cY = self.collectionView.contentOffset.x + self.viewHeight / 2; 57 | CGFloat attributesY = self.itemHeight * indexPath.row + self.itemHeight / 2;// 58 | attributes.zIndex = -ABS(attributesY - cY); 59 | CGFloat delta = cY - attributesY; 60 | CGFloat ratio = - delta / (self.itemHeight * 2); 61 | CGFloat scale = 1 - ABS(delta) / (self.itemHeight * 6.0) * cos(ratio * M_2_PI*0.9); 62 | attributes.transform = CGAffineTransformMakeScale(scale, scale); 63 | CGFloat centerY = attributesY; 64 | // NSLog(@"scale= %f",scale); 65 | // NSLog(@"indexPath = %ld",(long)indexPath.row); 66 | // NSLog(@"self.lastIndexOne = %ld",(long)self.lastIndexOne.row); 67 | if (scale>0.999){//滑动到最前面时, 交换持有者 68 | self.lastIndexOne = indexPath; 69 | } 70 | if (self.lastIndexOne == indexPath) { 71 | CGFloat index1 = 0.0f; 72 | if ([self judgeDirection:centerY]) { 73 | index1 = 2; 74 | }else{ 75 | index1 = -2; 76 | } 77 | centerY = cY + sin(ratio * 1.31) * self.itemHeight * INTERSPACEPARAM*2.2+index1; 78 | //双保险,如果滑动急快的情况下,方法没有获取到最高点的坐标会导致判断失败scale>0.999 实效, 79 | //所以启用判断scale <= 0.84加以纠正。(且只有在上述方法实效的情况下调用,所以不能使用|| ,不然有冲突,) 80 | if (scale <= 0.84){ 81 | if ([self judgeDirection:centerY]) { 82 | NSIndexPath *indexNext = [NSIndexPath indexPathForRow:self.lastIndexOne.row+1 inSection:0]; 83 | self.lastIndexOne = indexNext; 84 | }else{ 85 | NSIndexPath *indexNext = [NSIndexPath indexPathForRow:self.lastIndexOne.row-1 inSection:0]; 86 | self.lastIndexOne = indexNext; 87 | } 88 | } 89 | if (scale <=0.9172) { 90 | CGFloat sinIndex = sin(ratio * 1.31) * self.itemHeight * INTERSPACEPARAM*2.7+index1; 91 | if ([self judgeDirection:centerY]) { 92 | centerY = centerY-(sinIndex+(self.itemSize.width*96/124)); 93 | 94 | }else{ 95 | centerY = centerY-(sinIndex-(self.itemSize.width*96/124)); 96 | } 97 | } 98 | self.lastDirectionIndex = centerY; 99 | }else{ 100 | centerY = cY + sin(ratio * 1.217) * self.itemHeight * INTERSPACEPARAM; 101 | } 102 | attributes.center = CGPointMake(centerY, CGRectGetHeight(self.collectionView.frame) / 2); 103 | return attributes; 104 | } 105 | 106 | - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity { 107 | CGFloat index = roundf((proposedContentOffset.x+ self.viewHeight / 2 - self.itemHeight / 2) / self.itemHeight); 108 | proposedContentOffset.x = self.itemHeight * index + self.itemHeight / 2 - self.viewHeight / 2; 109 | return proposedContentOffset; 110 | } 111 | 112 | //判断滑动的方向(yes往左,no为右); 113 | -(BOOL)judgeDirection:(CGFloat )index{ 114 | if (self.lastDirectionIndex>index) { 115 | return YES; 116 | }else{ 117 | return NO; 118 | } 119 | } 120 | 121 | - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { 122 | return YES; 123 | } 124 | 125 | @end 126 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/TXTextTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TXTextTableViewCell.h 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/19. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TXTextTableViewCell : UITableViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/TXTextTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TXTextTableViewCell.m 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/19. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import "TXTextTableViewCell.h" 10 | 11 | @implementation TXTextTableViewCell 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | // Initialization code 16 | } 17 | 18 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 19 | [super setSelected:selected animated:animated]; 20 | 21 | // Configure the view for the selected state 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/TXTextTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TXCarouselViewDemo 4 | // 5 | // Created by 新华龙mac on 2018/1/31. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /TXCarouselViewDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // textView 4 | // 5 | // Created by 新华龙mac on 2018/1/10. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "TXCarouselCellModel.h" 11 | #import "CarouselImageCell.h" 12 | #import "TXTextTableViewCell.h" 13 | 14 | #define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width) 15 | #define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height) 16 | 17 | @interface ViewController () 18 | @property (nonatomic, strong) NSMutableArray *array; 19 | @property (nonatomic, strong) UITableView *tableView; 20 | 21 | @end 22 | 23 | @implementation ViewController 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | [self.view addSubview:self.tableView]; 28 | NSArray *arrayStr = [NSArray arrayWithObjects: 29 | @"1111111111111111111111111111111111111111111111", 30 | @"2222222222222222222222222222222222222222222222", 31 | @"3333333333333333333333333333333333333333333333", 32 | @"4444444444444444444444444444444444444444444444", 33 | @"5555555555555555555555555555555555555555555555", 34 | nil]; 35 | for (int i = 0; i 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TXCarouselViewDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TXCarouselViewDemoTests/TXCarouselViewDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TXCarouselViewDemoTests.m 3 | // TXCarouselViewDemoTests 4 | // 5 | // Created by 新华龙mac on 2018/1/31. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TXCarouselViewDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation TXCarouselViewDemoTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /TXCarouselViewDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TXCarouselViewDemoUITests/TXCarouselViewDemoUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TXCarouselViewDemoUITests.m 3 | // TXCarouselViewDemoUITests 4 | // 5 | // Created by 新华龙mac on 2018/1/31. 6 | // Copyright © 2018年 新华龙mac. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TXCarouselViewDemoUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation TXCarouselViewDemoUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------