├── .gitignore ├── README.md ├── SGKit.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── SGKit ├── Core │ ├── SGCategory │ │ ├── NSString+SGSize.h │ │ ├── NSString+SGSize.m │ │ ├── UIColor+SGExtension.h │ │ ├── UIColor+SGExtension.m │ │ ├── UIScreen+SGExtension.h │ │ ├── UIScreen+SGExtension.m │ │ ├── UIViewController+SGExtension.h │ │ └── UIViewController+SGExtension.m │ ├── SGCollectionView │ │ ├── SGCollectionReusableView.h │ │ ├── SGCollectionReusableView.m │ │ ├── SGCollectionViewFlowLayout.h │ │ ├── SGCollectionViewFlowLayout.m │ │ ├── SGCollectionViewLayoutAttributes.h │ │ └── SGCollectionViewLayoutAttributes.m │ ├── SGGuideView │ │ ├── SGGuideView.h │ │ └── SGGuideView.m │ ├── SGImagePlyer │ │ ├── SGImagePlayer.h │ │ └── SGImagePlayer.m │ ├── SGPageView │ │ ├── SGPageItem.h │ │ ├── SGPageItem.m │ │ ├── SGPageTitleItem.h │ │ ├── SGPageTitleItem.m │ │ ├── SGPageTitleView.h │ │ ├── SGPageTitleView.m │ │ ├── SGPageView.h │ │ └── SGPageView.m │ ├── SGSwipeView │ │ ├── SGSwipeView.h │ │ └── SGSwipeView.m │ └── SGTransform │ │ ├── SGTransformView.h │ │ └── SGTransformView.m ├── Info.plist └── SGKit.h └── demo ├── demo.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── demo.xcworkspace └── contents.xcworkspacedata └── demo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json ├── Contents.json ├── moto_1.imageset │ ├── Contents.json │ └── moto_1@2x.jpg ├── moto_2.imageset │ ├── Contents.json │ └── moto_2@2x.jpg ├── moto_3.imageset │ ├── Contents.json │ └── moto_3@2x.jpg └── moto_4.imageset │ ├── Contents.json │ └── moto_4@2x.jpg ├── Core ├── Example.h ├── Example.m ├── SGCollectionViewFlowLayoutExample │ ├── SGCollectionViewFlowLayoutExample.h │ └── SGCollectionViewFlowLayoutExample.m ├── SGGuideViewExample │ ├── SGGuideViewExample.h │ └── SGGuideViewExample.m ├── SGImagePlayerExample │ ├── SGImagePlayerExample.h │ └── SGImagePlayerExample.m ├── SGPageViewExample │ ├── SGPageViewExample.h │ ├── SGPageViewExample.m │ ├── SGTableViewExample.h │ └── SGTableViewExample.m ├── SGSwipeViewExample │ ├── SGSwipeViewExample.h │ └── SGSwipeViewExample.m └── SGTransformExample │ ├── SGTransformViewExample.h │ └── SGTransformViewExample.m ├── Info.plist └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.pbxuser 3 | !default.pbxuser 4 | *.mode1v3 5 | !default.mode1v3 6 | *.mode2v3 7 | !default.mode2v3 8 | *.perspectivev3 9 | !default.perspectivev3 10 | xcuserdata 11 | *.xccheckout 12 | *.moved-aside 13 | DerivedData 14 | *.hmap 15 | *.ipa 16 | *.xcuserstate 17 | .DS_Store 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SGKit 2 | 3 | SGKit 是一个 UI 组件合集。 4 | 5 | 6 | ## 包含组件 7 | 8 | 具体使用方式参看 demo。 9 | 10 | - SGTransformView - 自由变换视图,适用于贴纸。 11 | - SGPageView - 类似网易新闻。 12 | - SGSwipeView - 类似半塘。 13 | - SGImagePlayer - 轮播图。 14 | - SGCollectionViewFlowLayout - 自定义 UICollectionView Section 的背景颜色。 15 | - SGGuideView - 引导图。 16 | 17 | 18 | ## 效果演示 19 | 20 | ### SGTransformView 21 | 22 | ![SGTransformView](https://github.com/libobjc/resource/blob/master/SGKit/SGTtansformView.gif?raw=true) 23 | 24 | 25 | ### SGPageView 26 | 27 | ![SGTransformView](https://github.com/libobjc/resource/blob/master/SGKit/SGPageView.gif?raw=true) 28 | 29 | 30 | ### SGSwipeView 31 | 32 | ![SGTransformView](https://github.com/libobjc/resource/blob/master/SGKit/SGSwipeView.gif?raw=true) 33 | 34 | 35 | ### SGImagePlayer 36 | 37 | ![SGTransformView](https://github.com/libobjc/resource/blob/master/SGKit/SGImagePlayer.gif?raw=true) 38 | 39 | 40 | ### SGCollectionViewFlowLayout 41 | 42 | ![SGTransformView](https://github.com/libobjc/resource/blob/master/SGKit/SGColloectionViewFlowLayout.gif?raw=true) 43 | 44 | 45 | ### SGGuideView 46 | 47 | ![SGTransformView](https://github.com/libobjc/resource/blob/master/SGKit/SGGuideView.gif?raw=true) 48 | -------------------------------------------------------------------------------- /SGKit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9C1E3B851DF02BD800747C56 /* NSString+SGSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C1E3B831DF02BD800747C56 /* NSString+SGSize.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 9C1E3B861DF02BD800747C56 /* NSString+SGSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C1E3B841DF02BD800747C56 /* NSString+SGSize.m */; }; 12 | 9C5BEA8F1DCDEFCF00385153 /* SGKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5BEA8D1DCDEFCF00385153 /* SGKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | 9C5C542D1DDEE5D80066C389 /* SGSwipeView.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5C542B1DDEE5D80066C389 /* SGSwipeView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14 | 9C5C542E1DDEE5D80066C389 /* SGSwipeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C5C542C1DDEE5D80066C389 /* SGSwipeView.m */; }; 15 | 9C5C54381DDF06780066C389 /* SGPageItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C5C54361DDF06780066C389 /* SGPageItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16 | 9C5C54391DDF06780066C389 /* SGPageItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C5C54371DDF06780066C389 /* SGPageItem.m */; }; 17 | 9C7E678E1E232D1F0023D5CA /* SGGuideView.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C7E678C1E232D1F0023D5CA /* SGGuideView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18 | 9C7E678F1E232D1F0023D5CA /* SGGuideView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7E678D1E232D1F0023D5CA /* SGGuideView.m */; }; 19 | 9C87B2911E07B9F600B92A98 /* SGTransformView.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C87B28F1E07B9F600B92A98 /* SGTransformView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20 | 9C87B2921E07B9F600B92A98 /* SGTransformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C87B2901E07B9F600B92A98 /* SGTransformView.m */; }; 21 | 9CCE87641DCF6E4E00B62C21 /* UIViewController+SGExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CCE87621DCF6E4E00B62C21 /* UIViewController+SGExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; 22 | 9CCE87651DCF6E4E00B62C21 /* UIViewController+SGExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCE87631DCF6E4E00B62C21 /* UIViewController+SGExtension.m */; }; 23 | 9CCE87681DCF765000B62C21 /* UIScreen+SGExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CCE87661DCF765000B62C21 /* UIScreen+SGExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; 24 | 9CCE87691DCF765000B62C21 /* UIScreen+SGExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CCE87671DCF765000B62C21 /* UIScreen+SGExtension.m */; }; 25 | 9CD17A141DDD4AFC00C2A834 /* SGImagePlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CD17A121DDD4AFC00C2A834 /* SGImagePlayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | 9CD17A151DDD4AFC00C2A834 /* SGImagePlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CD17A131DDD4AFC00C2A834 /* SGImagePlayer.m */; }; 27 | 9CD17A3C1DDD5BF900C2A834 /* Masonry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9CD17A3B1DDD5BF900C2A834 /* Masonry.framework */; }; 28 | 9CD17A401DDD940D00C2A834 /* SGPageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CD17A3E1DDD940D00C2A834 /* SGPageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 29 | 9CD17A411DDD940D00C2A834 /* SGPageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CD17A3F1DDD940D00C2A834 /* SGPageView.m */; }; 30 | 9CD17A481DDDA56700C2A834 /* SGPageTitleView.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CD17A461DDDA56700C2A834 /* SGPageTitleView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 31 | 9CD17A491DDDA56700C2A834 /* SGPageTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CD17A471DDDA56700C2A834 /* SGPageTitleView.m */; }; 32 | 9CD17A4C1DDDB9D200C2A834 /* SGPageTitleItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CD17A4A1DDDB9D200C2A834 /* SGPageTitleItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; 33 | 9CD17A4D1DDDB9D200C2A834 /* SGPageTitleItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CD17A4B1DDDB9D200C2A834 /* SGPageTitleItem.m */; }; 34 | 9CD491091DD321DC002D978A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9CD491081DD321DC002D978A /* Foundation.framework */; }; 35 | 9CD491FB1DD33671002D978A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9CD491FA1DD33671002D978A /* UIKit.framework */; }; 36 | 9CDD5F471DCE30B200AB7057 /* SGCollectionReusableView.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDD5F411DCE30B200AB7057 /* SGCollectionReusableView.h */; }; 37 | 9CDD5F481DCE30B200AB7057 /* SGCollectionReusableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CDD5F421DCE30B200AB7057 /* SGCollectionReusableView.m */; }; 38 | 9CDD5F491DCE30B200AB7057 /* SGCollectionViewFlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDD5F431DCE30B200AB7057 /* SGCollectionViewFlowLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 39 | 9CDD5F4A1DCE30B200AB7057 /* SGCollectionViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CDD5F441DCE30B200AB7057 /* SGCollectionViewFlowLayout.m */; }; 40 | 9CDD5F4B1DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDD5F451DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.h */; }; 41 | 9CDD5F4C1DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CDD5F461DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.m */; }; 42 | 9CE66AED1DCEF60500C4ED11 /* UIColor+SGExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CE66AEB1DCEF60500C4ED11 /* UIColor+SGExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; 43 | 9CE66AEE1DCEF60500C4ED11 /* UIColor+SGExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CE66AEC1DCEF60500C4ED11 /* UIColor+SGExtension.m */; }; 44 | /* End PBXBuildFile section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 9C1E3B831DF02BD800747C56 /* NSString+SGSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+SGSize.h"; sourceTree = ""; }; 48 | 9C1E3B841DF02BD800747C56 /* NSString+SGSize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+SGSize.m"; sourceTree = ""; }; 49 | 9C5BEA8A1DCDEFCF00385153 /* SGKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SGKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 9C5BEA8D1DCDEFCF00385153 /* SGKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SGKit.h; sourceTree = ""; }; 51 | 9C5BEA8E1DCDEFCF00385153 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 9C5C542B1DDEE5D80066C389 /* SGSwipeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGSwipeView.h; sourceTree = ""; }; 53 | 9C5C542C1DDEE5D80066C389 /* SGSwipeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGSwipeView.m; sourceTree = ""; }; 54 | 9C5C54361DDF06780066C389 /* SGPageItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGPageItem.h; sourceTree = ""; }; 55 | 9C5C54371DDF06780066C389 /* SGPageItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGPageItem.m; sourceTree = ""; }; 56 | 9C7E678C1E232D1F0023D5CA /* SGGuideView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGGuideView.h; sourceTree = ""; }; 57 | 9C7E678D1E232D1F0023D5CA /* SGGuideView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGGuideView.m; sourceTree = ""; }; 58 | 9C87B28F1E07B9F600B92A98 /* SGTransformView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGTransformView.h; sourceTree = ""; }; 59 | 9C87B2901E07B9F600B92A98 /* SGTransformView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGTransformView.m; sourceTree = ""; }; 60 | 9CCE87621DCF6E4E00B62C21 /* UIViewController+SGExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+SGExtension.h"; sourceTree = ""; }; 61 | 9CCE87631DCF6E4E00B62C21 /* UIViewController+SGExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+SGExtension.m"; sourceTree = ""; }; 62 | 9CCE87661DCF765000B62C21 /* UIScreen+SGExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScreen+SGExtension.h"; sourceTree = ""; }; 63 | 9CCE87671DCF765000B62C21 /* UIScreen+SGExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScreen+SGExtension.m"; sourceTree = ""; }; 64 | 9CD17A121DDD4AFC00C2A834 /* SGImagePlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGImagePlayer.h; sourceTree = ""; }; 65 | 9CD17A131DDD4AFC00C2A834 /* SGImagePlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGImagePlayer.m; sourceTree = ""; }; 66 | 9CD17A3B1DDD5BF900C2A834 /* Masonry.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Masonry.framework; path = "../SGVendors/Masonry-master/build/Debug-iphoneos/Masonry.framework"; sourceTree = ""; }; 67 | 9CD17A3E1DDD940D00C2A834 /* SGPageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGPageView.h; sourceTree = ""; }; 68 | 9CD17A3F1DDD940D00C2A834 /* SGPageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGPageView.m; sourceTree = ""; }; 69 | 9CD17A461DDDA56700C2A834 /* SGPageTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGPageTitleView.h; sourceTree = ""; }; 70 | 9CD17A471DDDA56700C2A834 /* SGPageTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGPageTitleView.m; sourceTree = ""; }; 71 | 9CD17A4A1DDDB9D200C2A834 /* SGPageTitleItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGPageTitleItem.h; sourceTree = ""; }; 72 | 9CD17A4B1DDDB9D200C2A834 /* SGPageTitleItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGPageTitleItem.m; sourceTree = ""; }; 73 | 9CD491081DD321DC002D978A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 74 | 9CD491FA1DD33671002D978A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 75 | 9CDD5F411DCE30B200AB7057 /* SGCollectionReusableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGCollectionReusableView.h; sourceTree = ""; }; 76 | 9CDD5F421DCE30B200AB7057 /* SGCollectionReusableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGCollectionReusableView.m; sourceTree = ""; }; 77 | 9CDD5F431DCE30B200AB7057 /* SGCollectionViewFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGCollectionViewFlowLayout.h; sourceTree = ""; }; 78 | 9CDD5F441DCE30B200AB7057 /* SGCollectionViewFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGCollectionViewFlowLayout.m; sourceTree = ""; }; 79 | 9CDD5F451DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGCollectionViewLayoutAttributes.h; sourceTree = ""; }; 80 | 9CDD5F461DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGCollectionViewLayoutAttributes.m; sourceTree = ""; }; 81 | 9CE66AEB1DCEF60500C4ED11 /* UIColor+SGExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+SGExtension.h"; sourceTree = ""; }; 82 | 9CE66AEC1DCEF60500C4ED11 /* UIColor+SGExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+SGExtension.m"; sourceTree = ""; }; 83 | /* End PBXFileReference section */ 84 | 85 | /* Begin PBXFrameworksBuildPhase section */ 86 | 9C5BEA861DCDEFCF00385153 /* Frameworks */ = { 87 | isa = PBXFrameworksBuildPhase; 88 | buildActionMask = 2147483647; 89 | files = ( 90 | 9CD17A3C1DDD5BF900C2A834 /* Masonry.framework in Frameworks */, 91 | 9CD491FB1DD33671002D978A /* UIKit.framework in Frameworks */, 92 | 9CD491091DD321DC002D978A /* Foundation.framework in Frameworks */, 93 | ); 94 | runOnlyForDeploymentPostprocessing = 0; 95 | }; 96 | /* End PBXFrameworksBuildPhase section */ 97 | 98 | /* Begin PBXGroup section */ 99 | 9C5BEA801DCDEFCF00385153 = { 100 | isa = PBXGroup; 101 | children = ( 102 | 9C5BEA8C1DCDEFCF00385153 /* SGKit */, 103 | 9C5BEA8B1DCDEFCF00385153 /* Products */, 104 | 9CD491071DD321DC002D978A /* Frameworks */, 105 | ); 106 | sourceTree = ""; 107 | }; 108 | 9C5BEA8B1DCDEFCF00385153 /* Products */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 9C5BEA8A1DCDEFCF00385153 /* SGKit.framework */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | 9C5BEA8C1DCDEFCF00385153 /* SGKit */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 9C5BEA8D1DCDEFCF00385153 /* SGKit.h */, 120 | 9C5BEA8E1DCDEFCF00385153 /* Info.plist */, 121 | 9C5BEACD1DCDF07600385153 /* Core */, 122 | ); 123 | path = SGKit; 124 | sourceTree = ""; 125 | }; 126 | 9C5BEACD1DCDF07600385153 /* Core */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 9CDD5F4D1DCE37D500AB7057 /* SGCategory */, 130 | 9C87B28E1E07B9E600B92A98 /* SGTransform */, 131 | 9CD17A3D1DDD93D600C2A834 /* SGPageView */, 132 | 9C5C542A1DDEE5C70066C389 /* SGSwipeView */, 133 | 9CD17A111DDD4AFC00C2A834 /* SGImagePlyer */, 134 | 9CDD5F401DCE30B200AB7057 /* SGCollectionView */, 135 | 9C7E678B1E232D1F0023D5CA /* SGGuideView */, 136 | ); 137 | path = Core; 138 | sourceTree = ""; 139 | }; 140 | 9C5C542A1DDEE5C70066C389 /* SGSwipeView */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 9C5C542B1DDEE5D80066C389 /* SGSwipeView.h */, 144 | 9C5C542C1DDEE5D80066C389 /* SGSwipeView.m */, 145 | ); 146 | path = SGSwipeView; 147 | sourceTree = ""; 148 | }; 149 | 9C7E678B1E232D1F0023D5CA /* SGGuideView */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 9C7E678C1E232D1F0023D5CA /* SGGuideView.h */, 153 | 9C7E678D1E232D1F0023D5CA /* SGGuideView.m */, 154 | ); 155 | path = SGGuideView; 156 | sourceTree = ""; 157 | }; 158 | 9C87B28E1E07B9E600B92A98 /* SGTransform */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | 9C87B28F1E07B9F600B92A98 /* SGTransformView.h */, 162 | 9C87B2901E07B9F600B92A98 /* SGTransformView.m */, 163 | ); 164 | path = SGTransform; 165 | sourceTree = ""; 166 | }; 167 | 9CD17A111DDD4AFC00C2A834 /* SGImagePlyer */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | 9CD17A121DDD4AFC00C2A834 /* SGImagePlayer.h */, 171 | 9CD17A131DDD4AFC00C2A834 /* SGImagePlayer.m */, 172 | ); 173 | path = SGImagePlyer; 174 | sourceTree = ""; 175 | }; 176 | 9CD17A3D1DDD93D600C2A834 /* SGPageView */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | 9CD17A3E1DDD940D00C2A834 /* SGPageView.h */, 180 | 9CD17A3F1DDD940D00C2A834 /* SGPageView.m */, 181 | 9C5C54361DDF06780066C389 /* SGPageItem.h */, 182 | 9C5C54371DDF06780066C389 /* SGPageItem.m */, 183 | 9CD17A461DDDA56700C2A834 /* SGPageTitleView.h */, 184 | 9CD17A471DDDA56700C2A834 /* SGPageTitleView.m */, 185 | 9CD17A4A1DDDB9D200C2A834 /* SGPageTitleItem.h */, 186 | 9CD17A4B1DDDB9D200C2A834 /* SGPageTitleItem.m */, 187 | ); 188 | path = SGPageView; 189 | sourceTree = ""; 190 | }; 191 | 9CD491071DD321DC002D978A /* Frameworks */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | 9CD17A3B1DDD5BF900C2A834 /* Masonry.framework */, 195 | 9CD491FA1DD33671002D978A /* UIKit.framework */, 196 | 9CD491081DD321DC002D978A /* Foundation.framework */, 197 | ); 198 | name = Frameworks; 199 | sourceTree = ""; 200 | }; 201 | 9CDD5F401DCE30B200AB7057 /* SGCollectionView */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | 9CDD5F411DCE30B200AB7057 /* SGCollectionReusableView.h */, 205 | 9CDD5F421DCE30B200AB7057 /* SGCollectionReusableView.m */, 206 | 9CDD5F431DCE30B200AB7057 /* SGCollectionViewFlowLayout.h */, 207 | 9CDD5F441DCE30B200AB7057 /* SGCollectionViewFlowLayout.m */, 208 | 9CDD5F451DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.h */, 209 | 9CDD5F461DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.m */, 210 | ); 211 | path = SGCollectionView; 212 | sourceTree = ""; 213 | }; 214 | 9CDD5F4D1DCE37D500AB7057 /* SGCategory */ = { 215 | isa = PBXGroup; 216 | children = ( 217 | 9CE66AEB1DCEF60500C4ED11 /* UIColor+SGExtension.h */, 218 | 9CE66AEC1DCEF60500C4ED11 /* UIColor+SGExtension.m */, 219 | 9CCE87621DCF6E4E00B62C21 /* UIViewController+SGExtension.h */, 220 | 9CCE87631DCF6E4E00B62C21 /* UIViewController+SGExtension.m */, 221 | 9CCE87661DCF765000B62C21 /* UIScreen+SGExtension.h */, 222 | 9CCE87671DCF765000B62C21 /* UIScreen+SGExtension.m */, 223 | 9C1E3B831DF02BD800747C56 /* NSString+SGSize.h */, 224 | 9C1E3B841DF02BD800747C56 /* NSString+SGSize.m */, 225 | ); 226 | path = SGCategory; 227 | sourceTree = ""; 228 | }; 229 | /* End PBXGroup section */ 230 | 231 | /* Begin PBXHeadersBuildPhase section */ 232 | 9C5BEA871DCDEFCF00385153 /* Headers */ = { 233 | isa = PBXHeadersBuildPhase; 234 | buildActionMask = 2147483647; 235 | files = ( 236 | 9C5BEA8F1DCDEFCF00385153 /* SGKit.h in Headers */, 237 | 9C1E3B851DF02BD800747C56 /* NSString+SGSize.h in Headers */, 238 | 9CE66AED1DCEF60500C4ED11 /* UIColor+SGExtension.h in Headers */, 239 | 9CCE87681DCF765000B62C21 /* UIScreen+SGExtension.h in Headers */, 240 | 9CCE87641DCF6E4E00B62C21 /* UIViewController+SGExtension.h in Headers */, 241 | 9CDD5F491DCE30B200AB7057 /* SGCollectionViewFlowLayout.h in Headers */, 242 | 9CD17A141DDD4AFC00C2A834 /* SGImagePlayer.h in Headers */, 243 | 9CD17A401DDD940D00C2A834 /* SGPageView.h in Headers */, 244 | 9C5C542D1DDEE5D80066C389 /* SGSwipeView.h in Headers */, 245 | 9C5C54381DDF06780066C389 /* SGPageItem.h in Headers */, 246 | 9CD17A4C1DDDB9D200C2A834 /* SGPageTitleItem.h in Headers */, 247 | 9C87B2911E07B9F600B92A98 /* SGTransformView.h in Headers */, 248 | 9C7E678E1E232D1F0023D5CA /* SGGuideView.h in Headers */, 249 | 9CD17A481DDDA56700C2A834 /* SGPageTitleView.h in Headers */, 250 | 9CDD5F471DCE30B200AB7057 /* SGCollectionReusableView.h in Headers */, 251 | 9CDD5F4B1DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.h in Headers */, 252 | ); 253 | runOnlyForDeploymentPostprocessing = 0; 254 | }; 255 | /* End PBXHeadersBuildPhase section */ 256 | 257 | /* Begin PBXNativeTarget section */ 258 | 9C5BEA891DCDEFCF00385153 /* SGKit */ = { 259 | isa = PBXNativeTarget; 260 | buildConfigurationList = 9C5BEA921DCDEFCF00385153 /* Build configuration list for PBXNativeTarget "SGKit" */; 261 | buildPhases = ( 262 | 9C5BEA851DCDEFCF00385153 /* Sources */, 263 | 9C5BEA861DCDEFCF00385153 /* Frameworks */, 264 | 9C5BEA871DCDEFCF00385153 /* Headers */, 265 | 9C5BEA881DCDEFCF00385153 /* Resources */, 266 | ); 267 | buildRules = ( 268 | ); 269 | dependencies = ( 270 | ); 271 | name = SGKit; 272 | productName = SGKit; 273 | productReference = 9C5BEA8A1DCDEFCF00385153 /* SGKit.framework */; 274 | productType = "com.apple.product-type.framework"; 275 | }; 276 | /* End PBXNativeTarget section */ 277 | 278 | /* Begin PBXProject section */ 279 | 9C5BEA811DCDEFCF00385153 /* Project object */ = { 280 | isa = PBXProject; 281 | attributes = { 282 | LastUpgradeCheck = 0820; 283 | ORGANIZATIONNAME = single; 284 | TargetAttributes = { 285 | 9C5BEA891DCDEFCF00385153 = { 286 | CreatedOnToolsVersion = 8.0; 287 | DevelopmentTeam = SWXNKT9754; 288 | ProvisioningStyle = Automatic; 289 | }; 290 | }; 291 | }; 292 | buildConfigurationList = 9C5BEA841DCDEFCF00385153 /* Build configuration list for PBXProject "SGKit" */; 293 | compatibilityVersion = "Xcode 3.2"; 294 | developmentRegion = English; 295 | hasScannedForEncodings = 0; 296 | knownRegions = ( 297 | en, 298 | ); 299 | mainGroup = 9C5BEA801DCDEFCF00385153; 300 | productRefGroup = 9C5BEA8B1DCDEFCF00385153 /* Products */; 301 | projectDirPath = ""; 302 | projectRoot = ""; 303 | targets = ( 304 | 9C5BEA891DCDEFCF00385153 /* SGKit */, 305 | ); 306 | }; 307 | /* End PBXProject section */ 308 | 309 | /* Begin PBXResourcesBuildPhase section */ 310 | 9C5BEA881DCDEFCF00385153 /* Resources */ = { 311 | isa = PBXResourcesBuildPhase; 312 | buildActionMask = 2147483647; 313 | files = ( 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | }; 317 | /* End PBXResourcesBuildPhase section */ 318 | 319 | /* Begin PBXSourcesBuildPhase section */ 320 | 9C5BEA851DCDEFCF00385153 /* Sources */ = { 321 | isa = PBXSourcesBuildPhase; 322 | buildActionMask = 2147483647; 323 | files = ( 324 | 9CD17A491DDDA56700C2A834 /* SGPageTitleView.m in Sources */, 325 | 9C87B2921E07B9F600B92A98 /* SGTransformView.m in Sources */, 326 | 9CDD5F4A1DCE30B200AB7057 /* SGCollectionViewFlowLayout.m in Sources */, 327 | 9CD17A4D1DDDB9D200C2A834 /* SGPageTitleItem.m in Sources */, 328 | 9CD17A411DDD940D00C2A834 /* SGPageView.m in Sources */, 329 | 9CD17A151DDD4AFC00C2A834 /* SGImagePlayer.m in Sources */, 330 | 9C5C54391DDF06780066C389 /* SGPageItem.m in Sources */, 331 | 9C1E3B861DF02BD800747C56 /* NSString+SGSize.m in Sources */, 332 | 9CDD5F481DCE30B200AB7057 /* SGCollectionReusableView.m in Sources */, 333 | 9CDD5F4C1DCE30B200AB7057 /* SGCollectionViewLayoutAttributes.m in Sources */, 334 | 9CCE87691DCF765000B62C21 /* UIScreen+SGExtension.m in Sources */, 335 | 9C5C542E1DDEE5D80066C389 /* SGSwipeView.m in Sources */, 336 | 9CE66AEE1DCEF60500C4ED11 /* UIColor+SGExtension.m in Sources */, 337 | 9C7E678F1E232D1F0023D5CA /* SGGuideView.m in Sources */, 338 | 9CCE87651DCF6E4E00B62C21 /* UIViewController+SGExtension.m in Sources */, 339 | ); 340 | runOnlyForDeploymentPostprocessing = 0; 341 | }; 342 | /* End PBXSourcesBuildPhase section */ 343 | 344 | /* Begin XCBuildConfiguration section */ 345 | 9C5BEA901DCDEFCF00385153 /* Debug */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | ALWAYS_SEARCH_USER_PATHS = NO; 349 | CLANG_ANALYZER_NONNULL = YES; 350 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 351 | CLANG_CXX_LIBRARY = "libc++"; 352 | CLANG_ENABLE_MODULES = YES; 353 | CLANG_ENABLE_OBJC_ARC = YES; 354 | CLANG_WARN_BOOL_CONVERSION = YES; 355 | CLANG_WARN_CONSTANT_CONVERSION = YES; 356 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 357 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 358 | CLANG_WARN_EMPTY_BODY = YES; 359 | CLANG_WARN_ENUM_CONVERSION = YES; 360 | CLANG_WARN_INFINITE_RECURSION = YES; 361 | CLANG_WARN_INT_CONVERSION = YES; 362 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 363 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 364 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 365 | CLANG_WARN_UNREACHABLE_CODE = YES; 366 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 367 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 368 | COPY_PHASE_STRIP = NO; 369 | CURRENT_PROJECT_VERSION = 1; 370 | DEBUG_INFORMATION_FORMAT = dwarf; 371 | ENABLE_STRICT_OBJC_MSGSEND = YES; 372 | ENABLE_TESTABILITY = YES; 373 | GCC_C_LANGUAGE_STANDARD = gnu99; 374 | GCC_DYNAMIC_NO_PIC = NO; 375 | GCC_NO_COMMON_BLOCKS = YES; 376 | GCC_OPTIMIZATION_LEVEL = 0; 377 | GCC_PREPROCESSOR_DEFINITIONS = ( 378 | "DEBUG=1", 379 | "$(inherited)", 380 | ); 381 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 382 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 383 | GCC_WARN_UNDECLARED_SELECTOR = YES; 384 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 385 | GCC_WARN_UNUSED_FUNCTION = YES; 386 | GCC_WARN_UNUSED_VARIABLE = YES; 387 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 388 | MTL_ENABLE_DEBUG_INFO = YES; 389 | ONLY_ACTIVE_ARCH = YES; 390 | SDKROOT = iphoneos; 391 | TARGETED_DEVICE_FAMILY = "1,2"; 392 | VERSIONING_SYSTEM = "apple-generic"; 393 | VERSION_INFO_PREFIX = ""; 394 | }; 395 | name = Debug; 396 | }; 397 | 9C5BEA911DCDEFCF00385153 /* Release */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | ALWAYS_SEARCH_USER_PATHS = NO; 401 | CLANG_ANALYZER_NONNULL = YES; 402 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 403 | CLANG_CXX_LIBRARY = "libc++"; 404 | CLANG_ENABLE_MODULES = YES; 405 | CLANG_ENABLE_OBJC_ARC = YES; 406 | CLANG_WARN_BOOL_CONVERSION = YES; 407 | CLANG_WARN_CONSTANT_CONVERSION = YES; 408 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 409 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 410 | CLANG_WARN_EMPTY_BODY = YES; 411 | CLANG_WARN_ENUM_CONVERSION = YES; 412 | CLANG_WARN_INFINITE_RECURSION = YES; 413 | CLANG_WARN_INT_CONVERSION = YES; 414 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 415 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 416 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 417 | CLANG_WARN_UNREACHABLE_CODE = YES; 418 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 419 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 420 | COPY_PHASE_STRIP = NO; 421 | CURRENT_PROJECT_VERSION = 1; 422 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 423 | ENABLE_NS_ASSERTIONS = NO; 424 | ENABLE_STRICT_OBJC_MSGSEND = YES; 425 | GCC_C_LANGUAGE_STANDARD = gnu99; 426 | GCC_NO_COMMON_BLOCKS = YES; 427 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 428 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 429 | GCC_WARN_UNDECLARED_SELECTOR = YES; 430 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 431 | GCC_WARN_UNUSED_FUNCTION = YES; 432 | GCC_WARN_UNUSED_VARIABLE = YES; 433 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 434 | MTL_ENABLE_DEBUG_INFO = NO; 435 | SDKROOT = iphoneos; 436 | TARGETED_DEVICE_FAMILY = "1,2"; 437 | VALIDATE_PRODUCT = YES; 438 | VERSIONING_SYSTEM = "apple-generic"; 439 | VERSION_INFO_PREFIX = ""; 440 | }; 441 | name = Release; 442 | }; 443 | 9C5BEA931DCDEFCF00385153 /* Debug */ = { 444 | isa = XCBuildConfiguration; 445 | buildSettings = { 446 | CODE_SIGN_IDENTITY = ""; 447 | DEFINES_MODULE = YES; 448 | DEVELOPMENT_TEAM = SWXNKT9754; 449 | DYLIB_COMPATIBILITY_VERSION = 1; 450 | DYLIB_CURRENT_VERSION = 1; 451 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 452 | INFOPLIST_FILE = SGKit/Info.plist; 453 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 454 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 455 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 456 | MACH_O_TYPE = staticlib; 457 | OTHER_LDFLAGS = ""; 458 | PRODUCT_BUNDLE_IDENTIFIER = com.single.SGKit; 459 | PRODUCT_NAME = "$(TARGET_NAME)"; 460 | SKIP_INSTALL = YES; 461 | }; 462 | name = Debug; 463 | }; 464 | 9C5BEA941DCDEFCF00385153 /* Release */ = { 465 | isa = XCBuildConfiguration; 466 | buildSettings = { 467 | CODE_SIGN_IDENTITY = ""; 468 | DEFINES_MODULE = YES; 469 | DEVELOPMENT_TEAM = SWXNKT9754; 470 | DYLIB_COMPATIBILITY_VERSION = 1; 471 | DYLIB_CURRENT_VERSION = 1; 472 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 473 | INFOPLIST_FILE = SGKit/Info.plist; 474 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 475 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 476 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 477 | MACH_O_TYPE = staticlib; 478 | OTHER_LDFLAGS = ""; 479 | PRODUCT_BUNDLE_IDENTIFIER = com.single.SGKit; 480 | PRODUCT_NAME = "$(TARGET_NAME)"; 481 | SKIP_INSTALL = YES; 482 | }; 483 | name = Release; 484 | }; 485 | /* End XCBuildConfiguration section */ 486 | 487 | /* Begin XCConfigurationList section */ 488 | 9C5BEA841DCDEFCF00385153 /* Build configuration list for PBXProject "SGKit" */ = { 489 | isa = XCConfigurationList; 490 | buildConfigurations = ( 491 | 9C5BEA901DCDEFCF00385153 /* Debug */, 492 | 9C5BEA911DCDEFCF00385153 /* Release */, 493 | ); 494 | defaultConfigurationIsVisible = 0; 495 | defaultConfigurationName = Release; 496 | }; 497 | 9C5BEA921DCDEFCF00385153 /* Build configuration list for PBXNativeTarget "SGKit" */ = { 498 | isa = XCConfigurationList; 499 | buildConfigurations = ( 500 | 9C5BEA931DCDEFCF00385153 /* Debug */, 501 | 9C5BEA941DCDEFCF00385153 /* Release */, 502 | ); 503 | defaultConfigurationIsVisible = 0; 504 | defaultConfigurationName = Release; 505 | }; 506 | /* End XCConfigurationList section */ 507 | }; 508 | rootObject = 9C5BEA811DCDEFCF00385153 /* Project object */; 509 | } 510 | -------------------------------------------------------------------------------- /SGKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SGKit/Core/SGCategory/NSString+SGSize.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+SGSize.h 3 | // SGKit 4 | // 5 | // Created by Single on 01/12/2016. 6 | // Copyright © 2016 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (SGSize) 12 | 13 | - (CGFloat)sg_widthOfFont:(UIFont *)font; 14 | - (CGFloat)sg_heightOfFont:(UIFont *)font; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /SGKit/Core/SGCategory/NSString+SGSize.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+SGSize.m 3 | // SGKit 4 | // 5 | // Created by Single on 01/12/2016. 6 | // Copyright © 2016 single. All rights reserved. 7 | // 8 | 9 | #import "NSString+SGSize.h" 10 | 11 | @implementation NSString (SGSize) 12 | 13 | - (CGFloat)sg_widthOfFont:(UIFont *)font 14 | { 15 | NSDictionary * attribute = @{NSFontAttributeName : font}; 16 | CGRect rect = [self boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) 17 | options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading 18 | attributes:attribute 19 | context:nil]; 20 | return rect.size.width; 21 | } 22 | 23 | - (CGFloat)sg_heightOfFont:(UIFont *)font 24 | { 25 | NSDictionary * attribute = @{NSFontAttributeName : font}; 26 | CGRect rect = [self boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) 27 | options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading 28 | attributes:attribute 29 | context:nil]; 30 | return rect.size.height; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /SGKit/Core/SGCategory/UIColor+SGExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+SGExtension.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/6. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (SGExtension) 12 | 13 | + (instancetype)sg_randomColor; // 随机颜色 14 | + (instancetype)sg_colorWithRGB:(NSInteger)RGB; // 16进制RGB 15 | + (instancetype)sg_colorWithRGB:(NSInteger)RGB alpha:(CGFloat)alpha; 16 | + (instancetype)sg_colorWithRed:(NSInteger)red green:(NSInteger)green blue:(NSInteger)blue; // 0~255 17 | + (instancetype)sg_colorWithRed:(NSInteger)red green:(NSInteger)green blue:(NSInteger)blue alpha:(CGFloat)alpha; 18 | 19 | + (instancetype)sg_redColor; 20 | + (instancetype)sg_greenColor; 21 | + (instancetype)sg_grayColor; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /SGKit/Core/SGCategory/UIColor+SGExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+SGExtension.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/6. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "UIColor+SGExtension.h" 10 | 11 | @implementation UIColor (SGExtension) 12 | 13 | + (instancetype)sg_randomColor 14 | { 15 | return [self sg_colorWithRGB:arc4random() % 0xFFFFFF]; 16 | } 17 | 18 | + (instancetype)sg_colorWithRGB:(NSInteger)RGB 19 | { 20 | return [self sg_colorWithRGB:RGB alpha:1.0]; 21 | } 22 | 23 | + (instancetype)sg_colorWithRGB:(NSInteger)RGB alpha:(CGFloat)alpha 24 | { 25 | NSInteger red = (RGB & 0xFF0000) >> 16; 26 | NSInteger green = (RGB & 0xFF00) >> 8; 27 | NSInteger blue = RGB & 0xFF; 28 | return [self sg_colorWithRed:red green:green blue:blue alpha:alpha]; 29 | } 30 | 31 | + (instancetype)sg_colorWithRed:(NSInteger)red green:(NSInteger)green blue:(NSInteger)blue 32 | { 33 | return [self sg_colorWithRed:red green:green blue:blue alpha:1.0]; 34 | } 35 | 36 | + (instancetype)sg_colorWithRed:(NSInteger)red green:(NSInteger)green blue:(NSInteger)blue alpha:(CGFloat)alpha 37 | { 38 | return [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:alpha]; 39 | } 40 | 41 | + (instancetype)sg_redColor 42 | { 43 | return [self sg_colorWithRed:229 green:37 blue:33]; 44 | } 45 | 46 | + (instancetype)sg_greenColor 47 | { 48 | return [self sg_colorWithRGB:0x0fc584]; 49 | } 50 | 51 | + (instancetype)sg_grayColor 52 | { 53 | return [self sg_colorWithRed:246 green:246 blue:246]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /SGKit/Core/SGCategory/UIScreen+SGExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIScreen+SGExtension.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/6. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // 屏幕尺寸 12 | typedef NS_ENUM(NSUInteger, SGScreenSizeType) 13 | { 14 | SGScreenSizeTypeUnknown, 15 | SGScreenSizeType35, // 3.5寸 16 | SGScreenSizeType40, // 4.0寸 17 | SGScreenSizeType47, // 4.7寸 18 | SGScreenSizeType55, // 5.5寸 19 | }; 20 | 21 | @interface UIScreen (SGExtension) 22 | 23 | + (SGScreenSizeType)sg_screenSizeType; 24 | + (UIImage *)sg_snapshot; 25 | 26 | + (CGRect)sg_bounds; 27 | + (CGSize)sg_size; 28 | + (CGPoint)sg_origin; 29 | + (CGFloat)sg_x; 30 | + (CGFloat)sg_y; 31 | + (CGFloat)sg_width; 32 | + (CGFloat)sg_height; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /SGKit/Core/SGCategory/UIScreen+SGExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIScreen+SGExtension.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/6. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "UIScreen+SGExtension.h" 10 | 11 | @implementation UIScreen (SGExtension) 12 | 13 | + (SGScreenSizeType)sg_screenSizeType 14 | { 15 | if (![UIScreen instancesRespondToSelector:@selector(currentMode)]) return SGScreenSizeTypeUnknown; 16 | 17 | CGSize size = [UIScreen mainScreen].currentMode.size; 18 | if (CGSizeEqualToSize(size, CGSizeMake(1242, 2208))) 19 | { 20 | return SGScreenSizeType55; 21 | } 22 | else if (CGSizeEqualToSize(size, CGSizeMake(750, 1334))) 23 | { 24 | return SGScreenSizeType47; 25 | } 26 | else if (CGSizeEqualToSize(size, CGSizeMake(640, 1136))) 27 | { 28 | return SGScreenSizeType40; 29 | } 30 | else if (CGSizeEqualToSize(size, CGSizeMake(640, 960))) 31 | { 32 | return SGScreenSizeType35; 33 | } 34 | return SGScreenSizeTypeUnknown; 35 | } 36 | 37 | + (UIImage *)sg_snapshot 38 | { 39 | CGSize imageSize = [[UIScreen mainScreen] bounds].size; 40 | UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); 41 | CGContextRef context = UIGraphicsGetCurrentContext(); 42 | for (UIWindow * window in [[UIApplication sharedApplication] windows]) 43 | { 44 | if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen]) 45 | { 46 | CGContextSaveGState(context); 47 | CGContextTranslateCTM(context, [window center].x, [window center].y); 48 | CGContextConcatCTM(context, [window transform]); 49 | CGContextTranslateCTM(context, -[window bounds].size.width * [[window layer] anchorPoint].x, -[window bounds].size.height * [[window layer] anchorPoint].y); 50 | [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES]; 51 | CGContextRestoreGState(context); 52 | } 53 | } 54 | UIImage * image = UIGraphicsGetImageFromCurrentImageContext(); 55 | UIGraphicsEndImageContext(); 56 | return image; 57 | } 58 | 59 | + (CGRect)sg_bounds 60 | { 61 | return [UIScreen mainScreen].bounds; 62 | } 63 | 64 | + (CGSize)sg_size 65 | { 66 | return [self sg_bounds].size; 67 | } 68 | 69 | + (CGPoint)sg_origin 70 | { 71 | return [self sg_bounds].origin; 72 | } 73 | 74 | + (CGFloat)sg_x 75 | { 76 | return [self sg_origin].x; 77 | } 78 | 79 | + (CGFloat)sg_y 80 | { 81 | return [self sg_origin].y; 82 | } 83 | 84 | + (CGFloat)sg_width 85 | { 86 | return [self sg_size].width; 87 | } 88 | 89 | + (CGFloat)sg_height 90 | { 91 | return [self sg_size].height; 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /SGKit/Core/SGCategory/UIViewController+SGExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+SGExtension.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/6. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef UIViewController *(^SGBootViewControllerBlock)(); 12 | 13 | @interface UIViewController (SGExtension) 14 | 15 | + (void)sg_setBootViewControllerBlock:(SGBootViewControllerBlock)bootViewControllerBlock; 16 | + (UIViewController *)sg_topViewController; // 使用前先设置 bootViewControllerBlock 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /SGKit/Core/SGCategory/UIViewController+SGExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+SGExtension.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/6. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "UIViewController+SGExtension.h" 10 | 11 | @implementation UIViewController (SGExtension) 12 | 13 | static SGBootViewControllerBlock bootViewControllerBlock = nil; 14 | 15 | + (void)sg_setBootViewControllerBlock:(SGBootViewControllerBlock)block 16 | { 17 | bootViewControllerBlock = [block copy]; 18 | } 19 | 20 | + (UIViewController *)sg_topViewController 21 | { 22 | if (!bootViewControllerBlock) return nil; 23 | UIViewController * viewController = bootViewControllerBlock(); 24 | return [self topViewControllerWithViewController:viewController]; 25 | } 26 | 27 | + (UIViewController *)topViewControllerWithViewController:(UIViewController *)viewController 28 | { 29 | if ([viewController isKindOfClass:[UINavigationController class]]) 30 | { 31 | UINavigationController * obj = (UINavigationController *)viewController; 32 | return [self topViewControllerWithViewController:obj.visibleViewController]; 33 | } 34 | return viewController; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /SGKit/Core/SGCollectionView/SGCollectionReusableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGCollectionReusableView.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/5. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SGCollectionReusableView : UICollectionReusableView 12 | 13 | @property (nonatomic, strong) UIView * backgroundView; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /SGKit/Core/SGCollectionView/SGCollectionReusableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGCollectionReusableView.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/5. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGCollectionReusableView.h" 10 | #import "SGCollectionViewLayoutAttributes.h" 11 | 12 | @implementation SGCollectionReusableView 13 | 14 | - (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes 15 | { 16 | [super applyLayoutAttributes:layoutAttributes]; 17 | if ([layoutAttributes isKindOfClass:[SGCollectionViewLayoutAttributes class]]) { 18 | self.backgroundColor = [(SGCollectionViewLayoutAttributes *)layoutAttributes color]; 19 | self.backgroundView = [(SGCollectionViewLayoutAttributes *)layoutAttributes backgroundView]; 20 | } 21 | } 22 | 23 | - (void)setBackgroundView:(UIView *)backgroundView 24 | { 25 | if (_backgroundView != backgroundView) { 26 | if (_backgroundView && _backgroundView.superview == self) { 27 | [_backgroundView removeFromSuperview]; 28 | } 29 | _backgroundView = backgroundView; 30 | if (backgroundView) { 31 | [self addSubview:backgroundView]; 32 | backgroundView.frame = self.bounds; 33 | } 34 | } 35 | } 36 | 37 | - (void)layoutSubviews 38 | { 39 | [super layoutSubviews]; 40 | self.backgroundView.frame = self.bounds; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /SGKit/Core/SGCollectionView/SGCollectionViewFlowLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGCollectionViewFlowLayout.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/5. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | @class SGCollectionViewFlowLayout; 11 | 12 | @protocol SGCollectionViewDelegateFlowLayout 13 | 14 | @optional 15 | - (UIColor *)collectionView:(UICollectionView *)collectionView layout:(SGCollectionViewFlowLayout *)collectionViewLayout backgroundColorForSectionAtIndex:(NSInteger)section; 16 | - (UIView *)collectionView:(UICollectionView *)collectionView layout:(SGCollectionViewFlowLayout *)collectionViewLayout backgroundViewForSectionAtIndex:(NSInteger)section; 17 | 18 | @end 19 | 20 | // 不支持 collectionView delete/insert 操作,会导致未知错误 21 | @interface SGCollectionViewFlowLayout : UICollectionViewFlowLayout 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /SGKit/Core/SGCollectionView/SGCollectionViewFlowLayout.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGCollectionViewFlowLayout.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/5. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGCollectionViewFlowLayout.h" 10 | #import "SGCollectionViewLayoutAttributes.h" 11 | #import "SGCollectionReusableView.h" 12 | 13 | static NSString * const DecorationReuseIdentifier = @"DecorationReuseIdentifier"; 14 | 15 | @interface SGCollectionViewFlowLayout () 16 | 17 | @property (nonatomic, strong) NSMutableArray * decorationAttributesArray; 18 | 19 | @end 20 | 21 | @implementation SGCollectionViewFlowLayout 22 | 23 | + (Class)layoutAttributesClass 24 | { 25 | return [SGCollectionViewLayoutAttributes class]; 26 | } 27 | 28 | - (void)prepareLayout 29 | { 30 | [super prepareLayout]; 31 | 32 | if (![self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:backgroundColorForSectionAtIndex:)]) return; 33 | 34 | NSInteger sectionCount = [self.collectionView numberOfSections]; 35 | if (!sectionCount) return; 36 | 37 | [self registerClass:[SGCollectionReusableView class] forDecorationViewOfKind:DecorationReuseIdentifier]; 38 | [self.decorationAttributesArray removeAllObjects]; 39 | for (NSInteger i = 0; i < sectionCount; i++) 40 | { 41 | NSInteger itemCount = [self.collectionView numberOfItemsInSection:i]; 42 | if (!itemCount) continue; 43 | 44 | UICollectionViewLayoutAttributes * first = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:i]]; 45 | UICollectionViewLayoutAttributes * last = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:itemCount-1 inSection:i]]; 46 | 47 | UIEdgeInsets sectionInset = self.sectionInset; 48 | if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) { 49 | sectionInset = [(id )self.collectionView.delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:i]; 50 | } 51 | 52 | CGRect sectionFrame = CGRectUnion(first.frame, last.frame); 53 | sectionFrame.origin.x -= sectionInset.left; 54 | sectionFrame.origin.y -= sectionInset.top; 55 | 56 | if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) { 57 | sectionFrame.size.width += sectionInset.left + sectionInset.right; 58 | sectionFrame.size.height = self.collectionView.frame.size.height; 59 | } else { 60 | sectionFrame.size.width = self.collectionView.frame.size.width; 61 | sectionFrame.size.height += sectionInset.top + sectionInset.bottom; 62 | } 63 | 64 | SGCollectionViewLayoutAttributes * attributes = [SGCollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:DecorationReuseIdentifier withIndexPath:[NSIndexPath indexPathForItem:0 inSection:i]]; 65 | attributes.frame = sectionFrame; 66 | attributes.zIndex = -1; 67 | attributes.color = [(id )self.collectionView.delegate collectionView:self.collectionView layout:self backgroundColorForSectionAtIndex:i]; 68 | if ([self.collectionView.delegate respondsToSelector:@selector(collectionView:layout:backgroundViewForSectionAtIndex:)]) { 69 | attributes.backgroundView = [(id )self.collectionView.delegate collectionView:self.collectionView layout:self backgroundViewForSectionAtIndex:i]; 70 | } 71 | [self.decorationAttributesArray addObject:attributes]; 72 | } 73 | } 74 | 75 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 76 | { 77 | NSArray * attributes = [super layoutAttributesForElementsInRect:rect]; 78 | NSMutableArray * allAttributes = [NSMutableArray arrayWithArray:attributes]; 79 | for (SGCollectionViewLayoutAttributes * obj in self.decorationAttributesArray) { 80 | if (CGRectIntersectsRect(rect, obj.frame)) { 81 | [allAttributes addObject:obj]; 82 | } 83 | } 84 | return allAttributes; 85 | } 86 | 87 | - (NSMutableArray *)decorationAttributesArray 88 | { 89 | if (!_decorationAttributesArray) { 90 | _decorationAttributesArray = [NSMutableArray array]; 91 | } 92 | return _decorationAttributesArray; 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /SGKit/Core/SGCollectionView/SGCollectionViewLayoutAttributes.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGCollectionViewLayoutAttributes.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/5. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SGCollectionViewLayoutAttributes : UICollectionViewLayoutAttributes 12 | 13 | @property (nonatomic, strong) UIColor * color; 14 | @property (nonatomic, strong) UIView * backgroundView; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /SGKit/Core/SGCollectionView/SGCollectionViewLayoutAttributes.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGCollectionViewLayoutAttributes.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/5. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGCollectionViewLayoutAttributes.h" 10 | 11 | @implementation SGCollectionViewLayoutAttributes 12 | 13 | - (id)copyWithZone:(NSZone *)zone 14 | { 15 | SGCollectionViewLayoutAttributes * obj = [super copyWithZone:zone]; 16 | obj.color = [self.color copyWithZone:zone]; 17 | obj.backgroundView = self.backgroundView; 18 | return obj; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SGKit/Core/SGGuideView/SGGuideView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GuideView.h 3 | // opera 4 | // 5 | // Created by Single on 15/12/20. 6 | // Copyright © 2015年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class SGGuideView; 12 | 13 | @protocol SGGuideViewDelegate 14 | 15 | - (void)guideViewWillDisapper:(SGGuideView *)guideView; 16 | - (void)guideViewDidDisapper:(SGGuideView *)guideView; 17 | 18 | @end 19 | 20 | @interface SGGuideView : UIView 21 | 22 | + (instancetype)new NS_UNAVAILABLE; 23 | - (instancetype)init NS_UNAVAILABLE; 24 | - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; 25 | 26 | + (instancetype)guideViewWithImageNames:(NSArray *)imageNames; 27 | 28 | @property (nonatomic, weak) id delegate; 29 | @property (nonatomic, strong, readonly) UIImageView * backgroundImageView; 30 | @property (nonatomic, assign) UIViewContentMode imageViewsContentMode; // default is UIViewContentModeScaleAspectFill. 31 | @property (nonatomic, assign) BOOL pageControlHidden; // default is NO. 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /SGKit/Core/SGGuideView/SGGuideView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GuideView.m 3 | // opera 4 | // 5 | // Created by Single on 15/12/20. 6 | // Copyright © 2015年 single. All rights reserved. 7 | // 8 | 9 | #import "SGGuideView.h" 10 | 11 | @interface SGGuideView () 12 | 13 | { 14 | dispatch_once_t onceToken; 15 | } 16 | 17 | @property (nonatomic, strong) NSArray * imageNames; 18 | @property (nonatomic, strong) NSArray * imageViews; 19 | 20 | @property (nonatomic, strong) UIScrollView * scrollView; 21 | @property (nonatomic, strong) UIImageView * backgroundImageView; 22 | @property (nonatomic, strong) UIPageControl * pageControl; 23 | 24 | @end 25 | 26 | @implementation SGGuideView 27 | 28 | + (instancetype)guideViewWithImageNames:(NSArray *)imageNames 29 | { 30 | return [[self alloc] initWithImageNames:imageNames]; 31 | } 32 | 33 | - (instancetype)initWithImageNames:(NSArray *)imageNames 34 | { 35 | if (self = [super initWithFrame:CGRectZero]) 36 | { 37 | self.imageNames = imageNames; 38 | [self setup]; 39 | } 40 | return self; 41 | } 42 | 43 | - (void)setup 44 | { 45 | self.backgroundColor =[UIColor clearColor]; 46 | self.imageViewsContentMode = UIViewContentModeScaleAspectFill; 47 | 48 | [self addSubview:self.scrollView]; 49 | [self addSubview:self.pageControl]; 50 | 51 | [self.imageViews enumerateObjectsUsingBlock:^(UIImageView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 52 | [self.scrollView addSubview:obj]; 53 | }]; 54 | [self layoutSubviews]; 55 | } 56 | 57 | - (void)layoutSubviews 58 | { 59 | [super layoutSubviews]; 60 | 61 | CGRect frame = self.bounds; 62 | self.backgroundImageView.frame = frame; 63 | self.scrollView.frame = frame; 64 | self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(frame) * self.imageNames.count, CGRectGetHeight(frame)); 65 | self.pageControl.frame = CGRectMake(0, CGRectGetHeight(frame) - 40, CGRectGetWidth(frame), 20); 66 | [self.imageViews enumerateObjectsUsingBlock:^(UIImageView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 67 | obj.frame = CGRectMake(CGRectGetWidth(frame) * idx, 0, CGRectGetWidth(frame), CGRectGetHeight(frame)); 68 | }]; 69 | } 70 | 71 | - (UIImageView *)backgroundImageView 72 | { 73 | if (!_backgroundImageView) { 74 | _backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; 75 | _backgroundImageView.backgroundColor = [UIColor clearColor]; 76 | [self insertSubview:_backgroundImageView atIndex:0]; 77 | } 78 | return _backgroundImageView; 79 | } 80 | 81 | - (UIScrollView *)scrollView 82 | { 83 | if (!_scrollView) { 84 | _scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero]; 85 | 86 | _scrollView.backgroundColor = [UIColor clearColor]; 87 | _scrollView.pagingEnabled = YES; 88 | _scrollView.showsHorizontalScrollIndicator = NO; 89 | _scrollView.showsVerticalScrollIndicator = NO; 90 | _scrollView.scrollsToTop = NO; 91 | _scrollView.delegate = self; 92 | _scrollView.bounces = YES; 93 | } 94 | return _scrollView; 95 | } 96 | 97 | - (UIPageControl *)pageControl 98 | { 99 | if (!_pageControl) { 100 | _pageControl = [[UIPageControl alloc] initWithFrame:CGRectZero]; 101 | 102 | _pageControl.backgroundColor = [UIColor clearColor]; 103 | _pageControl.numberOfPages = self.imageNames.count; 104 | _pageControl.userInteractionEnabled = NO; 105 | _pageControl.currentPage = 0; 106 | _pageControl.backgroundColor = [UIColor clearColor]; 107 | } 108 | return _pageControl; 109 | } 110 | 111 | - (void)setPageControlHidden:(BOOL)pageControlHidden 112 | { 113 | self.pageControl.hidden = pageControlHidden; 114 | } 115 | 116 | - (BOOL)pageControlHidden 117 | { 118 | return self.pageControl.hidden; 119 | } 120 | 121 | - (void)setImageViewsContentMode:(UIViewContentMode)imageViewsContentMode 122 | { 123 | if (_imageViewsContentMode != imageViewsContentMode) { 124 | _imageViewsContentMode = imageViewsContentMode; 125 | [self.imageViews enumerateObjectsUsingBlock:^(UIImageView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 126 | obj.contentMode = _imageViewsContentMode; 127 | }]; 128 | } 129 | } 130 | 131 | - (NSArray *)imageViews 132 | { 133 | if (!_imageViews) { 134 | NSMutableArray * array = [NSMutableArray arrayWithCapacity:self.imageNames.count]; 135 | for (int i = 0; i < self.imageNames.count; i++) 136 | { 137 | UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; 138 | 139 | imageView.backgroundColor = [UIColor whiteColor]; 140 | imageView.contentMode = self.imageViewsContentMode; 141 | imageView.image = [UIImage imageNamed:[self.imageNames objectAtIndex:i]]; 142 | imageView.clipsToBounds = YES; 143 | 144 | [array addObject:imageView]; 145 | 146 | if (i == self.imageNames.count - 1) { 147 | imageView.userInteractionEnabled = YES; 148 | UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touchesLastImage)]; 149 | [imageView addGestureRecognizer:tap]; 150 | } 151 | } 152 | _imageViews = array; 153 | } 154 | return _imageViews; 155 | } 156 | 157 | #pragma mark - ScrollViewDelegate 158 | 159 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 160 | { 161 | CGFloat pageWidth = CGRectGetWidth(self.bounds); 162 | int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; 163 | 164 | self.pageControl.currentPage = page; 165 | 166 | if ((self.scrollView.contentOffset.x > ((self.imageNames.count - 1) * self.frame.size.width + 50))) { 167 | [self touchesLastImage]; 168 | } 169 | } 170 | 171 | #pragma mrak - DataSource 172 | 173 | - (void)touchesLastImage 174 | { 175 | dispatch_once(&onceToken, ^{ 176 | if ([self.delegate respondsToSelector:@selector(guideViewWillDisapper:)]) { 177 | [self.delegate guideViewWillDisapper:self]; 178 | } 179 | [UIView animateWithDuration:1.0f animations:^{ 180 | self.alpha = 0.0; 181 | } completion:^(BOOL finished) { 182 | if (finished) { 183 | [self removeFromSuperview]; 184 | if ([self.delegate respondsToSelector:@selector(guideViewDidDisapper:)]) { 185 | [self.delegate guideViewDidDisapper:self]; 186 | } 187 | } 188 | }]; 189 | }); 190 | } 191 | 192 | - (void)dealloc 193 | { 194 | NSLog(@"SGGuideView release"); 195 | } 196 | 197 | @end 198 | -------------------------------------------------------------------------------- /SGKit/Core/SGImagePlyer/SGImagePlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGImagePlayer.h 3 | // imv_ios_v3 4 | // 5 | // Created by Single on 16/1/18. 6 | // Copyright © 2016年 YYT. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class SGImagePlayer; 12 | 13 | // pageControl style 14 | typedef NS_ENUM(NSUInteger, SGPageControlStyle) { 15 | SGPageControlStyleNone, 16 | SGPageControlStyleSystem, // default 17 | SGPageControlStyleNumber, 18 | }; 19 | 20 | // pageControl position 21 | typedef NS_ENUM(NSUInteger, SGPageControlPosition) { 22 | SGPageControlPositionTopLeft, 23 | SGPageControlPositionTopCenter, 24 | SGPageControlPositionTopRight, 25 | SGPageControlPositionBottomLeft, 26 | SGPageControlPositionBottomCenter, // default 27 | SGPageControlPositionBottomRight, 28 | }; 29 | 30 | @protocol SGImagePlayerDelegate 31 | 32 | - (NSInteger)numberOfImagesInImagePlayer:(SGImagePlayer *)imagePlayer; 33 | - (void)imagePlayerDidFinishLoad:(SGImagePlayer *)imagePlayer currentIndex:(NSInteger)index; 34 | - (void)imagePlayer:(SGImagePlayer *)imagePlayer imageView:(UIImageView *)imageView atIndex:(NSInteger)index; 35 | 36 | @optional 37 | - (void)imagePlayer:(SGImagePlayer *)imagePlayer didBeginScroll:(NSInteger)index; 38 | - (void)imagePlayer:(SGImagePlayer *)imagePlayer didEndScroll:(NSInteger)index; 39 | - (void)imagePlayer:(SGImagePlayer *)imagePlayer didTapAtIndex:(NSInteger)index; 40 | - (void)imagePlayer:(SGImagePlayer *)imagePlayer didLongPressAtIndex:(NSInteger)index; 41 | 42 | // pageControl style 43 | - (void)ImagePlayer:(SGImagePlayer *)imagePlayer editPageControlSystem:(UIPageControl *)pageControlSystem; 44 | - (void)imagePlayer:(SGImagePlayer *)imagePlayer editPageControlNumber:(UILabel *)pageControlNumber; 45 | 46 | @end 47 | 48 | @interface SGImagePlayer : UIView 49 | 50 | @property (nonatomic, weak) id delegate; 51 | @property (nonatomic, assign, readonly) BOOL scrolling; 52 | @property (nonatomic, assign) BOOL autoScroll; // defautl is YES 53 | @property (nonatomic, assign) BOOL autoPauseAndResumeWhenMoveToWindow; // default is YES 54 | @property (nonatomic, assign) NSTimeInterval animationDuration; // default is 2s 55 | 56 | @property (nonatomic, assign) UIViewContentMode imageViewsContentMode; // default is UIViewContentModeScaleAspectFill. 57 | 58 | - (void)resume; 59 | - (void)pause; 60 | - (void)reloadData; 61 | 62 | - (void)clearTimer; // auto execute when removeFromSuperView 63 | 64 | // pageControl 65 | @property (nonatomic, assign) SGPageControlStyle pageControlStyle; // default is SGPageControlStyleSystem 66 | @property (nonatomic, assign) SGPageControlPosition pageControlPosition; // default is SGPageControlPositionBottomCenter 67 | @property (nonatomic, assign) CGFloat pageControlHorizontalMargin; // default is 10 68 | @property (nonatomic, assign) CGFloat pageControlVerticalMargin; // default is 3 69 | 70 | @end 71 | 72 | 73 | -------------------------------------------------------------------------------- /SGKit/Core/SGImagePlyer/SGImagePlayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGImagePlayer.m 3 | // imv_ios_v3 4 | // 5 | // Created by Single on 16/1/18. 6 | // Copyright © 2016年 YYT. All rights reserved. 7 | // 8 | 9 | #import "SGImagePlayer.h" 10 | 11 | static CGFloat const SGImagePlayerAnimationDuration = 2; 12 | static CGFloat const SGImagePlayerPageControlHorizontalMargin = 10; 13 | static CGFloat const SGImagePlayerPageControlVerticalMargin = 3; 14 | static CGFloat const SGImagePlayerPageControlHeight = 25; 15 | 16 | @interface SGImagePlayer () 17 | 18 | @property (nonatomic, weak) NSTimer * timer; 19 | @property (nonatomic, strong) UIScrollView * scrollView; 20 | @property (nonatomic, strong) NSArray * imageViews; 21 | 22 | @property (nonatomic, strong) UIPageControl * pageSystem; 23 | @property (nonatomic, strong) UILabel * pageNumber; 24 | 25 | @property (nonatomic, assign) BOOL scrolling; 26 | @property (nonatomic, assign) BOOL needReload; 27 | @property (nonatomic, assign) NSInteger numberOfImage; 28 | @property (nonatomic, assign) NSInteger currentImage; 29 | 30 | @end 31 | 32 | @implementation SGImagePlayer 33 | 34 | - (void)pause 35 | { 36 | [self pauseTimer]; 37 | } 38 | 39 | - (void)resume 40 | { 41 | [self resumTimer]; 42 | } 43 | 44 | - (void)reloadData 45 | { 46 | if (self.scrolling) { 47 | self.needReload = YES; 48 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 49 | self.needReload = NO; 50 | [self doReloadData]; 51 | }); 52 | } else { 53 | [self doReloadData]; 54 | } 55 | } 56 | 57 | - (void)doReloadData 58 | { 59 | [self setupScrollView]; 60 | [self setupTimer]; 61 | [self setupPageControl]; 62 | [self refresh]; 63 | 64 | if ([self.delegate respondsToSelector:@selector(imagePlayerDidFinishLoad:currentIndex:)]) { 65 | [self.delegate imagePlayerDidFinishLoad:self currentIndex:self.currentImage]; 66 | } 67 | } 68 | 69 | - (void)setupScrollView 70 | { 71 | [self clearScrollView]; 72 | 73 | self.numberOfImage = [self.delegate numberOfImagesInImagePlayer:self]; 74 | self.currentImage = 0; 75 | 76 | if (self.numberOfImage == 0) return; 77 | 78 | self.scrllView.contentSize = CGSizeMake(self.frame.size.width * (self.numberOfImage == 1 ? 1 : 3), self.frame.size.height); 79 | self.scrllView.contentOffset = CGPointMake(self.frame.size.width * (self.numberOfImage != 1), 0); 80 | 81 | NSMutableArray * temp = [NSMutableArray arrayWithCapacity:self.numberOfImage]; 82 | for (NSInteger i = 0; i < (self.numberOfImage==1 ? 1 : 3); i++) 83 | { 84 | UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width * i, 0, self.frame.size.width, self.frame.size.height)]; 85 | imageView.clipsToBounds = YES; 86 | imageView.contentMode = self.imageViewsContentMode; 87 | imageView.backgroundColor = [UIColor clearColor]; 88 | imageView.userInteractionEnabled = YES; 89 | [self.scrllView addSubview:imageView]; 90 | [temp addObject:imageView]; 91 | 92 | UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewTap:)]; 93 | UILongPressGestureRecognizer * longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewLongPress:)]; 94 | 95 | tap.delegate = self; 96 | longPress.delegate = self; 97 | [imageView addGestureRecognizer:tap]; 98 | [imageView addGestureRecognizer:longPress]; 99 | } 100 | self.imageViews = temp; 101 | } 102 | 103 | - (void)clearScrollView 104 | { 105 | [self.scrllView.subviews enumerateObjectsUsingBlock:^(UIView * obj, NSUInteger idx, BOOL * stop) { 106 | if ([obj isKindOfClass:[UIImageView class]]) { 107 | [obj.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull subObj, NSUInteger subIdx, BOOL * _Nonnull subStop) { 108 | [subObj removeFromSuperview]; 109 | }]; 110 | } 111 | [obj removeFromSuperview]; 112 | }]; 113 | self.imageViews = nil; 114 | } 115 | 116 | - (void)pauseTimer 117 | { 118 | self.timer.fireDate = [NSDate distantFuture]; 119 | } 120 | 121 | - (void)resumTimer 122 | { 123 | if (self.needReload) return; 124 | self.timer.fireDate = [NSDate dateWithTimeIntervalSinceNow:self.animationDuration]; 125 | } 126 | 127 | - (void)setupTimer 128 | { 129 | [self clearTimer]; 130 | 131 | if (self.autoScroll) { 132 | if (self.numberOfImage > 1) { 133 | self.timer = [NSTimer scheduledTimerWithTimeInterval:self.animationDuration target:self selector:@selector(handleTimer) userInfo:nil repeats:YES]; 134 | self.timer.fireDate = [NSDate dateWithTimeIntervalSinceNow:self.animationDuration]; 135 | [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; 136 | } 137 | } 138 | } 139 | 140 | - (void)clearTimer 141 | { 142 | if (self.timer) { 143 | [self.timer invalidate]; 144 | self.timer = nil; 145 | } 146 | } 147 | 148 | - (void)handleTimer 149 | { 150 | [self.scrllView setContentOffset:CGPointMake(self.scrllView.contentSize.width - self.frame.size.width, 0) animated:YES]; 151 | } 152 | 153 | - (void)setupPageControl 154 | { 155 | [self clearPageControl]; 156 | 157 | switch (self.pageControlStyle) 158 | { 159 | case SGPageControlStyleNone: 160 | break; 161 | case SGPageControlStyleSystem: 162 | { 163 | self.pageSystem = [[UIPageControl alloc] init]; 164 | [self refreshPageControlPosition]; 165 | self.pageSystem.hidesForSinglePage = YES; 166 | self.pageSystem.numberOfPages = self.numberOfImage; 167 | self.pageSystem.currentPage = self.currentImage; 168 | [self addSubview:self.pageSystem]; 169 | if ([self.delegate respondsToSelector:@selector(ImagePlayer:editPageControlSystem:)]) { 170 | [self.delegate ImagePlayer:self editPageControlSystem:self.pageSystem]; 171 | } 172 | } 173 | break; 174 | case SGPageControlStyleNumber: 175 | { 176 | self.pageNumber = [[UILabel alloc] init]; 177 | [self refreshPageControlPosition]; 178 | self.pageNumber.font = [UIFont systemFontOfSize:10]; 179 | self.pageNumber.textColor = [UIColor whiteColor]; 180 | [self refreshPageNumber]; 181 | [self addSubview:self.pageNumber]; 182 | if ([self.delegate respondsToSelector:@selector(imagePlayer:editPageControlNumber:)]) { 183 | [self.delegate imagePlayer:self editPageControlNumber:self.pageNumber]; 184 | } 185 | } 186 | break; 187 | } 188 | } 189 | 190 | - (void)clearPageControl 191 | { 192 | if (self.pageSystem) { 193 | [self.pageSystem removeFromSuperview]; 194 | } 195 | if (self.pageNumber) { 196 | [self.pageNumber removeFromSuperview]; 197 | } 198 | } 199 | 200 | - (void)refresh 201 | { 202 | if (self.needReload) return; 203 | [self refreshImageView]; 204 | [self refreshLocation]; 205 | [self refreshPageControl]; 206 | } 207 | 208 | - (void)refreshImageView 209 | { 210 | for (NSInteger i = 0; i < (self.numberOfImage>1 ? 3 : self.numberOfImage); i++) { 211 | [self.delegate imagePlayer:self imageView:[self.imageViews objectAtIndex:i] atIndex:[self indexTransform:i]]; 212 | } 213 | } 214 | 215 | - (void)refreshLocation 216 | { 217 | self.scrllView.contentOffset = CGPointMake(self.frame.size.width * (self.numberOfImage != 1), 0); 218 | } 219 | 220 | - (void)refreshPageControl 221 | { 222 | switch (self.pageControlStyle) 223 | { 224 | case SGPageControlStyleNone: 225 | return; 226 | case SGPageControlStyleSystem: 227 | { 228 | self.pageSystem.currentPage = self.currentImage; 229 | } 230 | break; 231 | case SGPageControlStyleNumber: 232 | { 233 | [self refreshPageNumber]; 234 | } 235 | break; 236 | } 237 | } 238 | 239 | - (void)refreshPageNumber 240 | { 241 | self.pageNumber.hidden = self.numberOfImage <= 1; 242 | self.pageNumber.text = [NSString stringWithFormat:@"%ld/%ld", (long)self.currentImage + 1, (long)self.numberOfImage]; 243 | } 244 | 245 | - (void)refreshPageControlPosition 246 | { 247 | CGFloat x, y, w, h = SGImagePlayerPageControlHeight; 248 | if (self.pageControlStyle == SGPageControlStyleSystem) 249 | { 250 | switch (self.pageControlPosition) { 251 | case SGPageControlPositionTopLeft: 252 | x = self.pageControlHorizontalMargin; 253 | y = self.pageControlVerticalMargin; 254 | w = [self.pageSystem sizeForNumberOfPages:self.numberOfImage].width; 255 | break; 256 | case SGPageControlPositionTopCenter: 257 | x = 0; 258 | y = self.pageControlVerticalMargin; 259 | w = self.frame.size.width; 260 | break; 261 | case SGPageControlPositionTopRight: 262 | y = self.pageControlVerticalMargin; 263 | w = [self.pageSystem sizeForNumberOfPages:self.numberOfImage].width; 264 | x = (self.frame.size.width - w - self.pageControlHorizontalMargin); 265 | break; 266 | case SGPageControlPositionBottomLeft: 267 | x = self.pageControlHorizontalMargin; 268 | y = (self.frame.size.height - SGImagePlayerPageControlHeight - self.pageControlVerticalMargin); 269 | w = [self.pageSystem sizeForNumberOfPages:self.numberOfImage].width; 270 | break; 271 | case SGPageControlPositionBottomCenter: 272 | x = 0; 273 | y = (self.frame.size.height - SGImagePlayerPageControlHeight - self.pageControlVerticalMargin); 274 | w = self.frame.size.width; 275 | break; 276 | case SGPageControlPositionBottomRight: 277 | y = (self.frame.size.height - SGImagePlayerPageControlHeight - self.pageControlVerticalMargin); 278 | w = [self.pageSystem sizeForNumberOfPages:self.numberOfImage].width; 279 | x = (self.frame.size.width - w - self.pageControlHorizontalMargin); 280 | break; 281 | } 282 | self.pageSystem.frame = CGRectMake(x, y, w, h); 283 | } 284 | else if (self.pageControlStyle == SGPageControlStyleNumber) 285 | { 286 | x = self.pageControlHorizontalMargin; w = self.frame.size.width - 2*self.pageControlHorizontalMargin; 287 | switch (self.pageControlPosition) { 288 | case SGPageControlPositionTopLeft: 289 | y = self.pageControlVerticalMargin; 290 | self.pageNumber.textAlignment = NSTextAlignmentLeft; 291 | break; 292 | case SGPageControlPositionTopCenter: 293 | y = self.pageControlVerticalMargin; 294 | self.pageNumber.textAlignment = NSTextAlignmentCenter; 295 | break; 296 | case SGPageControlPositionTopRight: 297 | y = self.pageControlVerticalMargin; 298 | self.pageNumber.textAlignment = NSTextAlignmentRight; 299 | break; 300 | case SGPageControlPositionBottomLeft: 301 | y = (self.frame.size.height - SGImagePlayerPageControlHeight - self.pageControlVerticalMargin); 302 | self.pageNumber.textAlignment = NSTextAlignmentLeft; 303 | break; 304 | case SGPageControlPositionBottomCenter: 305 | y = (self.frame.size.height - SGImagePlayerPageControlHeight - self.pageControlVerticalMargin); 306 | self.pageNumber.textAlignment = NSTextAlignmentCenter; 307 | break; 308 | case SGPageControlPositionBottomRight: 309 | y = (self.frame.size.height - SGImagePlayerPageControlHeight - self.pageControlVerticalMargin); 310 | self.pageNumber.textAlignment = NSTextAlignmentRight; 311 | break; 312 | } 313 | self.pageNumber.frame = CGRectMake(x, y, w, h);; 314 | } 315 | } 316 | 317 | - (void)refreshLayout 318 | { 319 | self.scrollView.frame = self.bounds; 320 | self.scrllView.contentSize = CGSizeMake(self.frame.size.width * (self.numberOfImage == 1 ? 1 : 3), self.frame.size.height); 321 | self.scrllView.contentOffset = CGPointMake(self.frame.size.width * (self.numberOfImage != 1), 0); 322 | [self.imageViews enumerateObjectsUsingBlock:^(UIImageView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 323 | obj.frame = CGRectMake(self.frame.size.width * idx, 0, self.frame.size.width, self.frame.size.height); 324 | }]; 325 | [self refreshPageControlPosition]; 326 | [self resumTimer]; 327 | } 328 | 329 | - (void)layoutSubviews 330 | { 331 | [super layoutSubviews]; 332 | [self refreshLayout]; 333 | } 334 | 335 | - (NSInteger)indexTransform:(NSInteger)imageViewIndex 336 | { 337 | switch (imageViewIndex) 338 | { 339 | case 0: 340 | return (self.currentImage-1)<0 ? self.numberOfImage-1 : self.currentImage-1; 341 | case 1: 342 | return self.currentImage; 343 | default: 344 | return (self.currentImage+1)>(self.numberOfImage-1) ? 0 : self.currentImage+1; 345 | } 346 | } 347 | 348 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 349 | { 350 | if (!self.scrolling && [self.delegate respondsToSelector:@selector(imagePlayer:didBeginScroll:)]) { 351 | [self.delegate imagePlayer:self didBeginScroll:self.currentImage]; 352 | } 353 | 354 | self.scrolling = YES; 355 | 356 | if (self.scrllView.contentOffset.x == 0) 357 | { 358 | self.currentImage = (self.currentImage-1)<0 ? self.numberOfImage-1 : self.currentImage-1; 359 | self.scrolling = NO; 360 | [self refresh]; 361 | } 362 | else if (self.scrllView.contentOffset.x == self.frame.size.width * 2) 363 | { 364 | self.currentImage = (self.currentImage+1)>(self.numberOfImage-1) ? 0 : self.currentImage+1; 365 | self.scrolling = NO; 366 | [self refresh]; 367 | } 368 | [self pauseTimer]; 369 | } 370 | 371 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 372 | { 373 | self.scrolling = NO; 374 | [self didEndScroll]; 375 | [self resumTimer]; 376 | } 377 | 378 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView 379 | { 380 | self.scrolling = NO; 381 | [self didEndScroll]; 382 | [self resumTimer]; 383 | } 384 | 385 | - (void)didEndScroll 386 | { 387 | if (self.needReload) return; 388 | if ([self.delegate respondsToSelector:@selector(imagePlayer:didEndScroll:)]) { 389 | [self.delegate imagePlayer:self didEndScroll:self.currentImage]; 390 | } 391 | } 392 | 393 | - (void)imageViewTap:(UITapGestureRecognizer *)recognizer 394 | { 395 | switch (recognizer.state) 396 | { 397 | case UIGestureRecognizerStateEnded: 398 | { 399 | if ([self.delegate respondsToSelector:@selector(imagePlayer:didTapAtIndex:)]) { 400 | [self.delegate imagePlayer:self didTapAtIndex:self.currentImage]; 401 | } 402 | [self resumTimer]; 403 | } 404 | break; 405 | default: 406 | { 407 | [self resumTimer]; 408 | } 409 | break; 410 | } 411 | } 412 | 413 | - (void)imageViewLongPress:(UILongPressGestureRecognizer *)recognizer 414 | { 415 | 416 | switch (recognizer.state) 417 | { 418 | case UIGestureRecognizerStateBegan: 419 | { 420 | if ([self.delegate respondsToSelector:@selector(imagePlayer:didLongPressAtIndex:)]) { 421 | [self.delegate imagePlayer:self didLongPressAtIndex:self.currentImage]; 422 | } 423 | } 424 | break; 425 | case UIGestureRecognizerStateChanged: 426 | break; 427 | default: 428 | { 429 | [self resumTimer]; 430 | } 431 | break; 432 | } 433 | } 434 | 435 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 436 | { 437 | [self pauseTimer]; 438 | return YES; 439 | } 440 | 441 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 442 | { 443 | if (self = [super initWithCoder:aDecoder]) { 444 | [self UILayout]; 445 | } 446 | return self; 447 | } 448 | 449 | - (instancetype)initWithFrame:(CGRect)frame 450 | { 451 | if (self = [super initWithFrame:frame]) { 452 | [self UILayout]; 453 | } 454 | return self; 455 | } 456 | 457 | - (void)UILayout 458 | { 459 | self.backgroundColor = [UIColor clearColor]; 460 | self.imageViewsContentMode = UIViewContentModeScaleAspectFill; 461 | [self addSubview:self.scrllView]; 462 | 463 | self.autoScroll = YES; 464 | self.autoPauseAndResumeWhenMoveToWindow = YES; 465 | self.animationDuration = SGImagePlayerAnimationDuration; 466 | self.pageControlStyle = SGPageControlStyleSystem; 467 | self.pageControlPosition = SGPageControlPositionBottomCenter; 468 | self.pageControlHorizontalMargin = SGImagePlayerPageControlHorizontalMargin; 469 | self.pageControlVerticalMargin = SGImagePlayerPageControlVerticalMargin; 470 | } 471 | 472 | - (UIScrollView *)scrllView 473 | { 474 | if (!_scrollView) { 475 | _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 476 | _scrollView.backgroundColor = [UIColor clearColor]; 477 | _scrollView.showsHorizontalScrollIndicator = NO; 478 | _scrollView.showsVerticalScrollIndicator = NO; 479 | _scrollView.clipsToBounds = YES; 480 | _scrollView.pagingEnabled = YES; 481 | _scrollView.delegate = self; 482 | _scrollView.bounces = NO; 483 | } 484 | return _scrollView; 485 | } 486 | 487 | - (void)setDelegate:(id)delegate 488 | { 489 | if (_delegate != delegate) { 490 | _delegate = delegate; 491 | [self reloadData]; 492 | } 493 | } 494 | 495 | - (void)setAutoScroll:(BOOL)autoScroll 496 | { 497 | if (_autoScroll != autoScroll) { 498 | _autoScroll = autoScroll; 499 | if (autoScroll) { 500 | [self setupTimer]; 501 | } else { 502 | [self clearTimer]; 503 | } 504 | } 505 | } 506 | 507 | - (void)setImageViewsContentMode:(UIViewContentMode)imageViewsContentMode 508 | { 509 | if (_imageViewsContentMode != imageViewsContentMode) { 510 | _imageViewsContentMode = imageViewsContentMode; 511 | [self.imageViews enumerateObjectsUsingBlock:^(UIImageView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 512 | obj.contentMode = _imageViewsContentMode; 513 | }]; 514 | } 515 | } 516 | 517 | - (void)setPageControlStyle:(SGPageControlStyle)pageControlStyle 518 | { 519 | if (_pageControlStyle != pageControlStyle) { 520 | _pageControlStyle = pageControlStyle; 521 | [self setupPageControl]; 522 | } 523 | } 524 | 525 | - (void)setPageControlPosition:(SGPageControlPosition)pageControlPosition 526 | { 527 | if (_pageControlPosition != pageControlPosition) { 528 | _pageControlPosition = pageControlPosition; 529 | [self refreshPageControlPosition]; 530 | } 531 | } 532 | 533 | - (void)setPageControlHorizontalMargin:(CGFloat)pageControlHorizontalMargin 534 | { 535 | if (_pageControlHorizontalMargin != pageControlHorizontalMargin) { 536 | _pageControlHorizontalMargin = pageControlHorizontalMargin; 537 | [self refreshPageControlPosition]; 538 | } 539 | } 540 | 541 | - (void)setPageControlVerticalMargin:(CGFloat)pageControlVerticalMargin 542 | { 543 | if (_pageControlVerticalMargin != pageControlVerticalMargin) { 544 | _pageControlVerticalMargin = pageControlVerticalMargin; 545 | [self refreshPageControlPosition]; 546 | } 547 | } 548 | 549 | - (void)removeFromSuperview 550 | { 551 | if (self.timer) { 552 | [self clearTimer]; 553 | } 554 | [super removeFromSuperview]; 555 | } 556 | 557 | - (void)didMoveToWindow 558 | { 559 | if (self.autoPauseAndResumeWhenMoveToWindow) { 560 | if (self.window) { 561 | [self resume]; 562 | } else { 563 | [self pause]; 564 | } 565 | } 566 | } 567 | 568 | @end 569 | -------------------------------------------------------------------------------- /SGKit/Core/SGPageView/SGPageItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageItem.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/18. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SGPageView.h" 11 | 12 | @interface SGPageItem : UIView 13 | 14 | @property (nonatomic, strong) UIView * contentView; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /SGKit/Core/SGPageView/SGPageItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageItem.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/18. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGPageItem.h" 10 | 11 | @interface SGPageItem () 12 | 13 | @property (nonatomic, strong) UIScrollView * scrollView; 14 | 15 | @end 16 | 17 | @implementation SGPageItem 18 | 19 | - (void)setContentView:(UIView *)contentView 20 | { 21 | if (_contentView != contentView) { 22 | [_contentView removeFromSuperview]; 23 | _contentView = contentView; 24 | contentView.frame = self.bounds; 25 | [self.scrollView addSubview:contentView]; 26 | self.scrollView.backgroundColor = contentView.backgroundColor; 27 | } 28 | } 29 | 30 | - (UIScrollView *)scrollViewInPageItem:(UIView *)pageItem 31 | { 32 | return self.scrollView; 33 | } 34 | 35 | - (instancetype)initWithFrame:(CGRect)frame 36 | { 37 | if (self = [super initWithFrame:frame]) { 38 | [self superUILayout]; 39 | } 40 | return self; 41 | } 42 | 43 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 44 | { 45 | if (self = [super initWithCoder:aDecoder]) { 46 | [self superUILayout]; 47 | } 48 | return self; 49 | } 50 | 51 | - (void)superUILayout 52 | { 53 | self.backgroundColor = [UIColor clearColor]; 54 | [self addSubview:self.scrollView]; 55 | } 56 | 57 | - (void)layoutSubviews 58 | { 59 | [super layoutSubviews]; 60 | self.scrollView.frame = self.bounds; 61 | self.scrollView.contentSize = self.bounds.size; 62 | self.contentView.frame = self.bounds; 63 | } 64 | 65 | - (UIScrollView *)scrollView 66 | { 67 | if (_scrollView == nil) { 68 | _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 69 | _scrollView.backgroundColor = [UIColor clearColor]; 70 | _scrollView.showsVerticalScrollIndicator = NO; 71 | _scrollView.showsHorizontalScrollIndicator = NO; 72 | _scrollView.directionalLockEnabled = YES; 73 | _scrollView.contentSize = self.bounds.size; 74 | } 75 | return _scrollView; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /SGKit/Core/SGPageView/SGPageTitleItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageTitleItem.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SGPageTitleItem : UIView 12 | 13 | @property (nonatomic, assign, readonly) BOOL selected; 14 | @property (nonatomic, assign) CGFloat itemWidth; // default is 80; 15 | @property (nonatomic, assign) CGFloat bottomLineWidth; // default is 80; 16 | 17 | // subclass override 18 | - (void)normalStyle; 19 | - (void)selectedStyle; 20 | 21 | @end 22 | 23 | @interface SGPageTitleLabelItem : SGPageTitleItem 24 | 25 | @property (nonatomic, copy) NSString * text; 26 | @property (nonatomic, copy) UIFont * normalFont; // default is system font 14 27 | @property (nonatomic, copy) UIFont * selectedFont; // default is system font 14 28 | @property (nonatomic, copy) UIColor * normalColor; // default is blackColor 29 | @property (nonatomic, copy) UIColor * selectedColor; // default is blackColor 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /SGKit/Core/SGPageView/SGPageTitleItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageTitleItem.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGPageTitleItem.h" 10 | 11 | @interface SGPageTitleItem () 12 | 13 | @property (nonatomic, assign) BOOL selected; 14 | 15 | @end 16 | 17 | @implementation SGPageTitleItem 18 | 19 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 20 | { 21 | if (self = [super initWithCoder:aDecoder]) { 22 | [self superUILayout]; 23 | } 24 | return self; 25 | } 26 | 27 | - (instancetype)initWithFrame:(CGRect)frame 28 | { 29 | if (self = [super initWithFrame:frame]) { 30 | [self superUILayout]; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)superUILayout 36 | { 37 | self.itemWidth = 80; 38 | self.bottomLineWidth = 80; 39 | } 40 | 41 | - (void)normalStyle 42 | { 43 | self.selected = NO; 44 | } 45 | - (void)selectedStyle 46 | { 47 | self.selected = YES; 48 | } 49 | 50 | @end 51 | 52 | @interface SGPageTitleLabelItem () 53 | 54 | @property (nonatomic, strong) UILabel * textLabel; 55 | 56 | @end 57 | 58 | @implementation SGPageTitleLabelItem 59 | 60 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 61 | { 62 | if (self = [super initWithCoder:aDecoder]) { 63 | [self UILayout]; 64 | } 65 | return self; 66 | } 67 | 68 | - (instancetype)initWithFrame:(CGRect)frame 69 | { 70 | if (self = [super initWithFrame:frame]) { 71 | [self UILayout]; 72 | } 73 | return self; 74 | } 75 | 76 | - (void)UILayout 77 | { 78 | [self addSubview:self.textLabel]; 79 | } 80 | 81 | - (void)layoutSubviews 82 | { 83 | [super layoutSubviews]; 84 | self.textLabel.frame = self.bounds; 85 | } 86 | 87 | - (UILabel *)textLabel 88 | { 89 | if (!_textLabel) { 90 | _textLabel = [[UILabel alloc] initWithFrame:self.bounds]; 91 | _textLabel.font = [self font]; 92 | _textLabel.textColor = [self textColor]; 93 | _textLabel.textAlignment = NSTextAlignmentCenter; 94 | } 95 | return _textLabel; 96 | } 97 | 98 | - (void)normalStyle 99 | { 100 | [super normalStyle]; 101 | self.textLabel.font = [self font]; 102 | self.textLabel.textColor = [self textColor]; 103 | } 104 | 105 | - (void)selectedStyle 106 | { 107 | [super selectedStyle]; 108 | self.textLabel.font = [self font]; 109 | self.textLabel.textColor = [self textColor]; 110 | } 111 | 112 | - (UIFont *)font 113 | { 114 | UIFont * font = [UIFont systemFontOfSize:14]; 115 | if (self.selected) { 116 | if (self.selectedFont) { 117 | font = self.selectedFont; 118 | } else if (self.normalFont) { 119 | font = self.normalFont; 120 | } 121 | } else { 122 | if (self.normalFont) { 123 | font = self.normalFont; 124 | } 125 | } 126 | return font; 127 | } 128 | 129 | - (UIColor *)textColor 130 | { 131 | UIColor * color = [UIColor blackColor]; 132 | if (self.selected) { 133 | if (self.selectedColor) { 134 | color = self.selectedColor; 135 | } else if (self.normalColor) { 136 | color = self.normalColor; 137 | } 138 | } else { 139 | if (self.normalColor) { 140 | color = self.normalColor; 141 | } 142 | } 143 | return color; 144 | } 145 | 146 | - (void)setText:(NSString *)text 147 | { 148 | if (![_text isEqualToString:text]) { 149 | _text = text; 150 | self.textLabel.text = text; 151 | } 152 | } 153 | 154 | - (void)setNormalFont:(UIFont *)normalFont 155 | { 156 | _normalFont = normalFont; 157 | if (!self.selected) { 158 | self.textLabel.font = normalFont; 159 | } 160 | } 161 | 162 | - (void)setSelectedFont:(UIFont *)selectedFont 163 | { 164 | _selectedFont = selectedFont; 165 | if (self.selected) { 166 | self.textLabel.font = selectedFont; 167 | } 168 | } 169 | 170 | - (void)setNormalColor:(UIColor *)normalColor 171 | { 172 | _normalColor = normalColor; 173 | if (!self.selected) { 174 | self.textLabel.textColor = normalColor; 175 | } 176 | } 177 | 178 | - (void)setSelectedColor:(UIColor *)selectedColor 179 | { 180 | _selectedColor = selectedColor; 181 | if (self.selected) { 182 | self.textLabel.textColor = selectedColor; 183 | } 184 | } 185 | 186 | @end 187 | -------------------------------------------------------------------------------- /SGKit/Core/SGPageView/SGPageTitleView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageTitleView.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class SGPageView; 12 | 13 | @interface SGPageTitleView : UIView 14 | 15 | @property (nonatomic, weak, readonly) SGPageView * pageView; 16 | 17 | @property (nonatomic, assign) CGFloat leftMargin; // default is 0 18 | @property (nonatomic, assign) CGFloat rightMargin; // default is 0 19 | 20 | @property (nonatomic, assign) BOOL showBottomLine; // default is NO 21 | @property (nonatomic, assign) CGFloat bottomLineHeight; // default is 3 22 | @property (nonatomic, copy) UIColor * bottomLineColor; // default is red; 23 | @property (nonatomic, assign) CGFloat bottomLineAnimatedDuration; // default is 0.25s 24 | 25 | @property (nonatomic, assign) BOOL showBottomBoard; // default is NO 26 | @property (nonatomic, assign) CGFloat bottomBoardHeight; // default is 1 27 | @property (nonatomic, copy) UIColor * bottomBoardColor; // default is red; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /SGKit/Core/SGPageView/SGPageTitleView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageTitleView.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGPageTitleView.h" 10 | #import "SGPageView.h" 11 | 12 | @interface SGPageTitleItem () 13 | 14 | @property (nonatomic, assign) BOOL selected; 15 | 16 | @end 17 | 18 | @interface SGPageTitleView () 19 | 20 | @property (nonatomic, assign) BOOL didLoadData; 21 | @property (nonatomic, weak) SGPageView * pageView; 22 | @property (nonatomic, strong) UIScrollView * scrollView; 23 | @property (nonatomic, strong) NSArray * titleItems; 24 | @property (nonatomic, strong) UIView * bottomLineView; 25 | @property (nonatomic, strong) UIView * bottomBoardView; 26 | 27 | @end 28 | 29 | @implementation SGPageTitleView 30 | 31 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 32 | { 33 | if (self = [super initWithCoder:aDecoder]) { 34 | [self UILayout]; 35 | } 36 | return self; 37 | } 38 | 39 | - (instancetype)initWithFrame:(CGRect)frame 40 | { 41 | if (self = [super initWithFrame:frame]) { 42 | [self UILayout]; 43 | } 44 | return self; 45 | } 46 | 47 | - (void)UILayout 48 | { 49 | self.backgroundColor = [UIColor whiteColor]; 50 | [self insertSubview:self.scrollView atIndex:0]; 51 | 52 | self.bottomLineHeight = 3; 53 | self.bottomLineColor = [UIColor redColor]; 54 | self.bottomLineAnimatedDuration = 0.25; 55 | 56 | self.bottomBoardHeight = 1; 57 | self.bottomBoardColor = [UIColor redColor]; 58 | } 59 | 60 | - (void)scrollToIndex:(NSInteger)index 61 | { 62 | [self scrollToIndex:index animated:YES]; 63 | } 64 | 65 | - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated 66 | { 67 | [self selectedIndexDidChange]; 68 | [self resetBottomLineViewLocation:animated completion:^(BOOL finished) { 69 | [self resetScrollViewLocation:animated]; 70 | }]; 71 | } 72 | 73 | - (void)selectedIndexDidChange 74 | { 75 | [self.titleItems enumerateObjectsUsingBlock:^(SGPageTitleItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 76 | if (self.pageView.index == idx) { 77 | obj.selected = YES; 78 | [obj selectedStyle]; 79 | } else { 80 | obj.selected = NO; 81 | [obj normalStyle]; 82 | } 83 | }]; 84 | } 85 | 86 | - (void)reloadData 87 | { 88 | self.didLoadData = NO; 89 | 90 | [self.titleItems enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 91 | [obj removeFromSuperview]; 92 | }]; 93 | self.titleItems = nil; 94 | 95 | NSMutableArray * titleItemsTemp = [NSMutableArray arrayWithCapacity:self.pageView.numberOfPage]; 96 | for (NSInteger i = 0; i < self.pageView.numberOfPage; i++) { 97 | SGPageTitleItem * item = [self.pageView.delegate pageView:self.pageView pageTitleView:self titleItemAtIndex:i]; 98 | UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pageTitleItemTapAction:)]; 99 | [item addGestureRecognizer:tap]; 100 | [titleItemsTemp addObject:item]; 101 | [self.scrollView insertSubview:item atIndex:0]; 102 | } 103 | self.titleItems = titleItemsTemp; 104 | 105 | if (self.titleItems.count > 0) { 106 | self.didLoadData = YES; 107 | } 108 | 109 | [self resetLayout]; 110 | } 111 | 112 | - (void)pageTitleItemTapAction:(UITapGestureRecognizer *)tap 113 | { 114 | [self.pageView scrollToIndex:[self.titleItems indexOfObject:(SGPageTitleItem *)tap.view]]; 115 | } 116 | 117 | - (void)layoutSubviews 118 | { 119 | [super layoutSubviews]; 120 | [self resetLayout]; 121 | [self resetBottomBoardViewLayout]; 122 | } 123 | 124 | - (void)resetLayout 125 | { 126 | if (!self.didLoadData) return; 127 | 128 | self.scrollView.frame = self.bounds; 129 | 130 | __block CGFloat left = self.leftMargin; 131 | [self.titleItems enumerateObjectsUsingBlock:^(SGPageTitleItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 132 | obj.frame = CGRectMake(left, 0, obj.itemWidth, CGRectGetHeight(self.bounds)); 133 | left += obj.itemWidth; 134 | }]; 135 | 136 | self.scrollView.contentSize = CGSizeMake(left + self.rightMargin, CGRectGetHeight(self.bounds)); 137 | [self scrollToIndex:self.pageView.index animated:NO]; 138 | } 139 | 140 | - (void)resetBottomBoardViewLayout 141 | { 142 | self.bottomBoardView.frame = CGRectMake(0, CGRectGetHeight(self.frame) - self.bottomBoardHeight, CGRectGetWidth(self.frame), self.bottomBoardHeight); 143 | } 144 | 145 | - (void)resetBottomLineViewLocation:(BOOL)animated completion:(void (^)(BOOL finished))completion 146 | { 147 | if (!self.bottomLineView || !self.didLoadData) { 148 | if (completion) { 149 | completion(YES); 150 | } 151 | return; 152 | } 153 | if (self.bottomLineAnimatedDuration <= 0.03) animated = NO; 154 | 155 | SGPageTitleItem * item = [self.titleItems objectAtIndex:self.pageView.index]; 156 | CGFloat x = CGRectGetMinX(item.frame); 157 | CGFloat width = CGRectGetWidth(item.frame); 158 | if (item.bottomLineWidth < item.itemWidth) { 159 | x = CGRectGetMinX(item.frame) + (item.itemWidth - item.bottomLineWidth) / 2; 160 | width = item.bottomLineWidth; 161 | } 162 | 163 | CGRect frame = CGRectMake(x, CGRectGetHeight(self.bounds) - self.bottomLineHeight, width, self.bottomLineHeight); 164 | if (animated) { 165 | [UIView animateWithDuration:self.bottomLineAnimatedDuration animations:^{ 166 | self.bottomLineView.frame = frame; 167 | } completion:completion]; 168 | } else { 169 | self.bottomLineView.frame = frame; 170 | if (completion) { 171 | completion(YES); 172 | } 173 | } 174 | } 175 | 176 | - (void)resetScrollViewLocation:(BOOL)animated 177 | { 178 | if (!self.didLoadData) return; 179 | 180 | if (self.scrollView.contentSize.width > self.scrollView.frame.size.width) { 181 | CGRect frame = [self.titleItems objectAtIndex:self.pageView.index].frame; 182 | CGFloat centerX = frame.origin.x + frame.size.width / 2; 183 | CGFloat halfWidth = self.scrollView.frame.size.width / 2; 184 | CGPoint point = CGPointZero; 185 | if (centerX >= halfWidth && centerX <= (self.scrollView.contentSize.width - halfWidth)) { 186 | point = CGPointMake(centerX - halfWidth, 0); 187 | } else if (centerX > (self.scrollView.contentSize.width - halfWidth)) { 188 | point = CGPointMake(self.scrollView.contentSize.width - self.scrollView.frame.size.width, 0); 189 | } else if (centerX < halfWidth) { 190 | point = CGPointMake(0, 0); 191 | } 192 | 193 | if (animated) { 194 | [self.scrollView setContentOffset:point animated:YES]; 195 | } else { 196 | self.scrollView.contentOffset = point; 197 | } 198 | } 199 | } 200 | 201 | - (UIScrollView *)scrollView 202 | { 203 | if (_scrollView == nil) { 204 | _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 205 | _scrollView.backgroundColor = [UIColor clearColor]; 206 | _scrollView.bounces = NO; 207 | _scrollView.showsVerticalScrollIndicator = NO; 208 | _scrollView.showsHorizontalScrollIndicator = NO; 209 | _scrollView.directionalLockEnabled = YES; 210 | _scrollView.delegate = self; 211 | } 212 | return _scrollView; 213 | } 214 | 215 | - (void)setShowBottomLine:(BOOL)showBottomLine 216 | { 217 | if (_showBottomLine != showBottomLine) { 218 | _showBottomLine = showBottomLine; 219 | if (showBottomLine && !self.bottomLineView) { 220 | self.bottomLineView = [[UIView alloc] initWithFrame:CGRectZero]; 221 | self.bottomLineView.backgroundColor = self.bottomLineColor; 222 | [self.scrollView addSubview:self.bottomLineView]; 223 | [self resetBottomLineViewLocation:NO completion:nil]; 224 | } else { 225 | [self.bottomLineView removeFromSuperview]; 226 | self.bottomLineView = nil; 227 | } 228 | } 229 | } 230 | 231 | - (void)setBottomLineColor:(UIColor *)bottomLineColor 232 | { 233 | if (_bottomLineColor != bottomLineColor) { 234 | _bottomLineColor = bottomLineColor; 235 | self.bottomLineView.backgroundColor = bottomLineColor; 236 | } 237 | } 238 | 239 | - (void)setBottomLineHeight:(CGFloat)bottomLineHeight 240 | { 241 | if (_bottomLineHeight != bottomLineHeight) { 242 | _bottomLineHeight = bottomLineHeight; 243 | [self resetBottomLineViewLocation:NO completion:nil]; 244 | } 245 | } 246 | 247 | - (void)setShowBottomBoard:(BOOL)showBottomBoard 248 | { 249 | if (_showBottomBoard != showBottomBoard) { 250 | _showBottomBoard = showBottomBoard; 251 | if (showBottomBoard && !self.bottomBoardView) { 252 | self.bottomBoardView = [[UIView alloc] initWithFrame:CGRectZero]; 253 | self.bottomBoardView.backgroundColor = self.bottomBoardColor; 254 | [self addSubview:self.bottomBoardView]; 255 | [self resetBottomBoardViewLayout]; 256 | } else { 257 | [self.bottomBoardView removeFromSuperview]; 258 | self.bottomBoardView = nil; 259 | } 260 | } 261 | } 262 | 263 | - (void)setBottomBoardColor:(UIColor *)bottomBoardColor 264 | { 265 | if (_bottomBoardColor != bottomBoardColor) { 266 | _bottomBoardColor = bottomBoardColor; 267 | self.bottomBoardView.backgroundColor = bottomBoardColor; 268 | } 269 | } 270 | 271 | - (void)setBottomBoardHeight:(CGFloat)bottomBoardHeight 272 | { 273 | if (_bottomBoardHeight != bottomBoardHeight) { 274 | _bottomBoardHeight = bottomBoardHeight; 275 | [self resetBottomBoardViewLayout]; 276 | } 277 | } 278 | 279 | - (void)setLeftMargin:(CGFloat)leftMargin 280 | { 281 | if (_leftMargin != leftMargin) { 282 | _leftMargin = leftMargin; 283 | [self resetLayout]; 284 | } 285 | } 286 | 287 | - (void)setRightMargin:(CGFloat)rightMargin 288 | { 289 | if (_rightMargin != rightMargin) { 290 | _rightMargin = rightMargin; 291 | [self resetLayout]; 292 | } 293 | } 294 | 295 | @end 296 | -------------------------------------------------------------------------------- /SGKit/Core/SGPageView/SGPageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageView.h 3 | // opera 4 | // 5 | // Created by Single on 16/6/11. 6 | // Copyright © 2016年 HL. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SGPageTitleView.h" 11 | #import "SGPageTitleItem.h" 12 | 13 | @class SGPageView; 14 | 15 | @protocol SGPageItemDelegate 16 | @optional 17 | - (UIScrollView *)scrollViewInPageItem:(UIView *)pageItem; // if not implemented automatically created. 18 | @end 19 | 20 | @protocol SGPageViewDelegate 21 | 22 | - (NSInteger)numberOfPagesInPageView:(SGPageView *)pageView; 23 | - (UIView *)pageView:(SGPageView *)pageView viewAtIndex:(NSInteger)index; 24 | - (void)pageView:(SGPageView *)pageView didScrollToIndex:(NSInteger)index; 25 | 26 | @optional 27 | - (SGPageTitleView *)pageTitleViewInPageView:(SGPageView *)pageView; 28 | - (SGPageTitleItem *)pageView:(SGPageView *)pageView pageTitleView:(SGPageTitleView *)pageTitleView titleItemAtIndex:(NSInteger)index; 29 | 30 | @end 31 | 32 | @interface SGPageView : UIView 33 | 34 | @property (nonatomic, weak) id delegate; 35 | @property (nonatomic, assign, readonly) NSInteger index; 36 | @property (nonatomic, assign) NSInteger defaultIndex; // default is 0 37 | @property (nonatomic, assign, readonly) NSInteger numberOfPage; 38 | @property (nonatomic, strong, readonly) SGPageTitleView * pageTitleView; 39 | 40 | - (void)reloadData; 41 | - (void)scrollToIndex:(NSInteger)index; 42 | - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /SGKit/Core/SGPageView/SGPageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageView.m 3 | // opera 4 | // 5 | // Created by Single on 16/6/11. 6 | // Copyright © 2016年 HL. All rights reserved. 7 | // 8 | 9 | #import "SGPageView.h" 10 | #import "SGPageItem.h" 11 | 12 | @interface SGPageTitleView () 13 | 14 | @property (nonatomic, weak) SGPageView * pageView; 15 | 16 | - (void)reloadData; 17 | - (void)scrollToIndex:(NSInteger)index; 18 | - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated; 19 | 20 | @end 21 | 22 | @interface SGPageView () 23 | 24 | { 25 | dispatch_once_t _loadDataToken; 26 | } 27 | 28 | @property (nonatomic, strong) UIScrollView * scrollView; 29 | @property (nonatomic, assign) NSInteger index; 30 | @property (nonatomic, assign) NSInteger numberOfPage; 31 | @property (nonatomic, strong) NSArray *> * pages; 32 | @property (nonatomic, strong) SGPageTitleView * pageTitleView; 33 | 34 | @end 35 | 36 | @implementation SGPageView 37 | 38 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 39 | { 40 | if (self = [super initWithCoder:aDecoder]) { 41 | [self UILayout]; 42 | } 43 | return self; 44 | } 45 | 46 | - (instancetype)initWithFrame:(CGRect)frame 47 | { 48 | if (self = [super initWithFrame:frame]) { 49 | [self UILayout]; 50 | } 51 | return self; 52 | } 53 | 54 | - (void)UILayout 55 | { 56 | self.backgroundColor = [UIColor whiteColor]; 57 | [self addSubview:self.scrollView]; 58 | } 59 | 60 | - (void)scrollToIndex:(NSInteger)index 61 | { 62 | [self scrollToIndex:index animated:YES]; 63 | } 64 | 65 | - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated 66 | { 67 | self.index = index; 68 | CGFloat x = index * CGRectGetWidth(self.bounds); 69 | if ((x != self.scrollView.contentOffset.x) && (self.scrollView.contentSize.width > x)) { 70 | [self.scrollView setContentOffset:CGPointMake(x, 0) animated:animated]; 71 | } 72 | } 73 | 74 | - (void)reloadData 75 | { 76 | [self prepareData]; 77 | [self resetLayout]; 78 | [self.pageTitleView reloadData]; 79 | } 80 | 81 | - (void)prepareData 82 | { 83 | [self.pages enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 84 | [obj removeFromSuperview]; 85 | }]; 86 | self.pages = nil; 87 | self.pageTitleView = nil; 88 | 89 | self.numberOfPage = [self.delegate numberOfPagesInPageView:self]; 90 | NSMutableArray *> * pagesTemp = [NSMutableArray arrayWithCapacity:self.numberOfPage]; 91 | for (NSInteger i = 0; i < self.numberOfPage; i++) { 92 | UIView * view = [self.delegate pageView:self viewAtIndex:i]; 93 | [pagesTemp addObject:view]; 94 | [self.scrollView addSubview:view]; 95 | } 96 | self.pages = pagesTemp; 97 | 98 | NSInteger index = self.defaultIndex; 99 | if (self.defaultIndex >= self.numberOfPage) { 100 | index = self.numberOfPage - 1 >= 0 ? self.numberOfPage - 1 : 0; 101 | } 102 | _index = index; 103 | [self didScrollToIndexCallBack]; 104 | 105 | if ([self.delegate respondsToSelector:@selector(pageTitleViewInPageView:)]) { 106 | self.pageTitleView = [self.delegate pageTitleViewInPageView:self]; 107 | self.pageTitleView.pageView = self; 108 | } 109 | } 110 | 111 | - (NSArray *)fetchScrollViews 112 | { 113 | NSMutableArray * scrollViewsTemp = [NSMutableArray arrayWithCapacity:self.numberOfPage]; 114 | NSMutableArray *> * pagesTemp = [NSMutableArray arrayWithCapacity:self.numberOfPage]; 115 | [self.pages enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 116 | 117 | UIScrollView * scrollView; 118 | if ([obj respondsToSelector:@selector(scrollViewInPageItem:)]) { 119 | UIScrollView * view = [obj scrollViewInPageItem:obj]; 120 | if ([view isKindOfClass:[UIScrollView class]]) scrollView = view; 121 | [pagesTemp addObject:obj]; 122 | } 123 | if (!scrollView) { 124 | SGPageItem * item = [[SGPageItem alloc] initWithFrame:obj.frame]; 125 | [self.scrollView addSubview:item]; 126 | item.contentView = obj; 127 | scrollView = [item scrollViewInPageItem:item]; 128 | [pagesTemp addObject:item]; 129 | } 130 | [scrollViewsTemp addObject:scrollView]; 131 | }]; 132 | self.pages = pagesTemp; 133 | return scrollViewsTemp; 134 | } 135 | 136 | - (void)resetLayout 137 | { 138 | self.scrollView.frame = self.bounds; 139 | self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds) * self.numberOfPage, CGRectGetHeight(self.bounds)); 140 | 141 | [self.pages enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 142 | obj.frame = CGRectMake(idx * CGRectGetWidth(self.bounds), 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)); 143 | }]; 144 | 145 | self.scrollView.contentOffset = CGPointMake(self.index * CGRectGetWidth(self.bounds), 0); 146 | } 147 | 148 | - (void)layoutSubviews 149 | { 150 | [super layoutSubviews]; 151 | [self resetLayout]; 152 | } 153 | 154 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView 155 | { 156 | [self didEndScroll]; 157 | } 158 | 159 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 160 | { 161 | [self didEndScroll]; 162 | } 163 | 164 | - (void)didEndScroll 165 | { 166 | self.index = self.scrollView.contentOffset.x / self.scrollView.frame.size.width; 167 | } 168 | 169 | - (void)setIndex:(NSInteger)index 170 | { 171 | if (_index != index) { 172 | _index = index; 173 | [self didScrollToIndexCallBack]; 174 | } 175 | } 176 | 177 | - (void)didScrollToIndexCallBack 178 | { 179 | if (self.numberOfPage > self.index || [self.delegate respondsToSelector:@selector(pageView:didScrollToIndex:)]) { 180 | [self.delegate pageView:self didScrollToIndex:self.index]; 181 | [self.pageTitleView scrollToIndex:self.index]; 182 | } 183 | } 184 | 185 | - (UIScrollView *)scrollView 186 | { 187 | if (_scrollView == nil) { 188 | _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 189 | _scrollView.backgroundColor = [UIColor clearColor]; 190 | _scrollView.bounces = NO; 191 | _scrollView.pagingEnabled = YES; 192 | _scrollView.showsVerticalScrollIndicator = NO; 193 | _scrollView.showsHorizontalScrollIndicator = NO; 194 | _scrollView.directionalLockEnabled = YES; 195 | _scrollView.delegate = self; 196 | } 197 | return _scrollView; 198 | } 199 | 200 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 201 | { 202 | if (point.x < 20 && self.scrollView.contentOffset.x == 0) { 203 | return self; 204 | } 205 | return [super hitTest:point withEvent:event]; 206 | } 207 | 208 | - (void)didMoveToSuperview 209 | { 210 | [super didMoveToSuperview]; 211 | dispatch_once(&_loadDataToken, ^{ 212 | [self reloadData]; 213 | }); 214 | } 215 | 216 | @end 217 | -------------------------------------------------------------------------------- /SGKit/Core/SGSwipeView/SGSwipeView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGSwipeView.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/18. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SGPageView.h" 11 | 12 | @class SGSwipeView; 13 | 14 | @protocol SGSwipeViewDelegate 15 | 16 | - (SGPageView *)pageViewInSwipeView:(SGSwipeView *)swipeView; 17 | - (UIView *)headerViewInSwipeView:(SGSwipeView *)swipeView; 18 | - (CGFloat)headerViewHeightInSwipeView:(SGSwipeView *)swipeView; 19 | 20 | @optional 21 | - (CGFloat)pageTitleViewHeightInSwipeView:(SGSwipeView *)swipeView; 22 | - (void)swipeView:(SGSwipeView *)swipeView didChangeOffsetScale:(CGFloat)scale; 23 | 24 | @end 25 | 26 | @interface SGSwipeView : UIView 27 | 28 | @property (nonatomic, weak) id delegate; 29 | @property (nonatomic, strong, readonly) SGPageView * pageView; 30 | @property (nonatomic, strong, readonly) UIView * headerView; 31 | @property (nonatomic, assign, readonly) CGFloat headerViewHeight; 32 | @property (nonatomic, assign, readonly) CGFloat pageTitleViewHeight; 33 | @property (nonatomic, assign) CGFloat topMargin; 34 | 35 | - (void)reloadData; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /SGKit/Core/SGSwipeView/SGSwipeView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGSwipeView.m 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/18. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGSwipeView.h" 10 | 11 | @interface SGPageView () 12 | - (NSArray *)fetchScrollViews; 13 | @end 14 | 15 | @interface SGSwipeView () 16 | 17 | { 18 | dispatch_once_t _loadDataToken; 19 | } 20 | 21 | @property (nonatomic, strong) SGPageView * pageView; 22 | @property (nonatomic, strong) UIView * headerView; 23 | @property (nonatomic, assign) CGFloat headerViewHeight; 24 | @property (nonatomic, assign) CGFloat pageTitleViewHeight; 25 | 26 | @property (nonatomic, strong) NSArray * scrollViews; 27 | @property (nonatomic, strong) UIScrollView * currentScrollView; 28 | @property (nonatomic, assign) CGFloat contentViewTopDistant; 29 | @property (nonatomic, assign, readonly) CGFloat scrollViewContentInsetHeight; 30 | 31 | 32 | @end 33 | 34 | @implementation SGSwipeView 35 | 36 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 37 | { 38 | if (self = [super initWithCoder:aDecoder]) { 39 | [self UILayout]; 40 | } 41 | return self; 42 | } 43 | 44 | - (instancetype)initWithFrame:(CGRect)frame 45 | { 46 | if (self = [super initWithFrame:frame]) { 47 | [self UILayout]; 48 | } 49 | return self; 50 | } 51 | 52 | - (void)UILayout 53 | { 54 | self.backgroundColor = [UIColor whiteColor]; 55 | } 56 | 57 | - (void)reloadData 58 | { 59 | [self.pageView removeFromSuperview]; 60 | self.pageView = nil; 61 | [self.headerView removeFromSuperview]; 62 | self.headerView = nil; 63 | [self.pageView.pageTitleView removeFromSuperview]; 64 | [self clearScrollViews]; 65 | 66 | self.contentViewTopDistant = 0; 67 | self.pageView = [self.delegate pageViewInSwipeView:self]; 68 | [self addSubview:self.pageView]; 69 | self.headerView = [self.delegate headerViewInSwipeView:self]; 70 | [self addSubview:self.headerView]; 71 | self.headerViewHeight = [self.delegate headerViewHeightInSwipeView:self]; 72 | [self.pageView reloadData]; 73 | if (self.pageView.pageTitleView) { 74 | [self addSubview:self.pageView.pageTitleView]; 75 | self.pageTitleViewHeight = [self.delegate pageTitleViewHeightInSwipeView:self]; 76 | } 77 | 78 | NSMutableArray * scrollViewsTemp = [NSMutableArray array]; 79 | [self.pageView.fetchScrollViews enumerateObjectsUsingBlock:^(UIScrollView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 80 | [scrollViewsTemp addObject:obj]; 81 | obj.contentInset = UIEdgeInsetsMake(self.scrollViewContentInsetHeight, 0, 0, 0); 82 | [obj setContentOffset:CGPointMake(0, -self.scrollViewContentInsetHeight) animated:NO]; 83 | [obj.panGestureRecognizer addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL]; 84 | [obj addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL]; 85 | }]; 86 | self.scrollViews = scrollViewsTemp; 87 | 88 | [self resetLayout]; 89 | } 90 | 91 | - (void)setTopMargin:(CGFloat)topMargin 92 | { 93 | if (_topMargin != topMargin) { 94 | _topMargin = topMargin; 95 | if (_topMargin < 0) { 96 | _topMargin = 0; 97 | } 98 | } 99 | } 100 | 101 | - (void)clearScrollViews 102 | { 103 | [self.scrollViews enumerateObjectsUsingBlock:^(UIScrollView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 104 | [obj.panGestureRecognizer removeObserver:self forKeyPath:@"state"]; 105 | [obj removeObserver:self forKeyPath:@"contentOffset"]; 106 | }]; 107 | self.scrollViews = nil; 108 | } 109 | 110 | - (void)layoutSubviews 111 | { 112 | [super layoutSubviews]; 113 | [self resetLayout]; 114 | } 115 | 116 | - (void)resetLayout 117 | { 118 | self.contentViewTopDistant = 0; 119 | self.pageView.frame = self.bounds; 120 | [self resetHeaderAndTitleViewLayout]; 121 | } 122 | 123 | - (CGFloat)scrollViewContentInsetHeight 124 | { 125 | return self.headerViewHeight + self.pageTitleViewHeight; 126 | } 127 | 128 | - (void)setContentViewTopDistant:(CGFloat)contentViewTopDistant 129 | { 130 | if (_contentViewTopDistant != contentViewTopDistant) { 131 | 132 | CGFloat preContentViewTopDistant = _contentViewTopDistant; 133 | _contentViewTopDistant = contentViewTopDistant; 134 | 135 | [self.scrollViews enumerateObjectsUsingBlock:^(UIScrollView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 136 | if (obj != self.currentScrollView) { 137 | [obj setContentOffset:CGPointMake(0, obj.contentOffset.y-(_contentViewTopDistant-preContentViewTopDistant)) animated:NO]; 138 | } 139 | }]; 140 | 141 | [self resetHeaderAndTitleViewLayout]; 142 | 143 | CGFloat scale = (-_contentViewTopDistant / (self.headerViewHeight-self.topMargin)); 144 | if ([self.delegate respondsToSelector:@selector(swipeView:didChangeOffsetScale:)]) { 145 | [self.delegate swipeView:self didChangeOffsetScale:scale]; 146 | } 147 | } 148 | } 149 | 150 | - (void)resetHeaderAndTitleViewLayout 151 | { 152 | self.headerView.frame = CGRectMake(0, self.contentViewTopDistant, CGRectGetWidth(self.frame), self.headerViewHeight); 153 | self.pageView.pageTitleView.frame = CGRectMake(0, CGRectGetMaxY(self.headerView.frame), CGRectGetWidth(self.frame), self.pageTitleViewHeight); 154 | } 155 | 156 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 157 | { 158 | if ([keyPath isEqualToString:@"state"]) 159 | { 160 | self.currentScrollView = (UIScrollView *)[(UIGestureRecognizer *)object view]; 161 | } 162 | else if ([keyPath isEqualToString:@"contentOffset"]) 163 | { 164 | if (object == self.currentScrollView) 165 | { 166 | CGFloat contentHeight = self.currentScrollView.contentSize.height - CGRectGetHeight(self.currentScrollView.frame); 167 | if (contentHeight < CGRectGetHeight(self.currentScrollView.frame)) { 168 | contentHeight = CGRectGetHeight(self.currentScrollView.frame); 169 | } 170 | CGFloat oldOffsetY = [change[NSKeyValueChangeOldKey] CGPointValue].y; 171 | CGFloat newOffsetY = [change[NSKeyValueChangeNewKey] CGPointValue].y; 172 | 173 | if (oldOffsetY == newOffsetY) return; 174 | if (oldOffsetY > contentHeight && newOffsetY > contentHeight) return; 175 | if (oldOffsetY < -self.scrollViewContentInsetHeight && newOffsetY < -self.scrollViewContentInsetHeight) return; 176 | 177 | if (oldOffsetY > contentHeight) oldOffsetY = contentHeight; 178 | if (newOffsetY > contentHeight) newOffsetY = contentHeight; 179 | 180 | if (oldOffsetY < -self.scrollViewContentInsetHeight) oldOffsetY = -self.scrollViewContentInsetHeight; 181 | if (newOffsetY < -self.scrollViewContentInsetHeight) newOffsetY = -self.scrollViewContentInsetHeight; 182 | 183 | CGFloat deltaY = newOffsetY - oldOffsetY; 184 | if (deltaY == 0) return; 185 | 186 | if (deltaY > 0 || (deltaY < 0 && newOffsetY < -(self.topMargin + self.pageTitleViewHeight))) 187 | { 188 | CGFloat topOffset = self.contentViewTopDistant - deltaY; 189 | 190 | if (topOffset < -(self.headerViewHeight - self.topMargin)) { 191 | topOffset = -(self.headerViewHeight - self.topMargin); 192 | } 193 | if (topOffset > 0) { 194 | topOffset = 0; 195 | } 196 | 197 | self.contentViewTopDistant = topOffset; 198 | } 199 | } 200 | } 201 | } 202 | 203 | - (void)didMoveToSuperview 204 | { 205 | [super didMoveToSuperview]; 206 | dispatch_once(&_loadDataToken, ^{ 207 | [self reloadData]; 208 | }); 209 | } 210 | 211 | - (void)dealloc 212 | { 213 | [self clearScrollViews]; 214 | } 215 | 216 | @end 217 | -------------------------------------------------------------------------------- /SGKit/Core/SGTransform/SGTransformView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGTransformView.h 3 | // SGKit 4 | // 5 | // Created by Single on 19/12/2016. 6 | // Copyright © 2016 single. All rights reserved. 7 | // 8 | 9 | #import 10 | @class SGTransformView; 11 | 12 | extern CGFloat const TranslateControlViewWidth; 13 | extern CGFloat const TranslateControlViewHeight; 14 | 15 | @protocol SGTransformViewDelegate 16 | 17 | @optional 18 | - (void)transformViewStartTranslate:(SGTransformView *)transformView; 19 | - (void)transformViewStopTranslate:(SGTransformView *)transformView; 20 | - (void)transformViewTranslating:(SGTransformView *)transformView; 21 | - (CGRect)transformView:(SGTransformView *)transformView needChangeFrameByTranslateAction:(CGRect)frame currentTransform:(CGAffineTransform)transform; 22 | 23 | - (void)transformViewStartMove:(SGTransformView *)transformView; 24 | - (void)transformViewStopMove:(SGTransformView *)transformView; 25 | - (void)transformViewMoving:(SGTransformView *)transformView; 26 | - (CGPoint)transformView:(SGTransformView *)transformView needChangeCenterByMoveAction:(CGPoint)center; 27 | 28 | @end 29 | 30 | @interface SGTransformView : UIView 31 | 32 | @property (nonatomic, weak) id delegate; 33 | @property (nonatomic, strong, readonly) UIView * contentView; 34 | @property (nonatomic, strong, readonly) UIView * translateControlView; 35 | @property (nonatomic, assign) BOOL translateControlEnable; // default is YES; 36 | @property (nonatomic, assign) CGSize translateControlViewSize; // defalut wdith is TranslateViewWidth, default height is TranslateViewHeight. 37 | 38 | @property (nonatomic, assign) CGFloat aspect; // if frame.size is't CGRectZero whern init, defalut value is width/height, else default value is equal to translateView's width/height. 39 | @property (nonatomic, assign) CGSize minSize; // default is equal to translateView's size. 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /SGKit/Core/SGTransform/SGTransformView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGTransformView.m 3 | // SGKit 4 | // 5 | // Created by Single on 19/12/2016. 6 | // Copyright © 2016 single. All rights reserved. 7 | // 8 | 9 | #import "SGTransformView.h" 10 | #import "UIColor+SGExtension.h" 11 | 12 | CGFloat const TranslateControlViewWidth = 40; 13 | CGFloat const TranslateControlViewHeight = TranslateControlViewWidth; 14 | 15 | @interface SGTransformView () 16 | 17 | @property (nonatomic, strong) UIView * contentView; 18 | @property (nonatomic, strong) UIView * translateControlView; 19 | 20 | @property (nonatomic, assign) CGPoint translateStartPoint; 21 | @property (nonatomic, assign) CGPoint translateStartCenter; 22 | 23 | @property (nonatomic, assign) CGPoint moveStartPoint; 24 | @property (nonatomic, assign) CGAffineTransform moveStartTransform; 25 | 26 | @end 27 | 28 | @implementation SGTransformView 29 | 30 | - (instancetype)initWithFrame:(CGRect)frame 31 | { 32 | if (self = [super initWithFrame:frame]) 33 | { 34 | [self setup]; 35 | } 36 | return self; 37 | } 38 | 39 | - (void)setup 40 | { 41 | if (CGRectGetWidth(self.frame) > 0 && CGRectGetHeight(self.frame) > 0) { 42 | self.aspect = CGRectGetWidth(self.frame) / CGRectGetHeight(self.frame); 43 | } else { 44 | self.aspect = TranslateControlViewWidth / TranslateControlViewHeight; 45 | } 46 | self.translateControlViewSize = CGSizeMake(TranslateControlViewWidth, TranslateControlViewHeight); 47 | self.minSize = self.translateControlViewSize; 48 | self.translateControlEnable = YES; 49 | 50 | [self superUILayout]; 51 | [self setupGestureRecongizer]; 52 | } 53 | 54 | - (void)superUILayout 55 | { 56 | self.backgroundColor = [UIColor sg_colorWithRed:194 green:225 blue:200]; 57 | self.contentView = [[UIView alloc] initWithFrame:self.bounds]; 58 | [self addSubview:self.contentView]; 59 | 60 | self.translateControlView = [[UIView alloc] initWithFrame:CGRectMake( 61 | CGRectGetWidth(self.frame) - self.translateControlViewSize.width, 62 | CGRectGetHeight(self.frame) - self.translateControlViewSize.height, 63 | self.translateControlViewSize.width, 64 | self.translateControlViewSize.height 65 | )]; 66 | self.translateControlView.backgroundColor = [UIColor sg_colorWithRed:242 green:167 blue:151]; 67 | [self addSubview:self.translateControlView]; 68 | } 69 | 70 | - (void)setupGestureRecongizer 71 | { 72 | UIPanGestureRecognizer * moveGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveGestureRecognizerAction:)]; 73 | [self addGestureRecognizer:moveGestureRecognizer]; 74 | 75 | UIPanGestureRecognizer * translateGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(translateGestureRecognizerAction:)]; 76 | [self.translateControlView addGestureRecognizer:translateGestureRecognizer]; 77 | } 78 | 79 | - (void)settranslateControlEnable:(BOOL)translateControlEnable 80 | { 81 | if (_translateControlEnable != translateControlEnable) { 82 | _translateControlEnable = translateControlEnable; 83 | self.translateControlView.hidden = !_translateControlEnable; 84 | } 85 | } 86 | 87 | - (void)translateGestureRecognizerAction:(UIPanGestureRecognizer *)pan 88 | { 89 | switch (pan.state) 90 | { 91 | case UIGestureRecognizerStateBegan: 92 | { 93 | self.translateStartCenter = self.center; 94 | self.translateStartPoint = [pan locationInView:self.translateControlView]; 95 | [self startTranslateAction]; 96 | } 97 | break; 98 | case UIGestureRecognizerStateChanged: 99 | { 100 | CGPoint location = [pan locationInView:self.superview]; 101 | 102 | CGPoint point = CGPointMake( 103 | self.translateControlViewSize.width - self.translateStartPoint.x + location.x, 104 | self.translateControlViewSize.height - self.translateStartPoint.y + location.y 105 | ); 106 | 107 | CGPoint center = self.translateStartCenter; 108 | 109 | CGFloat a = point.x - center.x; 110 | CGFloat b = point.y - center.y; 111 | CGFloat c = sqrtf(a*a + b*b); 112 | 113 | CGFloat height = sqrtf(c*c / (1+self.aspect*self.aspect)); 114 | CGFloat width = height * self.aspect; 115 | 116 | if (height > self.minSize.height/2 && width > self.minSize.width/2) 117 | { 118 | CGRect frame = CGRectMake(center.x - width, center.y - height, width * 2, height * 2); 119 | 120 | if ([self.delegate respondsToSelector:@selector(transformView:needChangeFrameByTranslateAction:currentTransform:)]) { 121 | frame = [self.delegate transformView:self needChangeFrameByTranslateAction:frame currentTransform:self.transform]; 122 | } 123 | 124 | self.transform = CGAffineTransformMakeRotation(0); 125 | self.frame = frame; 126 | } 127 | 128 | float ang = atan2(point.y - center.y, point.x - center.x); 129 | self.transform = CGAffineTransformMakeRotation(ang - self.atan2); 130 | 131 | [self translatingAction]; 132 | } 133 | break; 134 | case UIGestureRecognizerStateEnded: 135 | case UIGestureRecognizerStateCancelled: 136 | { 137 | [self stopTranslateAction]; 138 | } 139 | break; 140 | default: 141 | break; 142 | } 143 | } 144 | 145 | - (void)startTranslateAction 146 | { 147 | if ([self.delegate respondsToSelector:@selector(transformViewStartTranslate:)]) { 148 | [self.delegate transformViewStartTranslate:self]; 149 | } 150 | } 151 | 152 | - (void)stopTranslateAction 153 | { 154 | if ([self.delegate respondsToSelector:@selector(transformViewStopTranslate:)]) { 155 | [self.delegate transformViewStopTranslate:self]; 156 | } 157 | } 158 | 159 | - (void)translatingAction 160 | { 161 | if ([self.delegate respondsToSelector:@selector(transformViewTranslating:)]) { 162 | [self.delegate transformViewTranslating:self]; 163 | } 164 | } 165 | 166 | - (void)moveGestureRecognizerAction:(UIPanGestureRecognizer *)pan 167 | { 168 | switch (pan.state) 169 | { 170 | case UIGestureRecognizerStateBegan: 171 | { 172 | self.moveStartPoint = [pan locationInView:self.superview]; 173 | self.moveStartTransform = self.transform; 174 | [self startMoveAction]; 175 | } 176 | break; 177 | case UIGestureRecognizerStateChanged: 178 | { 179 | CGPoint point = [pan locationInView:self.superview]; 180 | 181 | CGPoint newCenter = CGPointMake(self.center.x + point.x - self.moveStartPoint.x, self.center.y + point.y - self.moveStartPoint.y); 182 | 183 | if ([self.delegate respondsToSelector:@selector(transformView:needChangeCenterByMoveAction:)]) 184 | { 185 | newCenter = [self.delegate transformView:self needChangeCenterByMoveAction:newCenter]; 186 | } 187 | 188 | self.transform = CGAffineTransformMakeRotation(0); 189 | self.center = newCenter; 190 | self.transform = self.moveStartTransform; 191 | 192 | self.moveStartPoint = point; 193 | 194 | [self movingAction]; 195 | } 196 | break; 197 | case UIGestureRecognizerStateEnded: 198 | case UIGestureRecognizerStateCancelled: 199 | { 200 | [self stopMoveAction]; 201 | } 202 | break; 203 | default: 204 | break; 205 | } 206 | } 207 | 208 | - (void)startMoveAction 209 | { 210 | if ([self.delegate respondsToSelector:@selector(transformViewStartMove:)]) { 211 | [self.delegate transformViewStartMove:self]; 212 | } 213 | } 214 | 215 | - (void)stopMoveAction 216 | { 217 | if ([self.delegate respondsToSelector:@selector(transformViewStopMove:)]) { 218 | [self.delegate transformViewStopMove:self]; 219 | } 220 | } 221 | 222 | - (void)movingAction 223 | { 224 | if ([self.delegate respondsToSelector:@selector(transformViewMoving:)]) { 225 | [self.delegate transformViewMoving:self]; 226 | } 227 | } 228 | 229 | - (CGFloat)atan2 230 | { 231 | return atan2f(CGRectGetHeight(self.frame), CGRectGetWidth(self.frame)); 232 | } 233 | 234 | - (void)layoutSubviews 235 | { 236 | [super layoutSubviews]; 237 | 238 | self.moveStartTransform = self.transform; 239 | self.transform = CGAffineTransformMakeRotation(0); 240 | 241 | CGFloat width = CGRectGetWidth(self.frame); 242 | CGFloat height = CGRectGetHeight(self.frame); 243 | 244 | self.contentView.frame = self.bounds; 245 | self.translateControlView.frame = CGRectMake( 246 | width - self.translateControlViewSize.width, 247 | height - self.translateControlViewSize.height, 248 | self.translateControlViewSize.width, 249 | self.translateControlViewSize.height 250 | ); 251 | 252 | self.aspect = width / height; 253 | 254 | self.transform = self.moveStartTransform; 255 | } 256 | 257 | - (void)setFrame:(CGRect)frame 258 | { 259 | CGAffineTransform transform = self.transform; 260 | self.transform = CGAffineTransformMakeRotation(0); 261 | [super setFrame:frame]; 262 | self.transform = transform; 263 | } 264 | 265 | - (void)setTranslateControlViewSize:(CGSize)translateControlViewSize 266 | { 267 | if (!CGSizeEqualToSize(_translateControlViewSize, translateControlViewSize)) { 268 | _translateControlViewSize = translateControlViewSize; 269 | 270 | CGAffineTransform transform = self.transform; 271 | self.transform = CGAffineTransformMakeRotation(0); 272 | self.translateControlView.frame = CGRectMake( 273 | CGRectGetWidth(self.frame) - _translateControlViewSize.width, 274 | CGRectGetHeight(self.frame) - _translateControlViewSize.height, 275 | _translateControlViewSize.width, 276 | _translateControlViewSize.height 277 | ); 278 | self.transform = transform; 279 | } 280 | } 281 | 282 | @end 283 | -------------------------------------------------------------------------------- /SGKit/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | SGKit 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SGKit/SGKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGKit.h 3 | // SGKit 4 | // 5 | // Created by Single on 2016/11/5. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | FOUNDATION_EXPORT double SGKitVersionNumber; // version number 12 | FOUNDATION_EXPORT const unsigned char SGKitVersionString[]; // version string 13 | 14 | // class 15 | #import 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import 24 | 25 | // categroy 26 | #import 27 | #import 28 | #import 29 | #import 30 | -------------------------------------------------------------------------------- /demo/demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9C7A8E311EAB486C008FB9B5 /* SGKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C7A8E301EAB486C008FB9B5 /* SGKit.framework */; }; 11 | 9C9D21541EAB2529006CC234 /* Example.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C9D213E1EAB2529006CC234 /* Example.m */; }; 12 | 9C9D21551EAB2529006CC234 /* SGCollectionViewFlowLayoutExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C9D21411EAB2529006CC234 /* SGCollectionViewFlowLayoutExample.m */; }; 13 | 9C9D21561EAB2529006CC234 /* SGGuideViewExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C9D21441EAB2529006CC234 /* SGGuideViewExample.m */; }; 14 | 9C9D21571EAB2529006CC234 /* SGImagePlayerExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C9D21471EAB2529006CC234 /* SGImagePlayerExample.m */; }; 15 | 9C9D21591EAB2529006CC234 /* SGPageViewExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C9D214D1EAB2529006CC234 /* SGPageViewExample.m */; }; 16 | 9C9D215A1EAB2529006CC234 /* SGSwipeViewExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C9D21501EAB2529006CC234 /* SGSwipeViewExample.m */; }; 17 | 9C9D215B1EAB2529006CC234 /* SGTransformViewExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C9D21531EAB2529006CC234 /* SGTransformViewExample.m */; }; 18 | 9C9D21611EAB2667006CC234 /* SGTableViewExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C9D21601EAB2667006CC234 /* SGTableViewExample.m */; }; 19 | 9CE3B8121EAB2362009B63D5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CE3B8111EAB2362009B63D5 /* main.m */; }; 20 | 9CE3B8151EAB2362009B63D5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CE3B8141EAB2362009B63D5 /* AppDelegate.m */; }; 21 | 9CE3B81D1EAB2362009B63D5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9CE3B81C1EAB2362009B63D5 /* Assets.xcassets */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXFileReference section */ 25 | 9C7A8E301EAB486C008FB9B5 /* SGKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SGKit.framework; path = "../build/Debug-iphoneos/SGKit.framework"; sourceTree = ""; }; 26 | 9C9D213D1EAB2529006CC234 /* Example.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Example.h; sourceTree = ""; }; 27 | 9C9D213E1EAB2529006CC234 /* Example.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Example.m; sourceTree = ""; }; 28 | 9C9D21401EAB2529006CC234 /* SGCollectionViewFlowLayoutExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGCollectionViewFlowLayoutExample.h; sourceTree = ""; }; 29 | 9C9D21411EAB2529006CC234 /* SGCollectionViewFlowLayoutExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGCollectionViewFlowLayoutExample.m; sourceTree = ""; }; 30 | 9C9D21431EAB2529006CC234 /* SGGuideViewExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGGuideViewExample.h; sourceTree = ""; }; 31 | 9C9D21441EAB2529006CC234 /* SGGuideViewExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGGuideViewExample.m; sourceTree = ""; }; 32 | 9C9D21461EAB2529006CC234 /* SGImagePlayerExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGImagePlayerExample.h; sourceTree = ""; }; 33 | 9C9D21471EAB2529006CC234 /* SGImagePlayerExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGImagePlayerExample.m; sourceTree = ""; }; 34 | 9C9D214C1EAB2529006CC234 /* SGPageViewExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGPageViewExample.h; sourceTree = ""; }; 35 | 9C9D214D1EAB2529006CC234 /* SGPageViewExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGPageViewExample.m; sourceTree = ""; }; 36 | 9C9D214F1EAB2529006CC234 /* SGSwipeViewExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGSwipeViewExample.h; sourceTree = ""; }; 37 | 9C9D21501EAB2529006CC234 /* SGSwipeViewExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGSwipeViewExample.m; sourceTree = ""; }; 38 | 9C9D21521EAB2529006CC234 /* SGTransformViewExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGTransformViewExample.h; sourceTree = ""; }; 39 | 9C9D21531EAB2529006CC234 /* SGTransformViewExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGTransformViewExample.m; sourceTree = ""; }; 40 | 9C9D215D1EAB2599006CC234 /* SGKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SGKit.framework; path = "../../Documents/project/single-framework/SGKit/build/Debug-iphoneos/SGKit.framework"; sourceTree = ""; }; 41 | 9C9D215F1EAB2667006CC234 /* SGTableViewExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGTableViewExample.h; sourceTree = ""; }; 42 | 9C9D21601EAB2667006CC234 /* SGTableViewExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGTableViewExample.m; sourceTree = ""; }; 43 | 9CE3B80D1EAB2362009B63D5 /* demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 9CE3B8111EAB2362009B63D5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | 9CE3B8131EAB2362009B63D5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 46 | 9CE3B8141EAB2362009B63D5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 47 | 9CE3B81C1EAB2362009B63D5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 48 | 9CE3B8211EAB2362009B63D5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | /* End PBXFileReference section */ 50 | 51 | /* Begin PBXFrameworksBuildPhase section */ 52 | 9CE3B80A1EAB2362009B63D5 /* Frameworks */ = { 53 | isa = PBXFrameworksBuildPhase; 54 | buildActionMask = 2147483647; 55 | files = ( 56 | 9C7A8E311EAB486C008FB9B5 /* SGKit.framework in Frameworks */, 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXFrameworksBuildPhase section */ 61 | 62 | /* Begin PBXGroup section */ 63 | 9C9D213C1EAB2529006CC234 /* Core */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 9C9D213D1EAB2529006CC234 /* Example.h */, 67 | 9C9D213E1EAB2529006CC234 /* Example.m */, 68 | 9C9D213F1EAB2529006CC234 /* SGCollectionViewFlowLayoutExample */, 69 | 9C9D21421EAB2529006CC234 /* SGGuideViewExample */, 70 | 9C9D21451EAB2529006CC234 /* SGImagePlayerExample */, 71 | 9C9D214B1EAB2529006CC234 /* SGPageViewExample */, 72 | 9C9D214E1EAB2529006CC234 /* SGSwipeViewExample */, 73 | 9C9D21511EAB2529006CC234 /* SGTransformExample */, 74 | ); 75 | path = Core; 76 | sourceTree = ""; 77 | }; 78 | 9C9D213F1EAB2529006CC234 /* SGCollectionViewFlowLayoutExample */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 9C9D21401EAB2529006CC234 /* SGCollectionViewFlowLayoutExample.h */, 82 | 9C9D21411EAB2529006CC234 /* SGCollectionViewFlowLayoutExample.m */, 83 | ); 84 | path = SGCollectionViewFlowLayoutExample; 85 | sourceTree = ""; 86 | }; 87 | 9C9D21421EAB2529006CC234 /* SGGuideViewExample */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 9C9D21431EAB2529006CC234 /* SGGuideViewExample.h */, 91 | 9C9D21441EAB2529006CC234 /* SGGuideViewExample.m */, 92 | ); 93 | path = SGGuideViewExample; 94 | sourceTree = ""; 95 | }; 96 | 9C9D21451EAB2529006CC234 /* SGImagePlayerExample */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 9C9D21461EAB2529006CC234 /* SGImagePlayerExample.h */, 100 | 9C9D21471EAB2529006CC234 /* SGImagePlayerExample.m */, 101 | ); 102 | path = SGImagePlayerExample; 103 | sourceTree = ""; 104 | }; 105 | 9C9D214B1EAB2529006CC234 /* SGPageViewExample */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 9C9D215F1EAB2667006CC234 /* SGTableViewExample.h */, 109 | 9C9D21601EAB2667006CC234 /* SGTableViewExample.m */, 110 | 9C9D214C1EAB2529006CC234 /* SGPageViewExample.h */, 111 | 9C9D214D1EAB2529006CC234 /* SGPageViewExample.m */, 112 | ); 113 | path = SGPageViewExample; 114 | sourceTree = ""; 115 | }; 116 | 9C9D214E1EAB2529006CC234 /* SGSwipeViewExample */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 9C9D214F1EAB2529006CC234 /* SGSwipeViewExample.h */, 120 | 9C9D21501EAB2529006CC234 /* SGSwipeViewExample.m */, 121 | ); 122 | path = SGSwipeViewExample; 123 | sourceTree = ""; 124 | }; 125 | 9C9D21511EAB2529006CC234 /* SGTransformExample */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 9C9D21521EAB2529006CC234 /* SGTransformViewExample.h */, 129 | 9C9D21531EAB2529006CC234 /* SGTransformViewExample.m */, 130 | ); 131 | path = SGTransformExample; 132 | sourceTree = ""; 133 | }; 134 | 9C9D215C1EAB2599006CC234 /* Frameworks */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 9C7A8E301EAB486C008FB9B5 /* SGKit.framework */, 138 | 9C9D215D1EAB2599006CC234 /* SGKit.framework */, 139 | ); 140 | name = Frameworks; 141 | sourceTree = ""; 142 | }; 143 | 9CE3B8041EAB2362009B63D5 = { 144 | isa = PBXGroup; 145 | children = ( 146 | 9CE3B80F1EAB2362009B63D5 /* demo */, 147 | 9CE3B80E1EAB2362009B63D5 /* Products */, 148 | 9C9D215C1EAB2599006CC234 /* Frameworks */, 149 | ); 150 | sourceTree = ""; 151 | }; 152 | 9CE3B80E1EAB2362009B63D5 /* Products */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 9CE3B80D1EAB2362009B63D5 /* demo.app */, 156 | ); 157 | name = Products; 158 | sourceTree = ""; 159 | }; 160 | 9CE3B80F1EAB2362009B63D5 /* demo */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 9C9D213C1EAB2529006CC234 /* Core */, 164 | 9CE3B8131EAB2362009B63D5 /* AppDelegate.h */, 165 | 9CE3B8141EAB2362009B63D5 /* AppDelegate.m */, 166 | 9CE3B8101EAB2362009B63D5 /* Supporting Files */, 167 | ); 168 | path = demo; 169 | sourceTree = ""; 170 | }; 171 | 9CE3B8101EAB2362009B63D5 /* Supporting Files */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | 9CE3B81C1EAB2362009B63D5 /* Assets.xcassets */, 175 | 9CE3B8211EAB2362009B63D5 /* Info.plist */, 176 | 9CE3B8111EAB2362009B63D5 /* main.m */, 177 | ); 178 | name = "Supporting Files"; 179 | sourceTree = ""; 180 | }; 181 | /* End PBXGroup section */ 182 | 183 | /* Begin PBXNativeTarget section */ 184 | 9CE3B80C1EAB2362009B63D5 /* demo */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = 9CE3B8241EAB2362009B63D5 /* Build configuration list for PBXNativeTarget "demo" */; 187 | buildPhases = ( 188 | 9CE3B8091EAB2362009B63D5 /* Sources */, 189 | 9CE3B80A1EAB2362009B63D5 /* Frameworks */, 190 | 9CE3B80B1EAB2362009B63D5 /* Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | ); 196 | name = demo; 197 | productName = demo; 198 | productReference = 9CE3B80D1EAB2362009B63D5 /* demo.app */; 199 | productType = "com.apple.product-type.application"; 200 | }; 201 | /* End PBXNativeTarget section */ 202 | 203 | /* Begin PBXProject section */ 204 | 9CE3B8051EAB2362009B63D5 /* Project object */ = { 205 | isa = PBXProject; 206 | attributes = { 207 | LastUpgradeCheck = 0820; 208 | ORGANIZATIONNAME = Single; 209 | TargetAttributes = { 210 | 9CE3B80C1EAB2362009B63D5 = { 211 | CreatedOnToolsVersion = 8.2.1; 212 | DevelopmentTeam = SWXNKT9754; 213 | ProvisioningStyle = Automatic; 214 | }; 215 | }; 216 | }; 217 | buildConfigurationList = 9CE3B8081EAB2362009B63D5 /* Build configuration list for PBXProject "demo" */; 218 | compatibilityVersion = "Xcode 3.2"; 219 | developmentRegion = English; 220 | hasScannedForEncodings = 0; 221 | knownRegions = ( 222 | en, 223 | Base, 224 | ); 225 | mainGroup = 9CE3B8041EAB2362009B63D5; 226 | productRefGroup = 9CE3B80E1EAB2362009B63D5 /* Products */; 227 | projectDirPath = ""; 228 | projectRoot = ""; 229 | targets = ( 230 | 9CE3B80C1EAB2362009B63D5 /* demo */, 231 | ); 232 | }; 233 | /* End PBXProject section */ 234 | 235 | /* Begin PBXResourcesBuildPhase section */ 236 | 9CE3B80B1EAB2362009B63D5 /* Resources */ = { 237 | isa = PBXResourcesBuildPhase; 238 | buildActionMask = 2147483647; 239 | files = ( 240 | 9CE3B81D1EAB2362009B63D5 /* Assets.xcassets in Resources */, 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | }; 244 | /* End PBXResourcesBuildPhase section */ 245 | 246 | /* Begin PBXSourcesBuildPhase section */ 247 | 9CE3B8091EAB2362009B63D5 /* Sources */ = { 248 | isa = PBXSourcesBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | 9CE3B8151EAB2362009B63D5 /* AppDelegate.m in Sources */, 252 | 9C9D215A1EAB2529006CC234 /* SGSwipeViewExample.m in Sources */, 253 | 9C9D21611EAB2667006CC234 /* SGTableViewExample.m in Sources */, 254 | 9C9D21551EAB2529006CC234 /* SGCollectionViewFlowLayoutExample.m in Sources */, 255 | 9CE3B8121EAB2362009B63D5 /* main.m in Sources */, 256 | 9C9D215B1EAB2529006CC234 /* SGTransformViewExample.m in Sources */, 257 | 9C9D21591EAB2529006CC234 /* SGPageViewExample.m in Sources */, 258 | 9C9D21561EAB2529006CC234 /* SGGuideViewExample.m in Sources */, 259 | 9C9D21541EAB2529006CC234 /* Example.m in Sources */, 260 | 9C9D21571EAB2529006CC234 /* SGImagePlayerExample.m in Sources */, 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | /* End PBXSourcesBuildPhase section */ 265 | 266 | /* Begin XCBuildConfiguration section */ 267 | 9CE3B8221EAB2362009B63D5 /* Debug */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | ALWAYS_SEARCH_USER_PATHS = NO; 271 | CLANG_ANALYZER_NONNULL = YES; 272 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 273 | CLANG_CXX_LIBRARY = "libc++"; 274 | CLANG_ENABLE_MODULES = YES; 275 | CLANG_ENABLE_OBJC_ARC = YES; 276 | CLANG_WARN_BOOL_CONVERSION = YES; 277 | CLANG_WARN_CONSTANT_CONVERSION = YES; 278 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 279 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 280 | CLANG_WARN_EMPTY_BODY = YES; 281 | CLANG_WARN_ENUM_CONVERSION = YES; 282 | CLANG_WARN_INFINITE_RECURSION = YES; 283 | CLANG_WARN_INT_CONVERSION = YES; 284 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 285 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 286 | CLANG_WARN_UNREACHABLE_CODE = YES; 287 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 288 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 289 | COPY_PHASE_STRIP = NO; 290 | DEBUG_INFORMATION_FORMAT = dwarf; 291 | ENABLE_STRICT_OBJC_MSGSEND = YES; 292 | ENABLE_TESTABILITY = YES; 293 | GCC_C_LANGUAGE_STANDARD = gnu99; 294 | GCC_DYNAMIC_NO_PIC = NO; 295 | GCC_NO_COMMON_BLOCKS = YES; 296 | GCC_OPTIMIZATION_LEVEL = 0; 297 | GCC_PREPROCESSOR_DEFINITIONS = ( 298 | "DEBUG=1", 299 | "$(inherited)", 300 | ); 301 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 302 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 303 | GCC_WARN_UNDECLARED_SELECTOR = YES; 304 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 305 | GCC_WARN_UNUSED_FUNCTION = YES; 306 | GCC_WARN_UNUSED_VARIABLE = YES; 307 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 308 | MTL_ENABLE_DEBUG_INFO = YES; 309 | ONLY_ACTIVE_ARCH = YES; 310 | SDKROOT = iphoneos; 311 | }; 312 | name = Debug; 313 | }; 314 | 9CE3B8231EAB2362009B63D5 /* Release */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | ALWAYS_SEARCH_USER_PATHS = NO; 318 | CLANG_ANALYZER_NONNULL = YES; 319 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 320 | CLANG_CXX_LIBRARY = "libc++"; 321 | CLANG_ENABLE_MODULES = YES; 322 | CLANG_ENABLE_OBJC_ARC = YES; 323 | CLANG_WARN_BOOL_CONVERSION = YES; 324 | CLANG_WARN_CONSTANT_CONVERSION = YES; 325 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 326 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 327 | CLANG_WARN_EMPTY_BODY = YES; 328 | CLANG_WARN_ENUM_CONVERSION = YES; 329 | CLANG_WARN_INFINITE_RECURSION = YES; 330 | CLANG_WARN_INT_CONVERSION = YES; 331 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 332 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 333 | CLANG_WARN_UNREACHABLE_CODE = YES; 334 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 335 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 336 | COPY_PHASE_STRIP = NO; 337 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 338 | ENABLE_NS_ASSERTIONS = NO; 339 | ENABLE_STRICT_OBJC_MSGSEND = YES; 340 | GCC_C_LANGUAGE_STANDARD = gnu99; 341 | GCC_NO_COMMON_BLOCKS = YES; 342 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 343 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 344 | GCC_WARN_UNDECLARED_SELECTOR = YES; 345 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 346 | GCC_WARN_UNUSED_FUNCTION = YES; 347 | GCC_WARN_UNUSED_VARIABLE = YES; 348 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 349 | MTL_ENABLE_DEBUG_INFO = NO; 350 | SDKROOT = iphoneos; 351 | VALIDATE_PRODUCT = YES; 352 | }; 353 | name = Release; 354 | }; 355 | 9CE3B8251EAB2362009B63D5 /* Debug */ = { 356 | isa = XCBuildConfiguration; 357 | buildSettings = { 358 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 359 | DEVELOPMENT_TEAM = SWXNKT9754; 360 | INFOPLIST_FILE = demo/Info.plist; 361 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 362 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 363 | OTHER_LDFLAGS = "-ObjC"; 364 | PRODUCT_BUNDLE_IDENTIFIER = "com.libobjc.SGKit-demo"; 365 | PRODUCT_NAME = "$(TARGET_NAME)"; 366 | TARGETED_DEVICE_FAMILY = 1; 367 | }; 368 | name = Debug; 369 | }; 370 | 9CE3B8261EAB2362009B63D5 /* Release */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 374 | DEVELOPMENT_TEAM = SWXNKT9754; 375 | INFOPLIST_FILE = demo/Info.plist; 376 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 377 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 378 | OTHER_LDFLAGS = "-ObjC"; 379 | PRODUCT_BUNDLE_IDENTIFIER = "com.libobjc.SGKit-demo"; 380 | PRODUCT_NAME = "$(TARGET_NAME)"; 381 | TARGETED_DEVICE_FAMILY = 1; 382 | }; 383 | name = Release; 384 | }; 385 | /* End XCBuildConfiguration section */ 386 | 387 | /* Begin XCConfigurationList section */ 388 | 9CE3B8081EAB2362009B63D5 /* Build configuration list for PBXProject "demo" */ = { 389 | isa = XCConfigurationList; 390 | buildConfigurations = ( 391 | 9CE3B8221EAB2362009B63D5 /* Debug */, 392 | 9CE3B8231EAB2362009B63D5 /* Release */, 393 | ); 394 | defaultConfigurationIsVisible = 0; 395 | defaultConfigurationName = Release; 396 | }; 397 | 9CE3B8241EAB2362009B63D5 /* Build configuration list for PBXNativeTarget "demo" */ = { 398 | isa = XCConfigurationList; 399 | buildConfigurations = ( 400 | 9CE3B8251EAB2362009B63D5 /* Debug */, 401 | 9CE3B8261EAB2362009B63D5 /* Release */, 402 | ); 403 | defaultConfigurationIsVisible = 0; 404 | defaultConfigurationName = Release; 405 | }; 406 | /* End XCConfigurationList section */ 407 | }; 408 | rootObject = 9CE3B8051EAB2362009B63D5 /* Project object */; 409 | } 410 | -------------------------------------------------------------------------------- /demo/demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /demo/demo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /demo/demo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // demo 4 | // 5 | // Created by Single on 2017/4/22. 6 | // Copyright © 2017年 Single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /demo/demo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // demo 4 | // 5 | // Created by Single on 2017/4/22. 6 | // Copyright © 2017年 Single. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "Example.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 21 | self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[Example alloc] init]]; 22 | [self.window makeKeyAndVisible]; 23 | 24 | return YES; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /demo/demo/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 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /demo/demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /demo/demo/Assets.xcassets/moto_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "moto_1@2x.jpg", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /demo/demo/Assets.xcassets/moto_1.imageset/moto_1@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libobjc/SGKit/70055cd30f4786d1cccc3067b79a30c361130d8f/demo/demo/Assets.xcassets/moto_1.imageset/moto_1@2x.jpg -------------------------------------------------------------------------------- /demo/demo/Assets.xcassets/moto_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "moto_2@2x.jpg", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /demo/demo/Assets.xcassets/moto_2.imageset/moto_2@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libobjc/SGKit/70055cd30f4786d1cccc3067b79a30c361130d8f/demo/demo/Assets.xcassets/moto_2.imageset/moto_2@2x.jpg -------------------------------------------------------------------------------- /demo/demo/Assets.xcassets/moto_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "moto_3@2x.jpg", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /demo/demo/Assets.xcassets/moto_3.imageset/moto_3@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libobjc/SGKit/70055cd30f4786d1cccc3067b79a30c361130d8f/demo/demo/Assets.xcassets/moto_3.imageset/moto_3@2x.jpg -------------------------------------------------------------------------------- /demo/demo/Assets.xcassets/moto_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "moto_4@2x.jpg", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /demo/demo/Assets.xcassets/moto_4.imageset/moto_4@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libobjc/SGKit/70055cd30f4786d1cccc3067b79a30c361130d8f/demo/demo/Assets.xcassets/moto_4.imageset/moto_4@2x.jpg -------------------------------------------------------------------------------- /demo/demo/Core/Example.h: -------------------------------------------------------------------------------- 1 | // 2 | // Example.h 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Example : UIViewController 12 | 13 | @property (nonatomic, strong, readonly) NSArray * classNames; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /demo/demo/Core/Example.m: -------------------------------------------------------------------------------- 1 | // 2 | // Example.m 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "Example.h" 10 | 11 | @interface Example () 12 | 13 | @property (nonatomic, strong) UITableView * tableView; 14 | 15 | @end 16 | 17 | @implementation Example 18 | 19 | - (NSArray *)classNames 20 | { 21 | return @[@"SGSwipeViewExample", 22 | @"SGPageViewExample", 23 | @"SGTransformViewExample", 24 | @"SGCollectionViewFlowLayoutExample", 25 | @"SGImagePlayerExample", 26 | @"SGGuideViewExample"]; 27 | } 28 | 29 | - (void)viewDidLoad 30 | { 31 | [super viewDidLoad]; 32 | 33 | self.title = @"SGKit"; 34 | self.view.backgroundColor = [UIColor whiteColor]; 35 | 36 | self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; 37 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; 38 | self.tableView.delegate = self; 39 | self.tableView.dataSource = self; 40 | 41 | [self.view addSubview:self.tableView]; 42 | } 43 | 44 | - (void)viewDidLayoutSubviews 45 | { 46 | [super viewDidLayoutSubviews]; 47 | [self updateLayout]; 48 | } 49 | 50 | - (void)updateLayout 51 | { 52 | self.tableView.frame = self.view.bounds; 53 | } 54 | 55 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 56 | { 57 | return 1; 58 | } 59 | 60 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 61 | { 62 | return self.classNames.count; 63 | } 64 | 65 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 66 | { 67 | UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; 68 | cell.textLabel.text = [self.classNames objectAtIndex:indexPath.row]; 69 | return cell; 70 | } 71 | 72 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 73 | { 74 | Class class = NSClassFromString([self.classNames objectAtIndex:indexPath.row]); 75 | UIViewController * example = [[class alloc] init]; 76 | example.title = [self.classNames objectAtIndex:indexPath.row]; 77 | [self.navigationController pushViewController:example animated:YES]; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /demo/demo/Core/SGCollectionViewFlowLayoutExample/SGCollectionViewFlowLayoutExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGCollectionViewFlowLayoutDemo.h 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/5. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SGCollectionViewFlowLayoutExample : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /demo/demo/Core/SGCollectionViewFlowLayoutExample/SGCollectionViewFlowLayoutExample.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGCollectionViewFlowLayoutDemo.m 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/5. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGCollectionViewFlowLayoutExample.h" 10 | #import 11 | 12 | @interface SGCollectionViewFlowLayoutExample () 13 | 14 | @property (nonatomic, strong) UICollectionView * collectionView; 15 | 16 | @end 17 | 18 | @implementation SGCollectionViewFlowLayoutExample 19 | 20 | - (void)viewDidLoad 21 | { 22 | [super viewDidLoad]; 23 | 24 | self.view.backgroundColor = [UIColor whiteColor]; 25 | 26 | SGCollectionViewFlowLayout * flowLayout = [[SGCollectionViewFlowLayout alloc] init]; 27 | self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout]; 28 | self.collectionView.backgroundColor = [UIColor whiteColor]; 29 | self.collectionView.delegate = self; 30 | self.collectionView.dataSource = self; 31 | [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"]; 32 | [self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"]; 33 | 34 | [self.view addSubview:self.collectionView]; 35 | } 36 | 37 | - (void)viewDidLayoutSubviews 38 | { 39 | [super viewDidLayoutSubviews]; 40 | [self updateLayout]; 41 | } 42 | 43 | - (void)updateLayout 44 | { 45 | self.collectionView.frame = self.view.bounds; 46 | } 47 | 48 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 49 | { 50 | return 8; 51 | } 52 | 53 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 54 | { 55 | return 13; 56 | } 57 | 58 | - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath 59 | { 60 | if (kind == UICollectionElementKindSectionHeader) { 61 | UICollectionReusableView * view = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"header" forIndexPath:indexPath]; 62 | view.backgroundColor = [UIColor sg_colorWithRed:231 green:231 blue:231]; 63 | return view; 64 | } 65 | return nil; 66 | } 67 | 68 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 69 | { 70 | UICollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath]; 71 | cell.backgroundColor = [UIColor colorWithWhite:1 alpha:0.8]; 72 | return cell; 73 | } 74 | 75 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section 76 | { 77 | return UIEdgeInsetsMake(20, 20, 20, 20); 78 | } 79 | 80 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 81 | { 82 | return CGSizeMake(80, 50); 83 | } 84 | 85 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section 86 | { 87 | return CGSizeMake([UIScreen mainScreen].bounds.size.width, 40); 88 | } 89 | 90 | - (UIColor *)collectionView:(UICollectionView *)collectionView layout:(SGCollectionViewFlowLayout *)collectionViewLayout backgroundColorForSectionAtIndex:(NSInteger)section 91 | { 92 | NSInteger index = arc4random() % 4; 93 | switch (index) { 94 | case 0: 95 | return [UIColor sg_colorWithRed:242 green:167 blue:151]; 96 | case 1: 97 | return [UIColor sg_colorWithRed:187 green:224 blue:234]; 98 | case 2: 99 | return [UIColor sg_colorWithRed:252 green:218 blue:182]; 100 | default: 101 | return [UIColor sg_colorWithRed:194 green:225 blue:200]; 102 | } 103 | } 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /demo/demo/Core/SGGuideViewExample/SGGuideViewExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGGuideViewExample.h 3 | // SGDemo 4 | // 5 | // Created by Single on 09/01/2017. 6 | // Copyright © 2017 single. All rights reserved. 7 | // 8 | 9 | #import "Example.h" 10 | 11 | @interface SGGuideViewExample : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /demo/demo/Core/SGGuideViewExample/SGGuideViewExample.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGGuideViewExample.m 3 | // SGDemo 4 | // 5 | // Created by Single on 09/01/2017. 6 | // Copyright © 2017 single. All rights reserved. 7 | // 8 | 9 | #import "SGGuideViewExample.h" 10 | #import 11 | 12 | @interface SGGuideViewExample () 13 | 14 | @property (nonatomic, strong) SGGuideView * guideView; 15 | 16 | @end 17 | 18 | @implementation SGGuideViewExample 19 | 20 | - (void)viewDidLoad 21 | { 22 | [super viewDidLoad]; 23 | 24 | self.view.backgroundColor = [UIColor whiteColor]; 25 | 26 | self.guideView = [SGGuideView guideViewWithImageNames:@[@"moto_1", @"moto_2", @"moto_3"]]; 27 | self.guideView.delegate = self; 28 | [self.view addSubview:self.guideView]; 29 | } 30 | 31 | - (void)viewDidLayoutSubviews 32 | { 33 | [super viewDidLayoutSubviews]; 34 | [self updateLayout]; 35 | } 36 | 37 | - (void)updateLayout 38 | { 39 | self.guideView.frame = self.view.bounds; 40 | } 41 | 42 | - (void)guideViewWillDisapper:(SGGuideView *)guideView 43 | { 44 | NSLog(@"%s", __func__); 45 | } 46 | 47 | - (void)guideViewDidDisapper:(SGGuideView *)guideView 48 | { 49 | NSLog(@"%s", __func__); 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /demo/demo/Core/SGImagePlayerExample/SGImagePlayerExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGImagePlayerExample.h 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SGImagePlayerExample : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /demo/demo/Core/SGImagePlayerExample/SGImagePlayerExample.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGImagePlayerExample.m 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGImagePlayerExample.h" 10 | #import 11 | 12 | @interface SGImagePlayerExample () 13 | 14 | @property (nonatomic, strong) SGImagePlayer * imagePlayer; 15 | @property (nonatomic, strong) UIButton * reloadButton; 16 | 17 | @end 18 | 19 | @implementation SGImagePlayerExample 20 | 21 | - (void)viewDidLoad 22 | { 23 | [super viewDidLoad]; 24 | 25 | self.automaticallyAdjustsScrollViewInsets = NO; 26 | self.view.backgroundColor = [UIColor whiteColor]; 27 | 28 | self.imagePlayer = [[SGImagePlayer alloc] initWithFrame:CGRectZero]; 29 | self.imagePlayer.delegate = self; 30 | self.imagePlayer.imageViewsContentMode = UIViewContentModeScaleAspectFit; 31 | 32 | self.reloadButton = [[UIButton alloc] initWithFrame:CGRectZero]; 33 | [self.reloadButton setTitle:@"Reload" forState:UIControlStateNormal]; 34 | [self.reloadButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 35 | [self.reloadButton addTarget:self action:@selector(reloadButtonAction) forControlEvents:UIControlEventTouchUpInside]; 36 | 37 | [self.view addSubview:self.imagePlayer]; 38 | [self.view addSubview:self.reloadButton]; 39 | } 40 | 41 | - (void)viewDidLayoutSubviews 42 | { 43 | [super viewDidLayoutSubviews]; 44 | [self updateLayout]; 45 | } 46 | 47 | - (void)updateLayout 48 | { 49 | self.imagePlayer.frame = self.view.bounds; 50 | self.reloadButton.frame = CGRectMake(0, 51 | CGRectGetHeight(self.view.bounds) - 20 - 20, 52 | 80, 53 | 20); 54 | } 55 | 56 | - (void)reloadButtonAction 57 | { 58 | [self.imagePlayer reloadData]; 59 | } 60 | 61 | - (NSInteger)numberOfImagesInImagePlayer:(SGImagePlayer *)imagePlayer 62 | { 63 | return 4; 64 | } 65 | 66 | - (void)imagePlayer:(SGImagePlayer *)imagePlayer imageView:(UIImageView *)imageView atIndex:(NSInteger)index 67 | { 68 | imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"moto_%ld", index + 1]]; 69 | } 70 | 71 | - (void)imagePlayerDidFinishLoad:(SGImagePlayer *)imagePlayer currentIndex:(NSInteger)index 72 | { 73 | NSLog(@"%s", __func__); 74 | } 75 | 76 | - (void)imagePlayer:(SGImagePlayer *)imagePlayer didTapAtIndex:(NSInteger)index 77 | { 78 | NSLog(@"%s, index : %ld", __func__, index); 79 | } 80 | 81 | - (void)ImagePlayer:(SGImagePlayer *)imagePlayer editPageControlSystem:(UIPageControl *)pageControlSystem 82 | { 83 | pageControlSystem.pageIndicatorTintColor = [UIColor blackColor]; 84 | pageControlSystem.currentPageIndicatorTintColor = [UIColor sg_colorWithRed:194 green:225 blue:200]; 85 | } 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /demo/demo/Core/SGPageViewExample/SGPageViewExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageViewExample.h 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SGPageViewExample : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /demo/demo/Core/SGPageViewExample/SGPageViewExample.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGPageViewExample.m 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/17. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGPageViewExample.h" 10 | #import 11 | #import "SGTableViewExample.h" 12 | 13 | @interface SGPageViewExample () 14 | 15 | @property (nonatomic, strong) SGPageView * pageView; 16 | @property (nonatomic, strong) SGPageTitleView * pageTitleView; 17 | 18 | @end 19 | 20 | @implementation SGPageViewExample 21 | 22 | - (void)viewDidLoad 23 | { 24 | [super viewDidLoad]; 25 | [self UILayout]; 26 | } 27 | 28 | - (void)UILayout 29 | { 30 | self.view.backgroundColor = [UIColor whiteColor]; 31 | self.automaticallyAdjustsScrollViewInsets = NO; 32 | 33 | self.pageView = [[SGPageView alloc] initWithFrame:CGRectZero]; 34 | self.pageView.delegate = self; 35 | self.pageView.defaultIndex = 2; 36 | 37 | self.pageTitleView = [[SGPageTitleView alloc] initWithFrame:CGRectZero]; 38 | self.pageTitleView.bottomLineColor = [UIColor sg_colorWithRed:242 green:167 blue:151]; 39 | self.pageTitleView.bottomBoardColor = [UIColor sg_colorWithRed:242 green:167 blue:151]; 40 | self.pageTitleView.showBottomLine = YES; 41 | self.pageTitleView.leftMargin = 100; 42 | self.pageTitleView.rightMargin = 50; 43 | self.pageTitleView.showBottomBoard = YES; 44 | 45 | [self.view addSubview:self.pageView]; 46 | [self.view addSubview:self.pageTitleView]; 47 | } 48 | 49 | - (void)viewDidLayoutSubviews 50 | { 51 | [super viewDidLayoutSubviews]; 52 | 53 | self.pageTitleView.frame = CGRectMake(0, 70, CGRectGetWidth(self.view.bounds), 44); 54 | self.pageView.frame = CGRectMake(0, 55 | CGRectGetMaxY(self.pageTitleView.frame), 56 | CGRectGetWidth(self.view.bounds), 57 | CGRectGetHeight(self.view.bounds) - CGRectGetMaxY(self.pageTitleView.frame)); 58 | 59 | } 60 | 61 | - (NSInteger)numberOfPagesInPageView:(SGPageView *)pageView 62 | { 63 | return 5; 64 | } 65 | 66 | - (UIView *)pageView:(SGPageView *)pageView viewAtIndex:(NSInteger)index 67 | { 68 | SGTableViewExample * view = [[SGTableViewExample alloc] initWithNumber:100]; 69 | view.backgroundColor = [UIColor sg_randomColor]; 70 | return view; 71 | } 72 | 73 | - (void)pageView:(SGPageView *)pageView didScrollToIndex:(NSInteger)index 74 | { 75 | NSLog(@"scroll to index : %ld", index); 76 | } 77 | 78 | - (SGPageTitleView *)pageTitleViewInPageView:(SGPageView *)pageView 79 | { 80 | return self.pageTitleView; 81 | } 82 | 83 | - (SGPageTitleItem *)pageView:(SGPageView *)pageView pageTitleView:(SGPageTitleView *)pageTitleView titleItemAtIndex:(NSInteger)index 84 | { 85 | SGPageTitleLabelItem * item = [[SGPageTitleLabelItem alloc] initWithFrame:CGRectZero]; 86 | item.text = [NSString stringWithFormat:@"%ld", index]; 87 | item.selectedColor = [UIColor sg_colorWithRed:242 green:167 blue:151]; 88 | item.selectedFont = [UIFont systemFontOfSize:16]; 89 | item.itemWidth = 100; 90 | return item; 91 | } 92 | 93 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 94 | { 95 | [self.pageView reloadData]; 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /demo/demo/Core/SGPageViewExample/SGTableViewExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // TableView.h 3 | // ScrollDemo 4 | // 5 | // Created by Single on 2016/10/27. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SGTableViewExample : UIView 13 | 14 | - (instancetype)initWithNumber:(NSInteger)number; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /demo/demo/Core/SGPageViewExample/SGTableViewExample.m: -------------------------------------------------------------------------------- 1 | // 2 | // TableView.m 3 | // ScrollDemo 4 | // 5 | // Created by Single on 2016/10/27. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGTableViewExample.h" 10 | 11 | @interface SGTableViewExample () 12 | 13 | @property (nonatomic, strong) UITableView * tableView; 14 | @property (nonatomic, assign) NSInteger number; 15 | 16 | @end 17 | 18 | @implementation SGTableViewExample 19 | 20 | - (UIScrollView *)scrollViewInPageItem:(UIView *)pageItem 21 | { 22 | return self.tableView; 23 | } 24 | 25 | - (instancetype)initWithNumber:(NSInteger)number 26 | { 27 | if (self = [super initWithFrame:CGRectZero]) 28 | { 29 | self.number = number; 30 | [self UILayout]; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)UILayout 36 | { 37 | self.tableView = [[UITableView alloc] initWithFrame:self.bounds style:UITableViewStylePlain]; 38 | 39 | [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; 40 | self.tableView.delegate = self; 41 | self.tableView.dataSource = self; 42 | 43 | [self addSubview:self.tableView]; 44 | } 45 | 46 | - (void)layoutSubviews 47 | { 48 | [super layoutSubviews]; 49 | self.tableView.frame = self.bounds; 50 | } 51 | 52 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 53 | { 54 | return 1; 55 | } 56 | 57 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 58 | { 59 | return self.number; 60 | } 61 | 62 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 63 | { 64 | UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; 65 | 66 | cell.textLabel.text = [NSString stringWithFormat:@"第 %ld 行", indexPath.row]; 67 | 68 | return cell; 69 | } 70 | 71 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 72 | { 73 | return 50; 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /demo/demo/Core/SGSwipeViewExample/SGSwipeViewExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGSwipeViewExample.h 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/18. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SGSwipeViewExample : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /demo/demo/Core/SGSwipeViewExample/SGSwipeViewExample.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGSwipeViewExample.m 3 | // SGDemo 4 | // 5 | // Created by Single on 2016/11/18. 6 | // Copyright © 2016年 single. All rights reserved. 7 | // 8 | 9 | #import "SGSwipeViewExample.h" 10 | #import 11 | #import "SGTableViewExample.h" 12 | 13 | @interface SGSwipeViewExample () 14 | 15 | @property (nonatomic, strong) SGSwipeView * swipeView; 16 | @property (nonatomic, strong) SGPageView * pageView; 17 | @property (nonatomic, strong) UIView * headerView; 18 | @property (nonatomic, strong) SGPageTitleView * pageTitleView; 19 | 20 | @end 21 | 22 | @implementation SGSwipeViewExample 23 | 24 | - (void)viewDidLoad 25 | { 26 | [super viewDidLoad]; 27 | [self UILayout]; 28 | } 29 | 30 | - (void)UILayout 31 | { 32 | self.automaticallyAdjustsScrollViewInsets = NO; 33 | 34 | self.pageView = [[SGPageView alloc] initWithFrame:CGRectZero]; 35 | self.pageView.delegate = self; 36 | 37 | self.pageTitleView = [[SGPageTitleView alloc] initWithFrame:CGRectZero]; 38 | self.pageTitleView.bottomLineColor = [UIColor sg_colorWithRed:242 green:167 blue:151]; 39 | self.pageTitleView.bottomBoardColor = [UIColor sg_colorWithRed:242 green:167 blue:151]; 40 | self.pageTitleView.showBottomLine = YES; 41 | self.pageTitleView.leftMargin = 100; 42 | self.pageTitleView.rightMargin = 50; 43 | 44 | self.headerView = [[UIView alloc] initWithFrame:CGRectZero]; 45 | self.headerView.backgroundColor = [UIColor sg_colorWithRed:194 green:225 blue:200]; 46 | 47 | self.swipeView = [[SGSwipeView alloc] initWithFrame:self.view.bounds]; 48 | self.swipeView.delegate = self; 49 | 50 | [self.view addSubview:self.swipeView]; 51 | } 52 | 53 | - (void)viewDidLayoutSubviews 54 | { 55 | [super viewDidLayoutSubviews]; 56 | self.swipeView.frame = self.view.bounds; 57 | UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 58 | if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) { 59 | self.swipeView.topMargin = 30; 60 | } else { 61 | self.swipeView.topMargin = 64; 62 | } 63 | } 64 | 65 | 66 | #pragma mark - SGSwipeViewDelegate 67 | 68 | - (SGPageView *)pageViewInSwipeView:(SGSwipeView *)swipeView 69 | { 70 | return self.pageView; 71 | } 72 | 73 | - (UIView *)headerViewInSwipeView:(SGSwipeView *)swipeView 74 | { 75 | return self.headerView; 76 | } 77 | 78 | - (CGFloat)headerViewHeightInSwipeView:(SGSwipeView *)swipeView 79 | { 80 | return 220; 81 | } 82 | 83 | - (CGFloat)pageTitleViewHeightInSwipeView:(SGSwipeView *)swipeView 84 | { 85 | return 44; 86 | } 87 | 88 | 89 | #pragma SGPageViewDelegate 90 | 91 | - (NSInteger)numberOfPagesInPageView:(SGPageView *)pageView 92 | { 93 | return 5; 94 | } 95 | 96 | - (UIView *)pageView:(SGPageView *)pageView viewAtIndex:(NSInteger)index 97 | { 98 | UIView * view; 99 | if (index == 0) { 100 | view = (UIView *)[[UIView alloc] init]; 101 | UIView * label = [[UIView alloc] initWithFrame:CGRectMake(10, 50, 200, 120)]; 102 | label.backgroundColor = [UIColor sg_colorWithRed:187 green:224 blue:234]; 103 | view.backgroundColor = [UIColor sg_colorWithRed:252 green:218 blue:182]; 104 | [view addSubview:label]; 105 | return view; 106 | } else if (index == 1) { 107 | view = [[SGTableViewExample alloc] initWithNumber:10]; 108 | } else { 109 | view = [[SGTableViewExample alloc] initWithNumber:100]; 110 | } 111 | return view; 112 | } 113 | 114 | - (void)pageView:(SGPageView *)pageView didScrollToIndex:(NSInteger)index 115 | { 116 | 117 | } 118 | 119 | - (SGPageTitleView *)pageTitleViewInPageView:(SGPageView *)pageView 120 | { 121 | return self.pageTitleView; 122 | } 123 | 124 | - (SGPageTitleItem *)pageView:(SGPageView *)pageView pageTitleView:(SGPageTitleView *)pageTitleView titleItemAtIndex:(NSInteger)index 125 | { 126 | SGPageTitleLabelItem * item = [[SGPageTitleLabelItem alloc] initWithFrame:CGRectZero]; 127 | item.text = [NSString stringWithFormat:@"%ld", index]; 128 | item.selectedColor = [UIColor sg_colorWithRed:242 green:167 blue:151]; 129 | item.selectedFont = [UIFont systemFontOfSize:16]; 130 | item.itemWidth = 100; 131 | return item; 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /demo/demo/Core/SGTransformExample/SGTransformViewExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGTransformViewExample.h 3 | // SGDemo 4 | // 5 | // Created by Single on 19/12/2016. 6 | // Copyright © 2016 single. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SGTransformViewExample : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /demo/demo/Core/SGTransformExample/SGTransformViewExample.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGTransformViewExample.m 3 | // SGDemo 4 | // 5 | // Created by Single on 19/12/2016. 6 | // Copyright © 2016 single. All rights reserved. 7 | // 8 | 9 | #import "SGTransformViewExample.h" 10 | #import 11 | 12 | @interface SGTransformViewExample () 13 | 14 | @property (nonatomic, strong) SGTransformView * transformView; 15 | 16 | @end 17 | 18 | @implementation SGTransformViewExample 19 | 20 | - (void)viewDidLoad 21 | { 22 | [super viewDidLoad]; 23 | 24 | self.view.backgroundColor = [UIColor whiteColor]; 25 | 26 | self.transformView = [[SGTransformView alloc] initWithFrame:CGRectMake(50, 150, 240, 180)]; 27 | self.transformView.delegate = self; 28 | [self.view addSubview:self.transformView]; 29 | } 30 | 31 | /* 32 | - (CGPoint)transformView:(SGTransformView *)transformView needChangeCenterByMoveAction:(CGPoint)center 33 | { 34 | CGFloat minCenterX = transformView.frame.size.width / 2; 35 | CGFloat maxCenterX = [UIScreen mainScreen].bounds.size.width - minCenterX; 36 | 37 | if (center.x < minCenterX) { 38 | return CGPointMake(minCenterX, center.y); 39 | } else if (center.x > maxCenterX) { 40 | return CGPointMake(maxCenterX, center.y); 41 | } 42 | 43 | return center; 44 | } 45 | */ 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /demo/demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | SGKit 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /demo/demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // demo 4 | // 5 | // Created by Single on 2017/4/22. 6 | // Copyright © 2017年 Single. All rights reserved. 7 | // 8 | 9 | #import 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 | --------------------------------------------------------------------------------