diff --git a/.gitignore b/.gitignore index 9b9088f..fef22fd 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ build/ # Backup files *~.nib + +# Swift Package Manager +.swiftpm diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a01a9c5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +os: + - osx +language: swift +osx_image: xcode11 +env: + - PROJECT_NAME=SSFadingScrollView +install: swift package update +script: + - xcodebuild build -sdk iphoneos -scheme $PROJECT_NAME diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..b092d08 --- /dev/null +++ b/Package.swift @@ -0,0 +1,21 @@ +// swift-tools-version:5.1 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "SSFadingScrollView", + platforms: [.iOS(.v9)], + products: [ + .library( + name: "SSFadingScrollView", + targets: ["SSFadingScrollView"]), + ], + dependencies: [], + targets: [ + .target( + name: "SSFadingScrollView", + dependencies: [], + path: "SSFadingScrollView") + ] +) diff --git a/SSFadingScrollView.podspec b/SSFadingScrollView.podspec index 5e9905b..5f70ba0 100644 --- a/SSFadingScrollView.podspec +++ b/SSFadingScrollView.podspec @@ -5,7 +5,7 @@ Pod::Spec.new do |s| s.homepage = "https://github.com/stephsharp/SSFadingScrollView/" s.license = { :type => "MIT", :file => "LICENSE" } s.author = "Stephanie Sharp" - s.platform = :ios, "8.0" + s.platform = :ios, "9.3" s.source = { :git => "https://github.com/stephsharp/SSFadingScrollView.git", :tag => "v#{s.version}" } s.source_files = "SSFadingScrollView" s.public_header_files = [ "SSFadingScrollView/SSFadingScrollView.h" ] diff --git a/SSFadingScrollView.xcodeproj/project.pbxproj b/SSFadingScrollView.xcodeproj/project.pbxproj index 155d582..5026699 100644 --- a/SSFadingScrollView.xcodeproj/project.pbxproj +++ b/SSFadingScrollView.xcodeproj/project.pbxproj @@ -7,11 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 15BEF56C22B62DBA00CFB6CF /* SSFadingScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15BEF56B22B62DBA00CFB6CF /* SSFadingScrollView.swift */; }; 82630F651B63A4EE003B4CCA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 82630F641B63A4EE003B4CCA /* Images.xcassets */; }; - 82B3A6901C031A13000024C3 /* SSFadingScrollView.h in Headers */ = {isa = PBXBuildFile; fileRef = 82B3A68F1C031A13000024C3 /* SSFadingScrollView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 82B3A6941C031A13000024C3 /* SSFadingScrollView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82B3A68D1C031A13000024C3 /* SSFadingScrollView.framework */; }; 82B3A6951C031A13000024C3 /* SSFadingScrollView.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 82B3A68D1C031A13000024C3 /* SSFadingScrollView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 82B3A69B1C031AE4000024C3 /* SSFadingScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 82B3A69A1C031AE4000024C3 /* SSFadingScrollView.m */; }; 82B3A69F1C031FB6000024C3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 82B3A69E1C031FB6000024C3 /* LaunchScreen.storyboard */; }; 970FDD7517A7A512008DC2FB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 970FDD2A17A7A4DC008DC2FB /* UIKit.framework */; }; 970FDD7617A7A512008DC2FB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 970FDD2C17A7A4DC008DC2FB /* Foundation.framework */; }; @@ -48,11 +47,11 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 152EDF8422D113810082A3BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainStoryboard.storyboard; sourceTree = ""; }; + 15BEF56B22B62DBA00CFB6CF /* SSFadingScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSFadingScrollView.swift; sourceTree = ""; }; 82630F641B63A4EE003B4CCA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 82B3A68D1C031A13000024C3 /* SSFadingScrollView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSFadingScrollView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 82B3A68F1C031A13000024C3 /* SSFadingScrollView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSFadingScrollView.h; sourceTree = ""; }; 82B3A6911C031A13000024C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 82B3A69A1C031AE4000024C3 /* SSFadingScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSFadingScrollView.m; sourceTree = ""; }; 82B3A69E1C031FB6000024C3 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 970FDD2A17A7A4DC008DC2FB /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 970FDD2C17A7A4DC008DC2FB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -63,7 +62,6 @@ 970FDD7E17A7A512008DC2FB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 970FDD8117A7A512008DC2FB /* SSAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSAppDelegate.h; sourceTree = ""; }; 970FDD8217A7A512008DC2FB /* SSAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SSAppDelegate.m; sourceTree = ""; }; - 970FDD8B17A7A512008DC2FB /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard.storyboard; sourceTree = ""; }; 970FDD9B17A7A5B9008DC2FB /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -93,8 +91,7 @@ 82B3A68E1C031A13000024C3 /* SSFadingScrollView */ = { isa = PBXGroup; children = ( - 82B3A68F1C031A13000024C3 /* SSFadingScrollView.h */, - 82B3A69A1C031AE4000024C3 /* SSFadingScrollView.m */, + 15BEF56B22B62DBA00CFB6CF /* SSFadingScrollView.swift */, 82B3A6911C031A13000024C3 /* Info.plist */, ); path = SSFadingScrollView; @@ -160,7 +157,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 82B3A6901C031A13000024C3 /* SSFadingScrollView.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -211,20 +207,22 @@ isa = PBXProject; attributes = { CLASSPREFIX = SS; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 1110; ORGANIZATIONNAME = "Stephanie Sharp"; TargetAttributes = { 82B3A68C1C031A13000024C3 = { CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 1020; }; }; }; buildConfigurationList = 970FDD2217A7A4DC008DC2FB /* Build configuration list for PBXProject "SSFadingScrollView" */; compatibilityVersion = "Xcode 6.3"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 970FDD1E17A7A4DC008DC2FB; productRefGroup = 970FDD2817A7A4DC008DC2FB /* Products */; @@ -263,7 +261,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 82B3A69B1C031AE4000024C3 /* SSFadingScrollView.m in Sources */, + 15BEF56C22B62DBA00CFB6CF /* SSFadingScrollView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -298,7 +296,7 @@ 970FDD8A17A7A512008DC2FB /* MainStoryboard.storyboard */ = { isa = PBXVariantGroup; children = ( - 970FDD8B17A7A512008DC2FB /* en */, + 152EDF8422D113810082A3BA /* Base */, ); name = MainStoryboard.storyboard; sourceTree = ""; @@ -314,6 +312,7 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; @@ -334,6 +333,8 @@ PRODUCT_BUNDLE_IDENTIFIER = com.ssharp.SSFadingScrollView; PRODUCT_NAME = SSFadingScrollView; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -348,6 +349,7 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -370,6 +372,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.ssharp.SSFadingScrollView; PRODUCT_NAME = SSFadingScrollView; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -380,29 +383,47 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; @@ -412,23 +433,42 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; VALIDATE_PRODUCT = YES; }; name = Release; @@ -436,6 +476,7 @@ 970FDD9117A7A512008DC2FB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; INFOPLIST_FILE = "$(SRCROOT)/SSFadingScrollViewDemo/SSFadingScrollViewDemo-Info.plist"; @@ -449,6 +490,7 @@ 970FDD9217A7A512008DC2FB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; INFOPLIST_FILE = "$(SRCROOT)/SSFadingScrollViewDemo/SSFadingScrollViewDemo-Info.plist"; diff --git a/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme b/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme index d7d627d..2fc0979 100644 --- a/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme +++ b/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme @@ -1,6 +1,6 @@ - - - - - - - - + + - - - -//! Project version number for SSFadingScrollView. -FOUNDATION_EXPORT double SSFadingScrollViewVersionNumber; - -//! Project version string for SSFadingScrollView. -FOUNDATION_EXPORT const unsigned char SSFadingScrollViewVersionString[]; - -typedef NS_ENUM(NSUInteger, SSScrollViewFadeAxis) { - SSScrollViewFadeAxisVertical = 0, - SSScrollViewFadeAxisHorizontal = 1, -}; - -typedef NS_ENUM(NSUInteger, FadeEdges) { - FadeEdgesTopAndBottom __attribute__((deprecated("Use the fadeLeadingEdge and fadeTrailingEdge properties instead."))), - FadeEdgesTop __attribute__((deprecated("Use the fadeLeadingEdge property instead."))), - FadeEdgesBottom __attribute__((deprecated("Use the fadeTrailingEdge property instead."))), -}; - -/** - * This scrollview subclass is meant to only scroll in one direction (horizontal or vertical). - * On the chosen axis, either or both the leading and trailing edges can be faded. - */ -@interface SSFadingScrollView : UIScrollView - -/** - * Designated initializer. - */ -- (instancetype)initWithFadeSize:(CGFloat)fadeSize axis:(SSScrollViewFadeAxis)fadeAxis; - -/** - * Initializer that fades the top and bottom of the scroll view. - */ -- (instancetype)initWithFadeSize:(CGFloat)fadeSize; - -/** - * Initializer that fades the top and bottom of the scroll view with default fade height. - */ -- (instancetype)init; - -#if TARGET_INTERFACE_BUILDER -@property (nonatomic) IBInspectable NSUInteger fadeAxis; -#else -@property (nonatomic) SSScrollViewFadeAxis fadeAxis; -#endif - -/** - * Fade leading edge of fade axis. Default is YES. - */ -@property (nonatomic) IBInspectable BOOL fadeLeadingEdge; - -/** - * Fade trailing edge of fade axis. Default is YES. - */ -@property (nonatomic) IBInspectable BOOL fadeTrailingEdge; - -/** - * Size of gradient. Default is 30. - */ -@property (nonatomic) IBInspectable CGFloat fadeSize; - -/** - * Duration of fade in & out. Default is 0.3 seconds. - */ -@property (nonatomic) IBInspectable double fadeDuration; - -/** - * Default is YES. Scroll bars are masked so they don't fade with the scroll view content. - * Set to NO to fade out the scroll bars along with the content. - */ -@property (nonatomic) IBInspectable BOOL maskScrollBars; - -#pragma mark - Deprecated - -/** - * Deprecated initializer. - */ -- (instancetype)initWithFadeHeight:(CGFloat)fadeHeight edges:(FadeEdges)fadeEdges __attribute__((deprecated("Use initWithFadeSize: and the fadeLeadingEdge/fadeTrailingEdge properties instead."))); - -/** - * Initializer that fades the top and bottom of the scroll view. - */ -- (instancetype)initWithFadeHeight:(CGFloat)fadeHeight __attribute__((deprecated("Use initWithFadeSize: instead."))); - -/** - * Fade top of scroll view. Default is YES. - */ -@property (nonatomic) BOOL fadeTop __attribute__((deprecated("Use the fadeLeadingEdge property instead."))); - -/** - * Fade bottom of scroll view. Default is YES. - */ -@property (nonatomic) BOOL fadeBottom __attribute__((deprecated("Use the fadeTrailingEdge property instead."))); - -/** - * Height of gradient. Default is 30. - */ -@property (nonatomic) CGFloat fadeHeight __attribute__((deprecated("Use the fadeSize property instead."))); - -@end diff --git a/SSFadingScrollView/SSFadingScrollView.m b/SSFadingScrollView/SSFadingScrollView.m deleted file mode 100644 index 5aaf45a..0000000 --- a/SSFadingScrollView/SSFadingScrollView.m +++ /dev/null @@ -1,467 +0,0 @@ -// -// SSFadingScrollView.m -// Created by Stephanie Sharp on 1/06/13. -// - -#import "SSFadingScrollView.h" -#import - -static CGFloat const SSDefaultFadeSize = 30.0; -static CFTimeInterval const SSDefaultFadeDuration = 0.3; -static void *SSContext = &SSContext; - -@interface SSFadingScrollView () - -@property (nonatomic) CALayer *maskLayer; -@property (nonatomic) CAGradientLayer *gradientLayer; - -@property (nonatomic) UIImageView *verticalScrollBar; -@property (nonatomic) UIImageView *horizontalScrollBar; -@property (nonatomic) CALayer *verticalScrollBarLayer; -@property (nonatomic) CALayer *horizontalScrollBarLayer; - -@end - -@implementation SSFadingScrollView - -#pragma mark - Initializers - -- (instancetype)initWithFadeSize:(CGFloat)fadeSize axis:(SSScrollViewFadeAxis)fadeAxis -{ - self = [super initWithFrame:CGRectZero]; - if (self) { - [self setDefaults]; - _fadeSize = fadeSize; - _fadeAxis = fadeAxis; - } - return self; -} - -- (instancetype)initWithFadeSize:(CGFloat)fadeSize -{ - return [self initWithFadeSize:fadeSize axis:SSScrollViewFadeAxisVertical]; -} - -- (instancetype)init -{ - return [self initWithFadeSize:SSDefaultFadeSize]; -} - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [self init]; - if (self) { - [self setDefaults]; - self.frame = frame; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)coder -{ - self = [super initWithCoder:coder]; - if (self) { - [self setDefaults]; - } - return self; -} - -- (void)setDefaults -{ - _fadeAxis = SSScrollViewFadeAxisVertical; - _fadeLeadingEdge = YES; - _fadeTrailingEdge = YES; - _fadeSize = SSDefaultFadeSize; - _fadeDuration = SSDefaultFadeDuration; - _maskScrollBars = YES; -} - -- (void)dealloc -{ - if (_verticalScrollBar) { - [_verticalScrollBar removeObserver:self forKeyPath:@"alpha" context:SSContext]; - } - if (_horizontalScrollBar) { - [_horizontalScrollBar removeObserver:self forKeyPath:@"alpha" context:SSContext]; - } -} - -#pragma mark - Layout - -- (void)layoutSubviews -{ - [super layoutSubviews]; - [self updateMask]; -} - -- (void)updateMask -{ - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - self.maskLayer.frame = self.bounds; - [CATransaction commit]; - - [self updateGradients]; - [self updateScrollBarMasks]; -} - -- (void)updateGradients -{ - self.gradientLayer.frame = self.maskLayer.bounds; - NSInteger contentOffset = roundf(self.isVertical ? self.contentOffset.y : self.contentOffset.x); - - if (self.fadeLeadingEdge) { - if (!self.leadingGradientIsHidden && contentOffset <= 0) { - [self animateLeadingGradientToColor:[SSFadingScrollView opaqueColor]]; // fade out - } - else if (self.leadingGradientIsHidden && contentOffset > 0) { - [self animateLeadingGradientToColor:[SSFadingScrollView transparentColor]]; // fade in - } - } - if (self.fadeTrailingEdge) { - NSInteger maxContentOffset; - if (self.isVertical) { - maxContentOffset = roundf(self.contentSize.height - CGRectGetHeight(self.bounds)); - } - else { - maxContentOffset = roundf(self.contentSize.width - CGRectGetWidth(self.bounds)); - } - - if (!self.trailingGradientIsHidden && contentOffset >= maxContentOffset) { - [self animateTrailingGradientToColor:[SSFadingScrollView opaqueColor]]; - } - else if (self.trailingGradientIsHidden && contentOffset < maxContentOffset) { - [self animateTrailingGradientToColor:[SSFadingScrollView transparentColor]]; - } - } -} - -#pragma mark - Properties - -- (BOOL)isVertical -{ - return self.fadeAxis == SSScrollViewFadeAxisVertical; -} - -- (CALayer *)maskLayer -{ - if (!_maskLayer) { - _maskLayer = [self setupMaskLayer]; - } - return _maskLayer; -} - -- (CALayer *)verticalScrollBarLayer -{ - if (!_verticalScrollBarLayer) { - _verticalScrollBarLayer = [self setupVerticalScrollBarLayer]; - } - - return _verticalScrollBarLayer; -} - -- (CALayer *)horizontalScrollBarLayer -{ - if (!_horizontalScrollBarLayer) { - _horizontalScrollBarLayer = [self setupHorizontalScrollBarLayer]; - } - - return _horizontalScrollBarLayer; -} - -- (BOOL)leadingGradientIsHidden -{ - CGColorRef firstColor = (__bridge CGColorRef)self.gradientLayer.colors.firstObject; - return CGColorEqualToColor(firstColor, [SSFadingScrollView opaqueColor]); -} - -- (BOOL)trailingGradientIsHidden -{ - CGColorRef lastColor = (__bridge CGColorRef)self.gradientLayer.colors.lastObject; - return CGColorEqualToColor(lastColor, [SSFadingScrollView opaqueColor]); -} - -#pragma mark - Mask - -- (CALayer *)setupMaskLayer -{ - CALayer *maskLayer = [CALayer layer]; - maskLayer.frame = self.bounds; - - self.gradientLayer = [self setupGradientLayer]; - [maskLayer addSublayer:self.gradientLayer]; - - if (self.maskScrollBars) { - [maskLayer addSublayer:self.verticalScrollBarLayer]; - [maskLayer addSublayer:self.horizontalScrollBarLayer]; - } - - self.layer.mask = maskLayer; - - return maskLayer; -} - -#pragma mark Mask colors - -+ (CGColorRef)opaqueColor -{ - return [UIColor blackColor].CGColor; -} - -+ (CGColorRef)transparentColor -{ - return [UIColor clearColor].CGColor; -} - -#pragma mark - Gradient mask - -- (CAGradientLayer *)setupGradientLayer -{ - id transparent = (id)[SSFadingScrollView transparentColor]; - id opaque = (id)[SSFadingScrollView opaqueColor]; - - CAGradientLayer *gradientLayer = [CAGradientLayer layer]; - CGRect frame = self.bounds; - frame.origin = CGPointZero; - gradientLayer.frame = frame; - - NSArray *colors = [NSArray new]; - NSArray *locations = [NSArray new]; - - CGFloat fadePercentage = [self percentageForFadeSize]; - - if (self.fadeLeadingEdge) { - colors = @[transparent, opaque]; - locations = @[@(0), @(fadePercentage)]; - } - if (self.fadeTrailingEdge) { - colors = [colors arrayByAddingObjectsFromArray:@[opaque, transparent]]; - locations = [locations arrayByAddingObjectsFromArray:@[@(1.0 - fadePercentage), @(1)]]; - } - - gradientLayer.colors = colors; - gradientLayer.locations = locations; - - if (self.isVertical) { - gradientLayer.startPoint = CGPointMake(0.5, 0); - gradientLayer.endPoint = CGPointMake(0.5, 1); - } - else { - gradientLayer.startPoint = CGPointMake(0, 0.5); - gradientLayer.endPoint = CGPointMake(1, 0.5); - } - - return gradientLayer; -} - -- (CGFloat)percentageForFadeSize -{ - CGFloat size = self.isVertical ? CGRectGetHeight(self.bounds) : CGRectGetWidth(self.bounds); - - if (size <= 0) { - return 0; - } - - CGFloat maxFadePercentage = (self.fadeLeadingEdge && self.fadeTrailingEdge) ? 0.5 : 1.0; - return fminf(self.fadeSize / size, maxFadePercentage); -} - -#pragma mark Gradient animation - -- (void)animateLeadingGradientToColor:(CGColorRef)color -{ - NSArray *colours = [self colorsArrayByReplacingObjectAtIndex:0 withColor:color]; - [self animateGradientColours:colours]; -} - -- (void)animateTrailingGradientToColor:(CGColorRef)color -{ - NSUInteger lastIndex = self.gradientLayer.colors.count - 1; - NSArray *colours = [self colorsArrayByReplacingObjectAtIndex:lastIndex withColor:color]; - [self animateGradientColours:colours]; -} - -- (NSArray *)colorsArrayByReplacingObjectAtIndex:(NSUInteger)index withColor:(CGColorRef)color -{ - NSMutableArray *mutableColours = [self.gradientLayer.colors mutableCopy]; - mutableColours[index] = (__bridge id)color; - - return [mutableColours copy]; -} - -- (void)animateGradientColours:(NSArray *)colours -{ - CABasicAnimation *animation; - animation = [CABasicAnimation animationWithKeyPath:@"colors"]; - animation.fromValue = ((CAGradientLayer *)self.gradientLayer.presentationLayer).colors; - animation.toValue = colours; - animation.duration = self.fadeDuration; - animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; - - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - self.gradientLayer.colors = colours; // update the model value - [CATransaction commit]; - - [self.gradientLayer addAnimation:animation forKey:@"animateGradient"]; -} - -#pragma mark - Scroll bar mask - -- (CALayer *)setupVerticalScrollBarLayer -{ - if (!self.verticalScrollBar) { - [self findScrollBars]; - - if (!self.verticalScrollBar) { - return nil; - } - } - - [self.verticalScrollBar addObserver:self forKeyPath:@"alpha" options:0 context:SSContext]; - - return [self scrollBarLayerWithFrame:self.verticalScrollBar.frame]; -} - -- (CALayer *)setupHorizontalScrollBarLayer -{ - if (!self.horizontalScrollBar) { - [self findScrollBars]; - - if (!self.horizontalScrollBar) { - return nil; - } - } - - [self.horizontalScrollBar addObserver:self forKeyPath:@"alpha" options:0 context:SSContext]; - - return [self scrollBarLayerWithFrame:self.horizontalScrollBar.frame]; -} - -- (void)findScrollBars -{ - for (UIView *subview in self.subviews) { - if ([subview isKindOfClass:[UIImageView class]] && subview.tag == 0) { - UIImageView *imageView = (UIImageView *)subview; - - if (imageView.frame.size.width == 3.5 || - imageView.frame.size.width == 2.5 || - (imageView.frame.size.width < 2.4 && imageView.frame.size.width > 2.3)) - { - self.verticalScrollBar = imageView; - } - else if (imageView.frame.size.height == 3.5 || - imageView.frame.size.height == 2.5 || - (imageView.frame.size.height < 2.4 && imageView.frame.size.height > 2.3)) - { - self.horizontalScrollBar = imageView; - } - } - } -} - -- (CALayer *)scrollBarLayerWithFrame:(CGRect)frame -{ - CALayer *scrollBarLayer = [CALayer layer]; - scrollBarLayer.backgroundColor = [SSFadingScrollView opaqueColor]; - scrollBarLayer.frame = frame; - - return scrollBarLayer; -} - -- (void)updateScrollBarMasks -{ - if (self.maskScrollBars) { - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - - CGRect verticalScrollBarFrame = [self.layer convertRect:self.verticalScrollBar.frame - toLayer:self.maskLayer]; - self.verticalScrollBarLayer.frame = verticalScrollBarFrame; - self.verticalScrollBarLayer.opacity = self.verticalScrollBar.alpha; - - CGRect horizontalScrollBarFrame = [self.layer convertRect:self.horizontalScrollBar.frame - toLayer:self.maskLayer]; - self.horizontalScrollBarLayer.frame = horizontalScrollBarFrame; - self.horizontalScrollBarLayer.opacity = self.horizontalScrollBar.alpha; - - [CATransaction commit]; - } -} - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context -{ - if (context != SSContext) { - return; - } - - if([keyPath isEqualToString:@"alpha"] && [object valueForKeyPath:keyPath] != [NSNull null]) { - [self layoutSubviews]; - } -} - -#pragma mark - Deprecated - -- (instancetype)initWithFadeHeight:(CGFloat)fadeHeight edges:(FadeEdges)fadeEdges -{ - self = [self initWithFadeSize:fadeHeight]; - if (self) { - switch (fadeEdges) { - case FadeEdgesTopAndBottom: - _fadeLeadingEdge = YES; - _fadeTrailingEdge = YES; - break; - case FadeEdgesTop: - _fadeLeadingEdge = YES; - _fadeTrailingEdge = NO; - break; - case FadeEdgesBottom: - _fadeLeadingEdge = NO; - _fadeTrailingEdge = YES; - break; - default: - break; - } - } - return self; -} - -- (instancetype)initWithFadeHeight:(CGFloat)fadeHeight -{ - return [self initWithFadeSize:fadeHeight]; -} - -- (BOOL)fadeTop; -{ - return self.fadeLeadingEdge; -} - -- (void)setFadeTop:(BOOL)fade; -{ - self.fadeLeadingEdge = fade; -} - -- (BOOL)fadeBottom; -{ - return self.fadeTrailingEdge; -} - -- (void)setFadeBottom:(BOOL)fade; -{ - self.fadeTrailingEdge = fade; -} - -- (CGFloat)fadeHeight; -{ - return self.fadeSize; -} - -- (void)setFadeHeight:(CGFloat)height; -{ - self.fadeSize = height; -} - -@end diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift new file mode 100644 index 0000000..fd7b654 --- /dev/null +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -0,0 +1,340 @@ +// +// SSFadingScrollView.swift +// SSFadingScrollView +// +// Created by Bartosz Dolewski on 16/06/2019. +// Copyright © 2019 Stephanie Sharp. All rights reserved. +// + +import UIKit +import QuartzCore + +@objc enum FadeAxis: Int { + case vertical = 0 + case horizontal = 1 +} + +private let SSDefaultFadeSize: CGFloat = 30.0 +private let SSDefaultFadeDuration: CFTimeInterval = 0.3 + +@IBDesignable +class SSFadingScrollView: UIScrollView { + + /// Fade leading edge of fade axis. Default is YES. + @IBInspectable public var fadeLeadingEdge = false + + /// Fade trailing edge of fade axis. Default is YES. + @IBInspectable public var fadeTrailingEdge = false + + /// Size of gradient. Default is 30. + @IBInspectable public var fadeSize: CGFloat = 0.0 + + /// Duration of fade in & out. Default is 0.3 seconds. + @IBInspectable public var fadeDuration = 0.0 + + /// Default is YES. Scroll bars are masked so they don't fade with the scroll view content. + /// Set to NO to fade out the scroll bars along with the content. + @IBInspectable public var maskScrollBars = false + + /// Set up the axis of fading + public var fadeAxis: FadeAxis = .vertical + + /// Set up the axis of fading in Interface Builder + @available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'fadeAxis' instead.") + @IBInspectable var axisIB: FadeAxis.RawValue { + set { fadeAxis = FadeAxis(rawValue: newValue) ?? .vertical } + get { return fadeAxis.rawValue } + } + + private lazy var maskLayer: CALayer = { + return setupMaskLayer() + }() + + private lazy var verticalScrollBarLayer: CALayer = { + return setupVerticalScrollBarLayer() + }() + + private lazy var horizontalScrollBarLayer: CALayer = { + return setupHorizontalScrollBarLayer() + }() + + private lazy var gradientLayer: CAGradientLayer = { + return setupGradientLayer() + }() + + private var verticalScrollBar: UIImageView? + private var horizontalScrollBar: UIImageView? + + private var verticalScrollObservation: NSKeyValueObservation? + private var horizontalScrollObservation: NSKeyValueObservation? + + // MARK: - Initializers + init(fadeSize: CGFloat, axis fadeAxis: FadeAxis) { + super.init(frame: CGRect.zero) + setDefaults() + self.fadeSize = fadeSize + self.fadeAxis = fadeAxis + + verticalScrollObservation = verticalScrollBar?.observe(\.alpha) { [weak self] object, change in + self?.layoutSubviews() + } + + horizontalScrollObservation = horizontalScrollBar?.observe(\.alpha) { [weak self] object, change in + self?.layoutSubviews() + } + } + + convenience init(fadeSize: CGFloat) { + self.init(fadeSize: fadeSize, axis: .vertical) + } + + convenience init() { + self.init(fadeSize: SSDefaultFadeSize) + } + + convenience override init(frame: CGRect) { + self.init() + setDefaults() + self.frame = frame + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setDefaults() + } + + override func layoutSubviews() { + super.layoutSubviews() + updateMask() + } +} + +// MARK: - Setup helpers +private extension SSFadingScrollView { + func setDefaults() { + fadeAxis = .vertical + fadeLeadingEdge = true + fadeTrailingEdge = true + fadeSize = SSDefaultFadeSize + fadeDuration = SSDefaultFadeDuration + maskScrollBars = true + } + + func setupMaskLayer() -> CALayer { + let maskLayer = CALayer() + maskLayer.frame = bounds + + gradientLayer = setupGradientLayer() + maskLayer.addSublayer(gradientLayer) + + if maskScrollBars { + maskLayer.addSublayer(verticalScrollBarLayer) + maskLayer.addSublayer(horizontalScrollBarLayer) + } + + layer.mask = maskLayer + + return maskLayer + } + + func setupVerticalScrollBarLayer() -> CALayer { + findScrollBars() + return scrollBar(with: verticalScrollBar?.frame ?? .zero) + } + + func setupHorizontalScrollBarLayer() -> CALayer { + findScrollBars() + return scrollBar(with: horizontalScrollBar?.frame ?? .zero) + } + + func setupGradientLayer() -> CAGradientLayer { + let gradientLayer = CAGradientLayer() + gradientLayer.frame = self.bounds + gradientLayer.frame.origin = .zero + + var colors: [CGColor] = [] + var locations: [NSNumber] = [] + + if fadeLeadingEdge { + colors = [transparentColor, opaqueColor] + locations = [NSNumber(value: 0), NSNumber(value: percentageForFadeSize)] + } + + if fadeTrailingEdge { + colors = colors + [opaqueColor, transparentColor] + locations = locations + [NSNumber(value: 1.0 - percentageForFadeSize), NSNumber(value: 1)] + } + + gradientLayer.colors = colors + gradientLayer.locations = locations + + gradientLayer.startPoint = isVertical ? CGPoint(x: 0.5, y: 0.0) : CGPoint(x: 0.0, y: 0.5) + gradientLayer.endPoint = isVertical ? CGPoint(x: 0.5, y: 1.0) : CGPoint(x: 1.0, y: 0.5) + + return gradientLayer + } +} + +// MARK: - Update helpers +private extension SSFadingScrollView { + func updateMask() { + CATransaction.begin() + CATransaction.setDisableActions(true) + maskLayer.frame = bounds + CATransaction.commit() + + updateGradients() + updateScrollBarMasks() + } + + func updateLeadingFade(_ contentOffset: Int) { + if !leadingGradientIsHidden && contentOffset <= 0 { + animateLeadingGradient(to: opaqueColor) // fade out + } else if leadingGradientIsHidden && contentOffset > 0 { + animateLeadingGradient(to: transparentColor) // fade in + } + } + + func updateTrailingFade(_ contentOffset: Int) { + let maxContentOffset = isVertical ? Float(contentSize.height - bounds.height) : Float(contentSize.width - bounds.width) + + if !trailingGradientIsHidden && contentOffset >= Int(roundf(maxContentOffset)) { + animateTrailingGradient(to: opaqueColor) + } else if trailingGradientIsHidden && contentOffset < Int(roundf(maxContentOffset)) { + animateTrailingGradient(to: transparentColor) + } + } + + func updateGradients() { + gradientLayer.frame = maskLayer.bounds + let contentOffset = Int(roundf(Float(isVertical ? self.contentOffset.y : self.contentOffset.x))) + + if fadeLeadingEdge { + updateLeadingFade(contentOffset) + } + if fadeTrailingEdge { + updateTrailingFade(contentOffset) + } + } + + func updateScrollBarMasks() { + guard maskScrollBars else { return } + guard let verticalScrollBar = verticalScrollBar, + let horizontalScrollBar = horizontalScrollBar else { return } + + CATransaction.begin() + CATransaction.setDisableActions(true) + + let verticalScrollBarFrame = layer.convert(verticalScrollBar.frame, to: maskLayer) + verticalScrollBarLayer.frame = verticalScrollBarFrame + verticalScrollBarLayer.opacity = Float(verticalScrollBar.alpha) + + let horizontalScrollBarFrame = layer.convert(horizontalScrollBar.frame, to: maskLayer) + horizontalScrollBarLayer.frame = horizontalScrollBarFrame + horizontalScrollBarLayer.opacity = Float(horizontalScrollBar.alpha) + + CATransaction.commit() + } +} + +// MARK: - ScrollBars +extension SSFadingScrollView { + func scrollBar(with frame: CGRect) -> CALayer { + let scrollBarLayer = CALayer() + scrollBarLayer.backgroundColor = opaqueColor + scrollBarLayer.frame = frame + + return scrollBarLayer + } + + func isScrollBar(_ dimension: CGFloat) -> Bool { + return dimension == 3.5 || dimension == 2.5 || ((dimension) < 2.4 && (dimension ) > 2.3) + } + + func findScrollBars() { + subviews + .filter { ($0 is UIImageView) && $0.tag == 0 } + .compactMap { $0 as? UIImageView } + .forEach { imageView in + if isScrollBar(imageView.frame.size.width) { + verticalScrollBar = imageView + } else if isScrollBar(imageView.frame.size.height) { + horizontalScrollBar = imageView + } + } + } +} + +// MARK: - Properties +private extension SSFadingScrollView { + var isVertical: Bool { + return fadeAxis == .vertical + } + + var leadingGradientIsHidden: Bool { + let firstColor = gradientLayer.colors?.first as! CGColor + return firstColor == opaqueColor + } + + var trailingGradientIsHidden: Bool { + let lastColor = gradientLayer.colors?.last as! CGColor + return lastColor == opaqueColor + } + + var opaqueColor: CGColor { + return UIColor.black.cgColor + } + + var transparentColor: CGColor { + return UIColor.clear.cgColor + } + + var percentageForFadeSize: Float { + let size = isVertical ? bounds.height : bounds.width + + if size <= 0 { + return 0 + } + + let maxFadePercentage = (fadeLeadingEdge && fadeTrailingEdge) ? Float(0.5) : Float(1.0) + return fminf(Float(fadeSize / size), maxFadePercentage) + } +} + +// MARK: - Gradient animation +private extension SSFadingScrollView { + func animateLeadingGradient(to color: CGColor) { + let colors = colorsWithReplacement(at: 0, with: color) + animateGradientColors(colors) + } + + func animateTrailingGradient(to color: CGColor) { + guard let endIndex = gradientLayer.colors?.endIndex else { return } + + let lastIndex = endIndex - 1 + let colors = colorsWithReplacement(at: lastIndex, with: color) + animateGradientColors(colors) + } + + func colorsWithReplacement(at index: Int, with color: CGColor) -> [CGColor] { + var mutableColors = gradientLayer.colors as! [CGColor] + mutableColors[index] = color + + return mutableColors + } + + func animateGradientColors(_ colors: [CGColor]) { + let animation = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.colors)) + animation.fromValue = (gradientLayer.presentation())?.colors + animation.toValue = colors + animation.duration = fadeDuration + animation.timingFunction = CAMediaTimingFunction(name: .easeOut) + + CATransaction.begin() + CATransaction.setDisableActions(true) + gradientLayer.colors = colors // update the model value + CATransaction.commit() + + gradientLayer.add(animation, forKey: "animateGradient") + } +} diff --git a/SSFadingScrollViewDemo/en.lproj/MainStoryboard.storyboard b/SSFadingScrollViewDemo/Base.lproj/MainStoryboard.storyboard similarity index 92% rename from SSFadingScrollViewDemo/en.lproj/MainStoryboard.storyboard rename to SSFadingScrollViewDemo/Base.lproj/MainStoryboard.storyboard index 110c56e..19a65ec 100644 --- a/SSFadingScrollViewDemo/en.lproj/MainStoryboard.storyboard +++ b/SSFadingScrollViewDemo/Base.lproj/MainStoryboard.storyboard @@ -1,9 +1,12 @@ - - + + + + + - - + + @@ -11,26 +14,26 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -127,14 +130,14 @@ - + - - + + - + @@ -174,7 +177,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -188,7 +191,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -199,11 +202,11 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + - - + + @@ -242,7 +245,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -257,7 +260,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -265,7 +268,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -275,7 +278,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -286,14 +289,14 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + - - + + @@ -365,26 +368,26 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + - - + + - + - + - + @@ -403,16 +406,16 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - - - + + + - + @@ -426,7 +429,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + diff --git a/SSFadingScrollViewDemo/LaunchScreen.storyboard b/SSFadingScrollViewDemo/LaunchScreen.storyboard index d29eb3e..6bec512 100644 --- a/SSFadingScrollViewDemo/LaunchScreen.storyboard +++ b/SSFadingScrollViewDemo/LaunchScreen.storyboard @@ -1,9 +1,12 @@ - - + + + + + - - + + @@ -15,39 +18,37 @@ - + - + - - + + - - + + - +