├── HyParallaxCurveHeaderViewDemo
├── Assets.xcassets
│ ├── Contents.json
│ ├── 11381801.imageset
│ │ ├── 11381801.png
│ │ ├── 11381801@2x.png
│ │ ├── 11381801@3x.png
│ │ └── Contents.json
│ ├── icon_refuse.imageset
│ │ ├── icon_refuse@2x.png
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── preview.gif
├── ViewController.h
├── TestViews.h
├── AppDelegate.h
├── main.m
├── HyParallaxCurveHeaderViewClass
│ ├── UIImage+ImageEffects.h
│ ├── HyParallaxCurveHeaderView.h
│ ├── HyParallaxCurveHeaderView.m
│ └── UIImage+ImageEffects.m
├── Info.plist
├── Base.lproj
│ ├── Main.storyboard
│ └── LaunchScreen.storyboard
├── TestViews.m
├── AppDelegate.m
├── ViewController.m
└── TestViews.xib
├── HyParallaxCurveHeaderViewDemo.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcuserdata
│ └── Hy_Mac.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── HyParallaxCurveHeaderViewDemo.xcscheme
└── project.pbxproj
├── Podfile
├── HyParallaxCurveHeaderViewClass
├── UIImage+ImageEffects.h
├── HyParallaxCurveHeaderView.h
├── HyParallaxCurveHeaderView.m
└── UIImage+ImageEffects.m
├── HyParallaxCurveHeaderViewDemoTests
├── Info.plist
└── HyParallaxCurveHeaderViewDemoTests.m
├── HyParallaxCurveHeaderViewDemoUITests
├── Info.plist
└── HyParallaxCurveHeaderViewDemoUITests.m
├── README.md
└── HyParallaxCurveHeaderView.podspec
/HyParallaxCurveHeaderViewDemo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wwdc14yh/HyParallaxCurveHeaderView/HEAD/HyParallaxCurveHeaderViewDemo/preview.gif
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/Assets.xcassets/11381801.imageset/11381801.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wwdc14yh/HyParallaxCurveHeaderView/HEAD/HyParallaxCurveHeaderViewDemo/Assets.xcassets/11381801.imageset/11381801.png
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/Assets.xcassets/11381801.imageset/11381801@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wwdc14yh/HyParallaxCurveHeaderView/HEAD/HyParallaxCurveHeaderViewDemo/Assets.xcassets/11381801.imageset/11381801@2x.png
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/Assets.xcassets/11381801.imageset/11381801@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wwdc14yh/HyParallaxCurveHeaderView/HEAD/HyParallaxCurveHeaderViewDemo/Assets.xcassets/11381801.imageset/11381801@3x.png
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/Assets.xcassets/icon_refuse.imageset/icon_refuse@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wwdc14yh/HyParallaxCurveHeaderView/HEAD/HyParallaxCurveHeaderViewDemo/Assets.xcassets/icon_refuse.imageset/icon_refuse@2x.png
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // HyParallaxCurveHeaderViewDemo
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 @Hy. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/TestViews.h:
--------------------------------------------------------------------------------
1 | //
2 | // TestViews.h
3 | // TableViewCurveHeaderView
4 | //
5 | // Created by Hy_Mac on 16/8/26.
6 | // Copyright © 2016年 Hy. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TestViews : UIView
12 |
13 | + (_Nonnull instancetype)loadXib;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // HyParallaxCurveHeaderViewDemo
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 @Hy. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // HyParallaxCurveHeaderViewDemo
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 @Hy. 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 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/Assets.xcassets/icon_refuse.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "icon_refuse@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | platform :ios, ‘7.0’
3 | inhibit_all_warning!
4 |
5 |
6 | target 'HyParallaxCurveHeaderViewDemo' do
7 |
8 | end
9 |
10 | target 'HyParallaxCurveHeaderViewDemoTests' do
11 |
12 | end
13 |
14 | target 'HyParallaxCurveHeaderViewDemoUITests' do
15 |
16 | end
17 |
18 | pod repo add master https://gitcafe.com/akuandev/Specs.git;
19 | Cloning spec repo `master` from `https://gitcafe.com/akuandev/Specs.git`
20 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/Assets.xcassets/11381801.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "11381801.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "11381801@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "11381801@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewClass/UIImage+ImageEffects.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+ImageEffects.h
3 | // Inkling
4 | //
5 | // Created by Aaron Pang on 3/26/14.
6 | // Copyright (c) 2014 Inkling. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (ImageEffects)
12 |
13 | - (UIImage *)applySubtleEffect;
14 | - (UIImage *)applyLightEffect;
15 | - (UIImage *)applyExtraLightEffect;
16 | - (UIImage *)applyDarkEffect;
17 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;
18 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/HyParallaxCurveHeaderViewClass/UIImage+ImageEffects.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+ImageEffects.h
3 | // Inkling
4 | //
5 | // Created by Aaron Pang on 3/26/14.
6 | // Copyright (c) 2014 Inkling. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (ImageEffects)
12 |
13 | - (UIImage *)applySubtleEffect;
14 | - (UIImage *)applyLightEffect;
15 | - (UIImage *)applyExtraLightEffect;
16 | - (UIImage *)applyDarkEffect;
17 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;
18 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemoTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemoUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo.xcodeproj/xcuserdata/Hy_Mac.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | HyParallaxCurveHeaderViewDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 7A9FD10A1D7432B200156442
16 |
17 | primary
18 |
19 |
20 | 7A9FD1231D7432B200156442
21 |
22 | primary
23 |
24 |
25 | 7A9FD12E1D7432B200156442
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/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 | }
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemoTests/HyParallaxCurveHeaderViewDemoTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // HyParallaxCurveHeaderViewDemoTests.m
3 | // HyParallaxCurveHeaderViewDemoTests
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 @Hy. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HyParallaxCurveHeaderViewDemoTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation HyParallaxCurveHeaderViewDemoTests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | }
21 |
22 | - (void)tearDown {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | [super tearDown];
25 | }
26 |
27 | - (void)testExample {
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 0.0.1
19 | CFBundleVersion
20 | 0.0.1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewClass/HyParallaxCurveHeaderView.h:
--------------------------------------------------------------------------------
1 | //
2 | // HyParallaxCurveHeaderView.h
3 | // TableViewCurveHeaderView
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 Hy. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HyParallaxCurveHeaderView : UIView
12 |
13 |
14 | /**
15 | * 弧度;
16 | 默认 0.7f;
17 | 取值范围(0.0f ~ 1.0f)
18 | */
19 | @property (nonatomic) CGFloat curveFloat;
20 |
21 | /**
22 | * 是否设置推荐弧度(为YES"curveFloat"属性失效)
23 | 默认 NO
24 | 取值范围(YES ~ NO)
25 | */
26 | @property (nonatomic) BOOL suggestCurve;
27 |
28 | /**
29 | * 曲面颜色
30 | */
31 | @property (nonatomic, strong, nonnull) UIColor *curveColor;
32 |
33 | /**
34 | * 背景颜色
35 | */
36 | @property (nonatomic, strong, nonnull) UIColor *backgroundColor;
37 |
38 | /**
39 | * ...
40 | */
41 | @property (nonatomic) CGFloat POINT_Y1;
42 |
43 | @property (nonatomic) CGFloat imageWidth;
44 |
45 | @property (nonatomic, nonnull, strong, readonly) UIView *followBottomView;
46 |
47 | @property (nonatomic, nonnull, strong, readonly) UIImageView *imageView;
48 |
49 | @property (nonatomic, strong, nonnull) UIColor *blurTintColor;
50 |
51 | @property (assign, nonatomic) BOOL isShowBlur;
52 |
53 | @property (assign, nonatomic) BOOL isParallax;
54 |
55 | - (void) layoutHeaderViewForScrollViewOffset:(CGPoint)offset;
56 |
57 | + (_Nonnull instancetype)loadHeaderCurveViewWithSize:(CGSize)size;
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/HyParallaxCurveHeaderViewClass/HyParallaxCurveHeaderView.h:
--------------------------------------------------------------------------------
1 | //
2 | // HyParallaxCurveHeaderView.h
3 | // TableViewCurveHeaderView
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 Hy. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HyParallaxCurveHeaderView : UIView
12 |
13 |
14 | /**
15 | * 弧度;
16 | 默认 0.7f;
17 | 取值范围(0.0f ~ 1.0f)
18 | */
19 | @property (nonatomic) CGFloat curveFloat;
20 |
21 | /**
22 | * 是否设置推荐弧度(为YES"curveFloat"属性失效)
23 | 默认 NO
24 | 取值范围(YES ~ NO)
25 | */
26 | @property (nonatomic) BOOL suggestCurve;
27 |
28 | /**
29 | * 曲面颜色
30 | */
31 | @property (nonatomic, strong, nonnull) UIColor *curveColor;
32 |
33 | /**
34 | * 背景颜色
35 | */
36 | @property (nonatomic, strong, nonnull) UIColor *backgroundColor;
37 |
38 | /**
39 | * ...
40 | */
41 | @property (nonatomic) CGFloat POINT_Y1;
42 |
43 | @property (nonatomic) CGFloat imageWidth;
44 |
45 | @property (nonatomic, nonnull, strong, readonly) UIView *followBottomView;
46 |
47 | @property (nonatomic, nonnull, strong, readonly) UIImageView *imageView;
48 |
49 | @property (nonatomic, strong, nonnull) UIColor *blurTintColor;
50 |
51 | @property (assign, nonatomic) BOOL isShowBlur;
52 |
53 | @property (assign, nonatomic) BOOL isParallax;
54 |
55 | - (void) layoutHeaderViewForScrollViewOffset:(CGPoint)offset;
56 |
57 | + (_Nonnull instancetype)loadHeaderCurveViewWithSize:(CGSize)size;
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemoUITests/HyParallaxCurveHeaderViewDemoUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // HyParallaxCurveHeaderViewDemoUITests.m
3 | // HyParallaxCurveHeaderViewDemoUITests
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 @Hy. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HyParallaxCurveHeaderViewDemoUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation HyParallaxCurveHeaderViewDemoUITests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 |
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 |
22 | // In UI tests it is usually best to stop immediately when a failure occurs.
23 | self.continueAfterFailure = NO;
24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
25 | [[[XCUIApplication alloc] init] launch];
26 |
27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
28 | }
29 |
30 | - (void)tearDown {
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | [super tearDown];
33 | }
34 |
35 | - (void)testExample {
36 | // Use recording to get started writing UI tests.
37 | // Use XCTAssert and related functions to verify your tests produce the correct results.
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/TestViews.m:
--------------------------------------------------------------------------------
1 | //
2 | // TestViews.m
3 | // TableViewCurveHeaderView
4 | //
5 | // Created by Hy_Mac on 16/8/26.
6 | // Copyright © 2016年 Hy. All rights reserved.
7 | //
8 |
9 | #import "TestViews.h"
10 |
11 | @interface TestViews ()
12 | @property (weak, nonatomic) IBOutlet UIButton *button0;
13 | @property (weak, nonatomic) IBOutlet UIButton *button1;
14 | @property (weak, nonatomic) IBOutlet UIButton *button2;
15 |
16 | @end
17 |
18 | @implementation TestViews
19 |
20 | - (void)awakeFromNib
21 | {
22 | [super awakeFromNib];
23 | _button0.layer.cornerRadius = 15.f;
24 | _button0.layer.borderColor = [UIColor colorWithRed:62.f/255.f green:177.f/255.f blue:251.f/255.f alpha:1].CGColor;
25 | _button0.layer.borderWidth = 1.f/2.f;
26 |
27 | _button1.layer.cornerRadius = 15.f;
28 | _button1.layer.borderColor = [UIColor colorWithRed:62.f/255.f green:177.f/255.f blue:251.f/255.f alpha:1].CGColor;
29 | _button1.layer.borderWidth = 1.f/2.f;
30 |
31 | _button2.layer.cornerRadius = 15.f;
32 | _button2.layer.borderColor = [UIColor colorWithRed:252.f/255.f green:183.f/255.f blue:66.f/255.f alpha:1].CGColor;
33 | _button2.layer.borderWidth = 1.f;
34 |
35 | }
36 |
37 | + (_Nonnull instancetype)loadXib
38 | {
39 | // Instantiate the nib content without any reference to it.
40 | NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:@"TestViews" owner:nil options:nil];
41 |
42 | // Find the view among nib contents (not too hard assuming there is only one view in it).
43 | return [nibContents lastObject];
44 | }
45 |
46 | /*
47 | // Only override drawRect: if you perform custom drawing.
48 | // An empty implementation adversely affects performance during animation.
49 | - (void)drawRect:(CGRect)rect {
50 | // Drawing code
51 | }
52 | */
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // HyParallaxCurveHeaderViewDemo
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 @Hy. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 |
36 | - (void)applicationWillEnterForeground:(UIApplication *)application {
37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
38 | }
39 |
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43 | }
44 |
45 |
46 | - (void)applicationWillTerminate:(UIApplication *)application {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | #HyParallaxCurveHeaderView
3 | -------------
4 | [](https://developer.apple.com/iphone/index.action)
6 | [](https://developer.apple.com/Objective-C)
7 | [](http://mit-license.org)
8 | > 关于**HyParallaxCurveHeaderView**灵感来自于[智联招聘App]()
9 |
10 | ####示例:
11 |
12 | 
13 |
14 | ###原理说明
15 | 1.采用贝塞尔曲线绘制曲线视图具体看`- (void)drawRect:(CGRect)rect`方法
16 |
17 |
18 | ### 下载安装
19 | 将下载好的项目提取以下类托入项目中
20 | `UIImage+ImageEffects.h/.m`
21 | `HyParallaxCurveHeaderView.h/.m`
22 | 将`HyParallaxCurveHeaderView.h`import
23 |
24 | ### Podfile
25 | 使用`Podfile`进行代码集成,详情看下面
26 |
27 | 打开`Podfile`添加以下代码
28 |
29 | `pod 'HyParallaxCurveHeaderView', :git => 'https://github.com/wwdc14/HyParallaxCurveHeaderView.git'`
30 |
31 | 保存->`pod install`
32 |
33 | ###使用方法
34 |
35 | 实例`HyParallaxCurveHeaderView`
36 | ```obj
37 | HyParallaxCurveHeaderView *curveHeaderView = [HyParallaxCurveHeaderView loadHeaderCurveViewWithSize:CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds), 300)];
38 | _tableView.tableHeaderView = curveHeaderView;
39 | ```
40 |
41 | ###属性以及方法说明
42 | * 属性
43 |
44 | `@property (nonatomic) CGFloat curveFloat` 曲线弧度取值范围0.0~1.0
45 |
46 | `@property (nonatomic) BOOL suggestCurve` 是否设置推荐弧度(为YES"curveFloat"属性失效)
47 |
48 | `@property (nonatomic, strong, nonnull) UIColor *curveColor` 曲面颜色
49 |
50 | `@property (nonatomic, strong, nonnull) UIColor *backgroundColor` 背景颜色
51 |
52 | `@property (nonatomic) CGFloat imageWidth` imageView宽度
53 |
54 | `@property (nonatomic, nonnull, strong, readonly) UIView *followBottomView` 跟随底部View
55 |
56 | `@property (nonatomic, nonnull, strong, readonly) UIImageView *imageView` imageView
57 |
58 | `@property (nonatomic, strong, nonnull) UIColor *blurTintColor` 模糊颜色
59 |
60 | `@property (assign, nonatomic) BOOL isShowBlur` 是否显示模糊
61 |
62 | `@property (assign, nonatomic) BOOL isParallax` 是否具有视差效果
63 |
64 | * 函数
65 |
66 | `- (void) layoutHeaderViewForScrollViewOffset:(CGPoint)offset` 实现下拉改变曲面重要方法(必须调用)
67 |
68 | `+ (_Nonnull instancetype)loadHeaderCurveViewWithSize:(CGSize)size` 初始化方法
69 |
70 | ### 注意事项
71 |
72 | * 非常感谢[Vinodh-G](https://github.com/Vinodh-G/ParallaxTableViewHeader)开源的`ParallaxTableViewHeader`三方库提供滑动视差效果.
73 |
74 | ### 期待
75 | * 如果在使用过程中遇到BUG,希望你能Issues我
76 | * 如果觉得好用请Star!
77 |
78 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // HyParallaxCurveHeaderViewDemo
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 @Hy. All rights reserved.
7 | //
8 |
9 | #import "TestViews.h"
10 | #import "ViewController.h"
11 | #import "HyParallaxCurveHeaderView.h"
12 |
13 | @interface ViewController ()
14 | @property (nullable, nonatomic, assign)UITableView *tableView;
15 | @end
16 |
17 | @implementation ViewController
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 | // Do any additional setup after loading the view, typically from a nib.
22 | {
23 | UITableView *tableView = [UITableView new];
24 | _tableView = tableView;
25 | _tableView.frame = [UIScreen mainScreen].bounds;
26 | [self.view addSubview:_tableView];
27 | _tableView.delegate = self;
28 | _tableView.dataSource = self;
29 |
30 | HyParallaxCurveHeaderView *curveHeaderView = [HyParallaxCurveHeaderView loadHeaderCurveViewWithSize:CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds), 300)];
31 | curveHeaderView.imageView.image = [UIImage imageNamed:@"11381801"];
32 | curveHeaderView.curveFloat = 140.f/300.f;
33 | curveHeaderView.POINT_Y1 = 160.f/300.f;
34 | curveHeaderView.suggestCurve = false;
35 | curveHeaderView.curveColor = [UIColor whiteColor];
36 | curveHeaderView.backgroundColor = [UIColor colorWithRed:69.f/255.f green:168.f/255.f blue:244.f/255.f alpha:1];
37 | curveHeaderView.blurTintColor = [UIColor colorWithRed:69.f/255.f green:168.f/255.f blue:244.f/255.f alpha:0.2f];
38 |
39 | TestViews *views = [TestViews loadXib];
40 | views.backgroundColor = [UIColor clearColor];
41 | views.frame = CGRectMake(0, 0, CGRectGetWidth(curveHeaderView.followBottomView.frame), CGRectGetHeight(curveHeaderView.followBottomView.frame));
42 | [curveHeaderView.followBottomView addSubview:views];
43 | _tableView.tableHeaderView = curveHeaderView;
44 | }
45 | }
46 |
47 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
48 | {
49 | return 100;
50 | }
51 |
52 | // Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
53 | // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
54 |
55 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
56 | {
57 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
58 | if (!cell) {
59 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"];
60 | }
61 | cell.textLabel.text = [NSString stringWithFormat:@"%zd",indexPath.row];
62 | return cell;
63 | }
64 |
65 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView
66 | {
67 | [(HyParallaxCurveHeaderView *)self.tableView.tableHeaderView layoutHeaderViewForScrollViewOffset:scrollView.contentOffset];
68 | }
69 |
70 | - (BOOL)prefersStatusBarHidden
71 | {
72 | return true;
73 | }
74 |
75 | - (void)didReceiveMemoryWarning {
76 | [super didReceiveMemoryWarning];
77 | // Dispose of any resources that can be recreated.
78 | }
79 |
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo.xcodeproj/xcuserdata/Hy_Mac.xcuserdatad/xcschemes/HyParallaxCurveHeaderViewDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderView.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod spec lint HyParallaxCurveHeaderView.podspec' to ensure this is a
3 | # valid spec and to remove all comments including this before submitting the spec.
4 | #
5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
7 | #
8 |
9 | Pod::Spec.new do |s|
10 |
11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
12 | #
13 | # These will help people to find your library, and whilst it
14 | # can feel like a chore to fill in it's definitely to your advantage. The
15 | # summary should be tweet-length, and the description more in depth.
16 | #
17 |
18 | s.name = "HyParallaxCurveHeaderView"
19 | s.version = "0.0.2"
20 | s.summary = "A short description of HyParallaxCurveHeaderView."
21 |
22 | s.description = <<-DESC
23 | A longer description of HyParallaxCurveHeaderView in Markdown format.
24 |
25 | * Think: Why did you write this? What is the focus? What does it do?
26 | * CocoaPods will be using this to generate tags, and improve search results.
27 | * Try to keep it short, snappy and to the point.
28 | * Finally, don't worry about the indent, CocoaPods strips it!
29 | DESC
30 |
31 | s.homepage = "https://github.com/wwdc14/HyParallaxCurveHeaderView"
32 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
33 |
34 |
35 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
36 | #
37 | # Licensing your code is important. See http://choosealicense.com for more info.
38 | # CocoaPods will detect a license file if there is a named LICENSE*
39 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
40 | #
41 |
42 | s.license = "MIT (example)"
43 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" }
44 |
45 |
46 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
47 | #
48 | # Specify the authors of the library, with email addresses. Email addresses
49 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
50 | # accepts just a name if you'd rather not provide an email address.
51 | #
52 | # Specify a social_media_url where others can refer to, for example a twitter
53 | # profile URL.
54 | #
55 |
56 | s.author = { "Hy_Mac" => "wwdc14@vip.qq.com" }
57 | # Or just: s.author = "Hy_Mac"
58 | # s.authors = { "Hy_Mac" => "" }
59 | # s.social_media_url = "http://twitter.com/Hy_Mac"
60 |
61 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
62 | #
63 | # If this Pod runs only on iOS or OS X, then specify the platform and
64 | # the deployment target. You can optionally include the target after the platform.
65 | #
66 |
67 | #s.platform = :ios
68 | s.platform = :ios, "6.0"
69 |
70 | # When using multiple platforms
71 | s.ios.deployment_target = "6.0"
72 | # s.osx.deployment_target = "10.7"
73 | # s.watchos.deployment_target = "2.0"
74 |
75 |
76 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
77 | #
78 | # Specify the location from where the source should be retrieved.
79 | # Supports git, hg, bzr, svn and HTTP.
80 | #
81 |
82 | s.source = { :git => "https://github.com/wwdc14/HyParallaxCurveHeaderView.git", :tag => "0.0.1" }
83 |
84 |
85 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
86 | #
87 | # CocoaPods is smart about how it includes source code. For source files
88 | # giving a folder will include any swift, h, m, mm, c & cpp files.
89 | # For header files it will include any header in the folder.
90 | # Not including the public_header_files will make all headers public.
91 | #
92 |
93 | s.source_files = 'HyParallaxCurveHeaderViewClass/**/*.{h,m}'
94 | #s.exclude_files = ""
95 |
96 | # s.public_header_files = "HyParallaxCurveHeaderViewClass/**/*.h"
97 |
98 |
99 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
100 | #
101 | # A list of resources included with the Pod. These are copied into the
102 | # target bundle with a build phase script. Anything else will be cleaned.
103 | # You can preserve files from being cleaned, please don't preserve
104 | # non-essential files like tests, examples and documentation.
105 | #
106 |
107 | # s.resource = "icon.png"
108 | # s.resources = "Resources/*.png"
109 |
110 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave"
111 |
112 |
113 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
114 | #
115 | # Link your library with frameworks, or libraries. Libraries do not include
116 | # the lib prefix of their name.
117 | #
118 |
119 | # s.framework = "SomeFramework"
120 | # s.frameworks = "SomeFramework", "AnotherFramework"
121 |
122 | # s.library = "iconv"
123 | # s.libraries = "iconv", "xml2"
124 |
125 |
126 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
127 | #
128 | # If your library depends on compiler flags you can set them in the xcconfig hash
129 | # where they will only apply to your library. If you depend on other Podspecs
130 | # you can include multiple dependencies to ensure it works.
131 |
132 | # s.requires_arc = true
133 |
134 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
135 | # s.dependency "JSONKit", "~> 1.4"
136 |
137 | end
138 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/TestViews.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
23 |
31 |
41 |
50 |
59 |
68 |
77 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewClass/HyParallaxCurveHeaderView.m:
--------------------------------------------------------------------------------
1 | //
2 | // HyParallaxCurveHeaderView.m
3 | // TableViewCurveHeaderView
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 Hy. All rights reserved.
7 | //
8 |
9 | #import "HyParallaxCurveHeaderView.h"
10 | #import "UIImage+ImageEffects.h"
11 |
12 | @interface HyHeaderCurveView : UIView
13 | @property (nonatomic) CGFloat POINT_Y1;
14 | @property (nonatomic) BOOL suggestCurve;
15 | @property (nonatomic) CGFloat imageWidth;
16 | @property (nonatomic) CGFloat curveFloat;
17 | @property (nonatomic, strong, nonnull) UIColor *curveColor;
18 | @property (nonatomic, strong, nonnull) UIColor *backgroundColor;
19 | @property (nonatomic, nonnull, strong, readonly) UIView *followBottomView;
20 | @property (nonatomic, nonnull, strong, readonly) UIImageView *imageView;
21 | @property (nonnull, nonatomic, strong) UIBezierPath* rectanglePath;
22 | @property (nonnull, nonatomic, strong) UIBezierPath* bezierPath;
23 | @property (nonnull, nonatomic, strong) CAShapeLayer* shapeLayer;
24 | @end
25 |
26 | #define w [UIScreen mainScreen].bounds.size.width
27 | #define MAX_Y CGRectGetMaxY(self.frame)
28 | #define MARGIN 70
29 |
30 | @implementation HyHeaderCurveView
31 |
32 | - (instancetype) init
33 | {
34 | self = [super init];
35 | if (self) {
36 | [self initUI];
37 | }
38 | return self;
39 | }
40 |
41 | - (instancetype) initWithFrame:(CGRect)frame
42 | {
43 | self = [super initWithFrame:frame];
44 | if (self) {
45 | [self initUI];
46 | }
47 | return self;
48 | }
49 |
50 | - (void)initUI
51 | {
52 |
53 | _bezierPath = [UIBezierPath bezierPath];
54 | {
55 | _shapeLayer = [CAShapeLayer layer];
56 | [self.layer addSublayer:_shapeLayer];
57 | _shapeLayer.frame = self.frame;
58 | }
59 | _bezierPath = [UIBezierPath bezierPath];
60 | _curveFloat = 0.48f;
61 | _POINT_Y1 = 0.0f;
62 | _suggestCurve = false;
63 | {
64 | _followBottomView = [self viewWithTag:1000];
65 | if (!_followBottomView) {
66 | _followBottomView = [UIView new];
67 | [self addSubview:_followBottomView];
68 | _followBottomView.tag = 1000;
69 | }
70 | }
71 |
72 | {
73 | _imageWidth = 60;
74 | _imageView = [[UIImageView alloc] init];
75 | _imageView.tag = 1001;
76 | _imageView.contentMode = UIViewContentModeScaleAspectFill;
77 | [self addSubview:_imageView];
78 | _imageView.layer.masksToBounds = true;
79 | _imageView.layer.borderWidth = 2.f;
80 | _imageView.layer.borderColor = [UIColor whiteColor].CGColor;
81 | _imageView.layer.cornerRadius = _imageWidth/2;
82 | }
83 | }
84 |
85 | - (void)setImageWidth:(CGFloat)imageWidth
86 | {
87 | _imageWidth = imageWidth;
88 | _imageView.layer.cornerRadius = _imageWidth/2;
89 | _imageView.frame = CGRectMake(_imageView.frame.origin.x,
90 | _imageView.frame.origin.y,
91 | _imageWidth,
92 | _imageWidth);
93 | }
94 |
95 | - (void)setCurveColor:(UIColor *)curveColor
96 | {
97 | _curveColor = curveColor;
98 | _shapeLayer.fillColor = _curveColor.CGColor;
99 | }
100 |
101 | - (void)setBackgroundColor:(UIColor *)backgroundColor
102 | {
103 | _backgroundColor = backgroundColor;
104 | _shapeLayer.backgroundColor = _backgroundColor.CGColor;
105 | }
106 |
107 | - (void) setPOINT_Y1:(CGFloat)POINT_Y1
108 | {
109 | //_POINT_Y1 = POINT_Y1;
110 | _POINT_Y1 = POINT_Y1 * CGRectGetHeight(self.frame);
111 | _followBottomView.frame = CGRectMake(0,
112 | _POINT_Y1,
113 | CGRectGetWidth(self.frame),
114 | CGRectGetHeight(self.frame) - _POINT_Y1);
115 | [self setNeedsDisplay];
116 | }
117 |
118 | - (void)setSuggestCurve:(BOOL)suggestCurve
119 | {
120 | _suggestCurve = suggestCurve;
121 | if (_suggestCurve) {
122 | [self setPOINT_Y1:(CGRectGetMidY(self.frame)/2)/CGRectGetMidY(self.frame)];
123 | }
124 | }
125 |
126 | - (void)setFrame:(CGRect)frame
127 | {
128 | [super setFrame:frame];
129 | _shapeLayer.frame = frame;
130 | [self setNeedsDisplay];
131 | if (_POINT_Y1 == 0.0f) {
132 |
133 | _POINT_Y1 = CGRectGetMidY(frame);
134 | _followBottomView.frame = CGRectMake(0,
135 | _POINT_Y1,
136 | CGRectGetWidth(self.frame),
137 | CGRectGetHeight(self.frame) - CGRectGetMaxY(_imageView.frame));
138 | }
139 | [_followBottomView setFrame:CGRectMake(0,
140 | CGRectGetMaxY(self.frame) - CGRectGetHeight(_followBottomView.frame),
141 | w,
142 | CGRectGetHeight(_followBottomView.frame))];
143 | }
144 |
145 | // Only override drawRect: if you perform custom drawing.
146 | // An empty implementation adversely affects performance during animation.
147 | - (void)drawRect:(CGRect)rect {
148 | [super drawRect:rect];
149 | CGFloat progress = CGRectGetHeight(rect)/CGRectGetHeight([UIScreen mainScreen].bounds);
150 | progress = MAX(progress - 0.3, 0.0f);
151 | CGFloat centerX = CGRectGetMidX(self.frame);
152 | CGFloat point6X = CGRectGetMaxX(self.frame)-MARGIN;
153 | CGFloat dragY = ((_curveFloat * CGRectGetHeight(self.frame)) - (progress*400)) + (progress*400);//速度差值
154 | if (_suggestCurve) {
155 | dragY = (_POINT_Y1 - 85) + (progress*400);
156 | }
157 |
158 | {
159 | _imageView.frame = CGRectMake(centerX - _imageWidth/2,
160 | dragY - _imageWidth/2,
161 | _imageWidth,
162 | _imageWidth);
163 | }
164 |
165 | NSArray *points = @[[NSValue valueWithCGPoint:CGPointMake(0, _POINT_Y1)], //point0
166 | [NSValue valueWithCGPoint:CGPointMake(0, MAX_Y)], //point1
167 | [NSValue valueWithCGPoint:CGPointMake(w, MAX_Y)], //point2
168 | [NSValue valueWithCGPoint:CGPointMake(w, _POINT_Y1)], //point3
169 | [NSValue valueWithCGPoint:CGPointMake(centerX, dragY)], //point4
170 | [NSValue valueWithCGPoint:CGPointMake(w, _POINT_Y1)], //point5
171 | [NSValue valueWithCGPoint:CGPointMake(point6X, dragY)], //point6
172 | [NSValue valueWithCGPoint:CGPointMake(0, _POINT_Y1)], //point7
173 | [NSValue valueWithCGPoint:CGPointMake(MARGIN, dragY)], //point8
174 | [NSValue valueWithCGPoint:CGPointMake(0, _POINT_Y1)] //point9
175 | ];
176 | //标记关键点
177 | // for (NSValue * value in points) {
178 | // NSInteger index = [points indexOfObject:value];
179 | // CGPoint point = [value CGPointValue];
180 | // UILabel *view = [self viewWithTag:index+100];
181 | // if (!view) {
182 | // view = [[UILabel alloc] init];
183 | // view.tag = index+100;
184 | // [self addSubview:view];
185 | // view.backgroundColor = [UIColor redColor];
186 | // view.textAlignment = 1;
187 | // view.clipsToBounds = true;
188 | // }
189 | // view.text = [NSString stringWithFormat:@"%zd",index];
190 | // [view setFrame:CGRectMake(point.x-10/2, point.y-5/2, 10, 10)];
191 | // view.layer.cornerRadius = 10/2;
192 | // view.font = [UIFont systemFontOfSize:10];
193 | // view.textColor = [UIColor whiteColor];
194 | // view.hidden = true;
195 | // }
196 |
197 | // Bezier Drawing
198 | [_bezierPath removeAllPoints];
199 | [_bezierPath moveToPoint: [[points objectAtIndex:0] CGPointValue]];
200 | [_bezierPath addLineToPoint: [[points objectAtIndex:1] CGPointValue]];
201 | [_bezierPath addLineToPoint: [[points objectAtIndex:2] CGPointValue]];
202 | [_bezierPath addLineToPoint: [[points objectAtIndex:3] CGPointValue]];
203 |
204 | [_bezierPath addCurveToPoint: [[points objectAtIndex:4] CGPointValue]
205 | controlPoint1: [[points objectAtIndex:5] CGPointValue]
206 | controlPoint2: [[points objectAtIndex:6] CGPointValue]];
207 |
208 | [_bezierPath addCurveToPoint: [[points objectAtIndex:7] CGPointValue]
209 | controlPoint1: [[points objectAtIndex:8] CGPointValue]
210 | controlPoint2: [[points objectAtIndex:9] CGPointValue]];
211 | _shapeLayer.path = _bezierPath.CGPath;
212 | points = nil;
213 | }
214 |
215 | @end
216 |
217 | @interface HyParallaxCurveHeaderView ()
218 | @property (weak, nonatomic) UIScrollView *scrollView;
219 | @property (weak, nonatomic) HyHeaderCurveView *subView;
220 | @property (nonatomic) UIImageView *bluredImageView;
221 | @property (nonnull, strong, nonatomic) HyHeaderCurveView *curveView;
222 | @end
223 |
224 | #define kDefaultHeaderFrame CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)
225 | static CGFloat kParallaxDeltaFactor = 0.5f;
226 |
227 | @implementation HyParallaxCurveHeaderView
228 |
229 | + (_Nonnull instancetype)loadHeaderCurveViewWithSize:(CGSize)size
230 | {
231 | HyParallaxCurveHeaderView *headerView = [[HyParallaxCurveHeaderView alloc] initWithFrame:(CGRect){CGPointZero,size}];
232 | HyHeaderCurveView *curveView = [[HyHeaderCurveView alloc] initWithFrame:headerView.frame];
233 | headerView.isShowBlur = true;
234 | headerView.isParallax = true;
235 | [headerView initialSetupForCustomSubView:curveView];
236 | return headerView;
237 | }
238 |
239 | - (void)initialSetupForCustomSubView:(HyHeaderCurveView *)subView
240 | {
241 | UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
242 | self.scrollView = scrollView;
243 | self.subView = subView;
244 | _followBottomView = _subView.followBottomView;
245 | _imageView = _subView.imageView;
246 | subView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
247 | [self.scrollView addSubview:subView];
248 |
249 | self.bluredImageView = [[UIImageView alloc] initWithFrame:subView.frame];
250 | self.bluredImageView.autoresizingMask = subView.autoresizingMask;
251 | self.bluredImageView.alpha = 0.0f;
252 | [self.scrollView addSubview:self.bluredImageView];
253 |
254 | [self addSubview:self.scrollView];
255 | if (_isShowBlur) {
256 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
257 | [self refreshBlurView];
258 | });
259 | }
260 | }
261 |
262 | - (void)layoutHeaderViewForScrollViewOffset:(CGPoint)offset
263 | {
264 | CGRect frame = self.scrollView.frame;
265 | if (offset.y > 0)
266 | {
267 | if (_isParallax) {
268 | frame.origin.y = MAX(offset.y *kParallaxDeltaFactor, 0);
269 | }
270 | self.scrollView.frame = frame;
271 | self.bluredImageView.alpha = 1 / kDefaultHeaderFrame.size.height * offset.y * 2;
272 | self.clipsToBounds = YES;
273 | }
274 | else
275 | {
276 | CGFloat delta = 0.0f;
277 | CGRect rect = kDefaultHeaderFrame;
278 | delta = fabs(MIN(0.0f, offset.y));
279 | rect.origin.y -= delta;
280 | rect.size.height += delta;
281 | self.scrollView.frame = rect;
282 | self.clipsToBounds = NO;
283 | self.bluredImageView.alpha = offset.y/kDefaultHeaderFrame.size.height;
284 | }
285 | }
286 |
287 | - (void)refreshBlurView
288 | {
289 | UIImage *screenShot = [self screenShotOfView:self];
290 |
291 | UIColor *color = _blurTintColor;
292 | if (!color) {
293 | color = [UIColor colorWithWhite:0.3 alpha:0.4];
294 | }
295 |
296 | screenShot = [screenShot applyBlurWithRadius:6 tintColor:color saturationDeltaFactor:1.0 maskImage:nil];
297 | self.bluredImageView.image = screenShot;
298 | }
299 |
300 | - (UIImage *)screenShotOfView:(UIView *)view
301 | {
302 | UIGraphicsBeginImageContextWithOptions(kDefaultHeaderFrame.size, YES, 0.0);
303 | [self drawViewHierarchyInRect:kDefaultHeaderFrame afterScreenUpdates:NO];
304 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
305 | UIGraphicsEndImageContext();
306 |
307 | return image;
308 | }
309 |
310 | - (void)setCurveColor:(UIColor *)curveColor
311 | {
312 | _curveColor = curveColor;
313 | _subView.curveColor = curveColor;
314 | }
315 |
316 | - (void)setSuggestCurve:(BOOL)suggestCurve
317 | {
318 | _suggestCurve = suggestCurve;
319 | _subView.suggestCurve = suggestCurve;
320 | }
321 |
322 | - (void)setCurveFloat:(CGFloat)curveFloat
323 | {
324 | _curveFloat = curveFloat;
325 | _subView.curveFloat = curveFloat;
326 | }
327 |
328 | - (void)setBackgroundColor:(UIColor *)backgroundColor
329 | {
330 | _backgroundColor = backgroundColor;
331 | _subView.backgroundColor = backgroundColor;
332 | }
333 |
334 | - (void)setPOINT_Y1:(CGFloat)POINT_Y1
335 | {
336 | _POINT_Y1 = POINT_Y1;
337 | _subView.POINT_Y1 = POINT_Y1;
338 | }
339 |
340 | - (void)setImageWidth:(CGFloat)imageWidth
341 | {
342 | _imageWidth = imageWidth;
343 | _subView.imageWidth = imageWidth;
344 | }
345 |
346 | /*
347 | // Only override drawRect: if you perform custom drawing.
348 | // An empty implementation adversely affects performance during animation.
349 | - (void)drawRect:(CGRect)rect {
350 | // Drawing code
351 | }
352 | */
353 |
354 | @end
355 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/HyParallaxCurveHeaderViewClass/HyParallaxCurveHeaderView.m:
--------------------------------------------------------------------------------
1 | //
2 | // HyParallaxCurveHeaderView.m
3 | // TableViewCurveHeaderView
4 | //
5 | // Created by Hy_Mac on 16/8/29.
6 | // Copyright © 2016年 Hy. All rights reserved.
7 | //
8 |
9 | #import "HyParallaxCurveHeaderView.h"
10 | #import "UIImage+ImageEffects.h"
11 |
12 | @interface HyHeaderCurveView : UIView
13 | @property (nonatomic) CGFloat POINT_Y1;
14 | @property (nonatomic) BOOL suggestCurve;
15 | @property (nonatomic) CGFloat imageWidth;
16 | @property (nonatomic) CGFloat curveFloat;
17 | @property (nonatomic, strong, nonnull) UIColor *curveColor;
18 | @property (nonatomic, strong, nonnull) UIColor *backgroundColor;
19 | @property (nonatomic, nonnull, strong, readonly) UIView *followBottomView;
20 | @property (nonatomic, nonnull, strong, readonly) UIImageView *imageView;
21 | @property (nonnull, nonatomic, strong) UIBezierPath* rectanglePath;
22 | @property (nonnull, nonatomic, strong) UIBezierPath* bezierPath;
23 | @property (nonnull, nonatomic, strong) CAShapeLayer* shapeLayer;
24 | @end
25 |
26 | #define w [UIScreen mainScreen].bounds.size.width
27 | #define MAX_Y CGRectGetMaxY(self.frame)
28 | #define MARGIN 70
29 |
30 | @implementation HyHeaderCurveView
31 |
32 | - (instancetype) init
33 | {
34 | self = [super init];
35 | if (self) {
36 | [self initUI];
37 | }
38 | return self;
39 | }
40 |
41 | - (instancetype) initWithFrame:(CGRect)frame
42 | {
43 | self = [super initWithFrame:frame];
44 | if (self) {
45 | [self initUI];
46 | }
47 | return self;
48 | }
49 |
50 | - (void)initUI
51 | {
52 |
53 | _bezierPath = [UIBezierPath bezierPath];
54 | {
55 | _shapeLayer = [CAShapeLayer layer];
56 | [self.layer addSublayer:_shapeLayer];
57 | _shapeLayer.frame = self.frame;
58 | }
59 | _bezierPath = [UIBezierPath bezierPath];
60 | _curveFloat = 0.48f;
61 | _POINT_Y1 = 0.0f;
62 | _suggestCurve = false;
63 | {
64 | _followBottomView = [self viewWithTag:1000];
65 | if (!_followBottomView) {
66 | _followBottomView = [UIView new];
67 | [self addSubview:_followBottomView];
68 | _followBottomView.tag = 1000;
69 | }
70 | }
71 |
72 | {
73 | _imageWidth = 60;
74 | _imageView = [[UIImageView alloc] init];
75 | _imageView.tag = 1001;
76 | _imageView.contentMode = UIViewContentModeScaleAspectFill;
77 | [self addSubview:_imageView];
78 | _imageView.layer.masksToBounds = true;
79 | _imageView.layer.borderWidth = 2.f;
80 | _imageView.layer.borderColor = [UIColor whiteColor].CGColor;
81 | _imageView.layer.cornerRadius = _imageWidth/2;
82 | }
83 | }
84 |
85 | - (void)setImageWidth:(CGFloat)imageWidth
86 | {
87 | _imageWidth = imageWidth;
88 | _imageView.layer.cornerRadius = _imageWidth/2;
89 | _imageView.frame = CGRectMake(_imageView.frame.origin.x,
90 | _imageView.frame.origin.y,
91 | _imageWidth,
92 | _imageWidth);
93 | }
94 |
95 | - (void)setCurveColor:(UIColor *)curveColor
96 | {
97 | _curveColor = curveColor;
98 | _shapeLayer.fillColor = _curveColor.CGColor;
99 | }
100 |
101 | - (void)setBackgroundColor:(UIColor *)backgroundColor
102 | {
103 | _backgroundColor = backgroundColor;
104 | _shapeLayer.backgroundColor = _backgroundColor.CGColor;
105 | }
106 |
107 | - (void) setPOINT_Y1:(CGFloat)POINT_Y1
108 | {
109 | //_POINT_Y1 = POINT_Y1;
110 | _POINT_Y1 = POINT_Y1 * CGRectGetHeight(self.frame);
111 | _followBottomView.frame = CGRectMake(0,
112 | _POINT_Y1,
113 | CGRectGetWidth(self.frame),
114 | CGRectGetHeight(self.frame) - _POINT_Y1);
115 | [self setNeedsDisplay];
116 | }
117 |
118 | - (void)setSuggestCurve:(BOOL)suggestCurve
119 | {
120 | _suggestCurve = suggestCurve;
121 | if (_suggestCurve) {
122 | [self setPOINT_Y1:(CGRectGetMidY(self.frame)/2)/CGRectGetMidY(self.frame)];
123 | }
124 | }
125 |
126 | - (void)setFrame:(CGRect)frame
127 | {
128 | [super setFrame:frame];
129 | _shapeLayer.frame = frame;
130 | [self setNeedsDisplay];
131 | if (_POINT_Y1 == 0.0f) {
132 |
133 | _POINT_Y1 = CGRectGetMidY(frame);
134 | _followBottomView.frame = CGRectMake(0,
135 | _POINT_Y1,
136 | CGRectGetWidth(self.frame),
137 | CGRectGetHeight(self.frame) - CGRectGetMaxY(_imageView.frame));
138 | }
139 | [_followBottomView setFrame:CGRectMake(0,
140 | CGRectGetMaxY(self.frame) - CGRectGetHeight(_followBottomView.frame),
141 | w,
142 | CGRectGetHeight(_followBottomView.frame))];
143 | }
144 |
145 | // Only override drawRect: if you perform custom drawing.
146 | // An empty implementation adversely affects performance during animation.
147 | - (void)drawRect:(CGRect)rect {
148 | [super drawRect:rect];
149 | CGFloat progress = CGRectGetHeight(rect)/CGRectGetHeight([UIScreen mainScreen].bounds);
150 | progress = MAX(progress - 0.3, 0.0f);
151 | CGFloat centerX = CGRectGetMidX(self.frame);
152 | CGFloat point6X = CGRectGetMaxX(self.frame)-MARGIN;
153 | CGFloat dragY = ((_curveFloat * CGRectGetHeight(self.frame)) - (progress*400)) + (progress*400);//速度差值
154 | if (_suggestCurve) {
155 | dragY = (_POINT_Y1 - 85) + (progress*400);
156 | }
157 |
158 | {
159 | _imageView.frame = CGRectMake(centerX - _imageWidth/2,
160 | dragY - _imageWidth/2,
161 | _imageWidth,
162 | _imageWidth);
163 | }
164 |
165 | NSArray *points = @[[NSValue valueWithCGPoint:CGPointMake(0, _POINT_Y1)], //point0
166 | [NSValue valueWithCGPoint:CGPointMake(0, MAX_Y)], //point1
167 | [NSValue valueWithCGPoint:CGPointMake(w, MAX_Y)], //point2
168 | [NSValue valueWithCGPoint:CGPointMake(w, _POINT_Y1)], //point3
169 | [NSValue valueWithCGPoint:CGPointMake(centerX, dragY)], //point4
170 | [NSValue valueWithCGPoint:CGPointMake(w, _POINT_Y1)], //point5
171 | [NSValue valueWithCGPoint:CGPointMake(point6X, dragY)], //point6
172 | [NSValue valueWithCGPoint:CGPointMake(0, _POINT_Y1)], //point7
173 | [NSValue valueWithCGPoint:CGPointMake(MARGIN, dragY)], //point8
174 | [NSValue valueWithCGPoint:CGPointMake(0, _POINT_Y1)] //point9
175 | ];
176 | //标记关键点
177 | // for (NSValue * value in points) {
178 | // NSInteger index = [points indexOfObject:value];
179 | // CGPoint point = [value CGPointValue];
180 | // UILabel *view = [self viewWithTag:index+100];
181 | // if (!view) {
182 | // view = [[UILabel alloc] init];
183 | // view.tag = index+100;
184 | // [self addSubview:view];
185 | // view.backgroundColor = [UIColor redColor];
186 | // view.textAlignment = 1;
187 | // view.clipsToBounds = true;
188 | // }
189 | // view.text = [NSString stringWithFormat:@"%zd",index];
190 | // [view setFrame:CGRectMake(point.x-10/2, point.y-5/2, 10, 10)];
191 | // view.layer.cornerRadius = 10/2;
192 | // view.font = [UIFont systemFontOfSize:10];
193 | // view.textColor = [UIColor whiteColor];
194 | // view.hidden = true;
195 | // }
196 |
197 | // Bezier Drawing
198 | [_bezierPath removeAllPoints];
199 | [_bezierPath moveToPoint: [[points objectAtIndex:0] CGPointValue]];
200 | [_bezierPath addLineToPoint: [[points objectAtIndex:1] CGPointValue]];
201 | [_bezierPath addLineToPoint: [[points objectAtIndex:2] CGPointValue]];
202 | [_bezierPath addLineToPoint: [[points objectAtIndex:3] CGPointValue]];
203 |
204 | [_bezierPath addCurveToPoint: [[points objectAtIndex:4] CGPointValue]
205 | controlPoint1: [[points objectAtIndex:5] CGPointValue]
206 | controlPoint2: [[points objectAtIndex:6] CGPointValue]];
207 |
208 | [_bezierPath addCurveToPoint: [[points objectAtIndex:7] CGPointValue]
209 | controlPoint1: [[points objectAtIndex:8] CGPointValue]
210 | controlPoint2: [[points objectAtIndex:9] CGPointValue]];
211 | _shapeLayer.path = _bezierPath.CGPath;
212 | points = nil;
213 | }
214 |
215 | @end
216 |
217 | @interface HyParallaxCurveHeaderView ()
218 | @property (weak, nonatomic) UIScrollView *scrollView;
219 | @property (weak, nonatomic) HyHeaderCurveView *subView;
220 | @property (nonatomic) UIImageView *bluredImageView;
221 | @property (nonnull, strong, nonatomic) HyHeaderCurveView *curveView;
222 | @end
223 |
224 | #define kDefaultHeaderFrame CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)
225 | static CGFloat kParallaxDeltaFactor = 0.5f;
226 |
227 | @implementation HyParallaxCurveHeaderView
228 |
229 | + (_Nonnull instancetype)loadHeaderCurveViewWithSize:(CGSize)size
230 | {
231 | HyParallaxCurveHeaderView *headerView = [[HyParallaxCurveHeaderView alloc] initWithFrame:(CGRect){CGPointZero,size}];
232 | HyHeaderCurveView *curveView = [[HyHeaderCurveView alloc] initWithFrame:headerView.frame];
233 | headerView.isShowBlur = true;
234 | headerView.isParallax = true;
235 | [headerView initialSetupForCustomSubView:curveView];
236 | return headerView;
237 | }
238 |
239 | - (void)initialSetupForCustomSubView:(HyHeaderCurveView *)subView
240 | {
241 | UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
242 | self.scrollView = scrollView;
243 | self.subView = subView;
244 | _followBottomView = _subView.followBottomView;
245 | _imageView = _subView.imageView;
246 | subView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
247 | [self.scrollView addSubview:subView];
248 |
249 | self.bluredImageView = [[UIImageView alloc] initWithFrame:subView.frame];
250 | self.bluredImageView.autoresizingMask = subView.autoresizingMask;
251 | self.bluredImageView.alpha = 0.0f;
252 | [self.scrollView addSubview:self.bluredImageView];
253 |
254 | [self addSubview:self.scrollView];
255 | if (_isShowBlur) {
256 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
257 | [self refreshBlurView];
258 | });
259 | }
260 | }
261 |
262 | - (void)layoutHeaderViewForScrollViewOffset:(CGPoint)offset
263 | {
264 | CGRect frame = self.scrollView.frame;
265 | if (offset.y > 0)
266 | {
267 | if (_isParallax) {
268 | frame.origin.y = MAX(offset.y *kParallaxDeltaFactor, 0);
269 | }
270 | self.scrollView.frame = frame;
271 | self.bluredImageView.alpha = 1 / kDefaultHeaderFrame.size.height * offset.y * 2;
272 | self.clipsToBounds = YES;
273 | }
274 | else
275 | {
276 | CGFloat delta = 0.0f;
277 | CGRect rect = kDefaultHeaderFrame;
278 | delta = fabs(MIN(0.0f, offset.y));
279 | rect.origin.y -= delta;
280 | rect.size.height += delta;
281 | self.scrollView.frame = rect;
282 | self.clipsToBounds = NO;
283 | self.bluredImageView.alpha = offset.y/kDefaultHeaderFrame.size.height;
284 | }
285 | }
286 |
287 | - (void)refreshBlurView
288 | {
289 | UIImage *screenShot = [self screenShotOfView:self];
290 |
291 | UIColor *color = _blurTintColor;
292 | if (!color) {
293 | color = [UIColor colorWithWhite:0.3 alpha:0.4];
294 | }
295 |
296 | screenShot = [screenShot applyBlurWithRadius:6 tintColor:color saturationDeltaFactor:1.0 maskImage:nil];
297 | self.bluredImageView.image = screenShot;
298 | }
299 |
300 | - (UIImage *)screenShotOfView:(UIView *)view
301 | {
302 | UIGraphicsBeginImageContextWithOptions(kDefaultHeaderFrame.size, YES, 0.0);
303 | [self drawViewHierarchyInRect:kDefaultHeaderFrame afterScreenUpdates:NO];
304 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
305 | UIGraphicsEndImageContext();
306 |
307 | return image;
308 | }
309 |
310 | - (void)setCurveColor:(UIColor *)curveColor
311 | {
312 | _curveColor = curveColor;
313 | _subView.curveColor = curveColor;
314 | }
315 |
316 | - (void)setSuggestCurve:(BOOL)suggestCurve
317 | {
318 | _suggestCurve = suggestCurve;
319 | _subView.suggestCurve = suggestCurve;
320 | }
321 |
322 | - (void)setCurveFloat:(CGFloat)curveFloat
323 | {
324 | _curveFloat = curveFloat;
325 | _subView.curveFloat = curveFloat;
326 | }
327 |
328 | - (void)setBackgroundColor:(UIColor *)backgroundColor
329 | {
330 | _backgroundColor = backgroundColor;
331 | _subView.backgroundColor = backgroundColor;
332 | }
333 |
334 | - (void)setPOINT_Y1:(CGFloat)POINT_Y1
335 | {
336 | _POINT_Y1 = POINT_Y1;
337 | _subView.POINT_Y1 = POINT_Y1;
338 | }
339 |
340 | - (void)setImageWidth:(CGFloat)imageWidth
341 | {
342 | _imageWidth = imageWidth;
343 | _subView.imageWidth = imageWidth;
344 | }
345 |
346 | /*
347 | // Only override drawRect: if you perform custom drawing.
348 | // An empty implementation adversely affects performance during animation.
349 | - (void)drawRect:(CGRect)rect {
350 | // Drawing code
351 | }
352 | */
353 |
354 | @end
355 |
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewClass/UIImage+ImageEffects.m:
--------------------------------------------------------------------------------
1 | /*
2 | File: UIImage+ImageEffects.m
3 | Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur.
4 | Version: 1.0
5 |
6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 | Inc. ("Apple") in consideration of your agreement to the following
8 | terms, and your use, installation, modification or redistribution of
9 | this Apple software constitutes acceptance of these terms. If you do
10 | not agree with these terms, please do not use, install, modify or
11 | redistribute this Apple software.
12 |
13 | In consideration of your agreement to abide by the following terms, and
14 | subject to these terms, Apple grants you a personal, non-exclusive
15 | license, under Apple's copyrights in this original Apple software (the
16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 | Software, with or without modifications, in source and/or binary forms;
18 | provided that if you redistribute the Apple Software in its entirety and
19 | without modifications, you must retain this notice and the following
20 | text and disclaimers in all such redistributions of the Apple Software.
21 | Neither the name, trademarks, service marks or logos of Apple Inc. may
22 | be used to endorse or promote products derived from the Apple Software
23 | without specific prior written permission from Apple. Except as
24 | expressly stated in this notice, no other rights or licenses, express or
25 | implied, are granted by Apple herein, including but not limited to any
26 | patent rights that may be infringed by your derivative works or by other
27 | works in which the Apple Software may be incorporated.
28 |
29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 |
35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 | POSSIBILITY OF SUCH DAMAGE.
43 |
44 | Copyright (C) 2013 Apple Inc. All Rights Reserved.
45 |
46 |
47 | Copyright © 2013 Apple Inc. All rights reserved.
48 | WWDC 2013 License
49 |
50 | NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013
51 | Session. Please refer to the applicable WWDC 2013 Session for further
52 | information.
53 |
54 | IMPORTANT: This Apple software is supplied to you by Apple Inc.
55 | ("Apple") in consideration of your agreement to the following terms, and
56 | your use, installation, modification or redistribution of this Apple
57 | software constitutes acceptance of these terms. If you do not agree with
58 | these terms, please do not use, install, modify or redistribute this
59 | Apple software.
60 |
61 | In consideration of your agreement to abide by the following terms, and
62 | subject to these terms, Apple grants you a non-exclusive license, under
63 | Apple's copyrights in this original Apple software (the "Apple
64 | Software"), to use, reproduce, modify and redistribute the Apple
65 | Software, with or without modifications, in source and/or binary forms;
66 | provided that if you redistribute the Apple Software in its entirety and
67 | without modifications, you must retain this notice and the following
68 | text and disclaimers in all such redistributions of the Apple Software.
69 | Neither the name, trademarks, service marks or logos of Apple Inc. may
70 | be used to endorse or promote products derived from the Apple Software
71 | without specific prior written permission from Apple. Except as
72 | expressly stated in this notice, no other rights or licenses, express or
73 | implied, are granted by Apple herein, including but not limited to any
74 | patent rights that may be infringed by your derivative works or by other
75 | works in which the Apple Software may be incorporated.
76 |
77 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES
78 | NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
79 | IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR
80 | A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
81 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
82 |
83 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
84 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
85 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
86 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
87 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
88 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
89 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
90 | POSSIBILITY OF SUCH DAMAGE.
91 |
92 | EA1002
93 | 5/3/2013
94 | */
95 |
96 | #import "UIImage+ImageEffects.h"
97 | #import
98 | #import
99 |
100 | @implementation UIImage (ImageEffects)
101 |
102 |
103 | - (UIImage *)applySubtleEffect
104 | {
105 | UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
106 | return [self applyBlurWithRadius:3 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
107 | }
108 |
109 |
110 | - (UIImage *)applyLightEffect
111 | {
112 | UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
113 | return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
114 | }
115 |
116 |
117 | - (UIImage *)applyExtraLightEffect
118 | {
119 | UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
120 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
121 | }
122 |
123 |
124 | - (UIImage *)applyDarkEffect
125 | {
126 | UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
127 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
128 | }
129 |
130 |
131 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor
132 | {
133 | const CGFloat EffectColorAlpha = 0.6;
134 | UIColor *effectColor = tintColor;
135 | int componentCount = CGColorGetNumberOfComponents(tintColor.CGColor);
136 | if (componentCount == 2) {
137 | CGFloat b;
138 | if ([tintColor getWhite:&b alpha:NULL]) {
139 | effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
140 | }
141 | }
142 | else {
143 | CGFloat r, g, b;
144 | if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
145 | effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
146 | }
147 | }
148 | return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil];
149 | }
150 |
151 |
152 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
153 | {
154 | // Check pre-conditions.
155 | if (self.size.width < 1 || self.size.height < 1) {
156 | NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
157 | return nil;
158 | }
159 | if (!self.CGImage) {
160 | NSLog (@"*** error: image must be backed by a CGImage: %@", self);
161 | return nil;
162 | }
163 | if (maskImage && !maskImage.CGImage) {
164 | NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
165 | return nil;
166 | }
167 |
168 | CGRect imageRect = { CGPointZero, self.size };
169 | UIImage *effectImage = self;
170 |
171 | BOOL hasBlur = blurRadius > __FLT_EPSILON__;
172 | BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
173 | if (hasBlur || hasSaturationChange) {
174 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
175 | CGContextRef effectInContext = UIGraphicsGetCurrentContext();
176 | CGContextScaleCTM(effectInContext, 1.0, -1.0);
177 | CGContextTranslateCTM(effectInContext, 0, -self.size.height);
178 | CGContextDrawImage(effectInContext, imageRect, self.CGImage);
179 |
180 | vImage_Buffer effectInBuffer;
181 | effectInBuffer.data = CGBitmapContextGetData(effectInContext);
182 | effectInBuffer.width = CGBitmapContextGetWidth(effectInContext);
183 | effectInBuffer.height = CGBitmapContextGetHeight(effectInContext);
184 | effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);
185 |
186 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
187 | CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
188 | vImage_Buffer effectOutBuffer;
189 | effectOutBuffer.data = CGBitmapContextGetData(effectOutContext);
190 | effectOutBuffer.width = CGBitmapContextGetWidth(effectOutContext);
191 | effectOutBuffer.height = CGBitmapContextGetHeight(effectOutContext);
192 | effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);
193 |
194 | if (hasBlur) {
195 | // A description of how to compute the box kernel width from the Gaussian
196 | // radius (aka standard deviation) appears in the SVG spec:
197 | // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
198 | //
199 | // For larger values of 's' (s >= 2.0), an approximation can be used: Three
200 | // successive box-blurs build a piece-wise quadratic convolution kernel, which
201 | // approximates the Gaussian kernel to within roughly 3%.
202 | //
203 | // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
204 | //
205 | // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.
206 | //
207 | CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
208 | NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
209 | if (radius % 2 != 1) {
210 | radius += 1; // force radius to be odd so that the three box-blur methodology works.
211 | }
212 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
213 | vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
214 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
215 | }
216 | BOOL effectImageBuffersAreSwapped = NO;
217 | if (hasSaturationChange) {
218 | CGFloat s = saturationDeltaFactor;
219 | CGFloat floatingPointSaturationMatrix[] = {
220 | 0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0,
221 | 0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0,
222 | 0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0,
223 | 0, 0, 0, 1,
224 | };
225 | const int32_t divisor = 256;
226 | NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
227 | int16_t saturationMatrix[matrixSize];
228 | for (NSUInteger i = 0; i < matrixSize; ++i) {
229 | saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
230 | }
231 | if (hasBlur) {
232 | vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
233 | effectImageBuffersAreSwapped = YES;
234 | }
235 | else {
236 | vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
237 | }
238 | }
239 | if (!effectImageBuffersAreSwapped)
240 | effectImage = UIGraphicsGetImageFromCurrentImageContext();
241 | UIGraphicsEndImageContext();
242 |
243 | if (effectImageBuffersAreSwapped)
244 | effectImage = UIGraphicsGetImageFromCurrentImageContext();
245 | UIGraphicsEndImageContext();
246 | }
247 |
248 | // Set up output context.
249 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
250 | CGContextRef outputContext = UIGraphicsGetCurrentContext();
251 | CGContextScaleCTM(outputContext, 1.0, -1.0);
252 | CGContextTranslateCTM(outputContext, 0, -self.size.height);
253 |
254 | // Draw base image.
255 | CGContextDrawImage(outputContext, imageRect, self.CGImage);
256 |
257 | // Draw effect image.
258 | if (hasBlur) {
259 | CGContextSaveGState(outputContext);
260 | if (maskImage) {
261 | CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
262 | }
263 | CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
264 | CGContextRestoreGState(outputContext);
265 | }
266 |
267 | // Add in color tint.
268 | if (tintColor) {
269 | CGContextSaveGState(outputContext);
270 | CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
271 | CGContextFillRect(outputContext, imageRect);
272 | CGContextRestoreGState(outputContext);
273 | }
274 |
275 | // Output image is ready.
276 | UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
277 | UIGraphicsEndImageContext();
278 |
279 | return outputImage;
280 | }
281 |
282 |
283 | @end
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo/HyParallaxCurveHeaderViewClass/UIImage+ImageEffects.m:
--------------------------------------------------------------------------------
1 | /*
2 | File: UIImage+ImageEffects.m
3 | Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur.
4 | Version: 1.0
5 |
6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 | Inc. ("Apple") in consideration of your agreement to the following
8 | terms, and your use, installation, modification or redistribution of
9 | this Apple software constitutes acceptance of these terms. If you do
10 | not agree with these terms, please do not use, install, modify or
11 | redistribute this Apple software.
12 |
13 | In consideration of your agreement to abide by the following terms, and
14 | subject to these terms, Apple grants you a personal, non-exclusive
15 | license, under Apple's copyrights in this original Apple software (the
16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 | Software, with or without modifications, in source and/or binary forms;
18 | provided that if you redistribute the Apple Software in its entirety and
19 | without modifications, you must retain this notice and the following
20 | text and disclaimers in all such redistributions of the Apple Software.
21 | Neither the name, trademarks, service marks or logos of Apple Inc. may
22 | be used to endorse or promote products derived from the Apple Software
23 | without specific prior written permission from Apple. Except as
24 | expressly stated in this notice, no other rights or licenses, express or
25 | implied, are granted by Apple herein, including but not limited to any
26 | patent rights that may be infringed by your derivative works or by other
27 | works in which the Apple Software may be incorporated.
28 |
29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 |
35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 | POSSIBILITY OF SUCH DAMAGE.
43 |
44 | Copyright (C) 2013 Apple Inc. All Rights Reserved.
45 |
46 |
47 | Copyright © 2013 Apple Inc. All rights reserved.
48 | WWDC 2013 License
49 |
50 | NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013
51 | Session. Please refer to the applicable WWDC 2013 Session for further
52 | information.
53 |
54 | IMPORTANT: This Apple software is supplied to you by Apple Inc.
55 | ("Apple") in consideration of your agreement to the following terms, and
56 | your use, installation, modification or redistribution of this Apple
57 | software constitutes acceptance of these terms. If you do not agree with
58 | these terms, please do not use, install, modify or redistribute this
59 | Apple software.
60 |
61 | In consideration of your agreement to abide by the following terms, and
62 | subject to these terms, Apple grants you a non-exclusive license, under
63 | Apple's copyrights in this original Apple software (the "Apple
64 | Software"), to use, reproduce, modify and redistribute the Apple
65 | Software, with or without modifications, in source and/or binary forms;
66 | provided that if you redistribute the Apple Software in its entirety and
67 | without modifications, you must retain this notice and the following
68 | text and disclaimers in all such redistributions of the Apple Software.
69 | Neither the name, trademarks, service marks or logos of Apple Inc. may
70 | be used to endorse or promote products derived from the Apple Software
71 | without specific prior written permission from Apple. Except as
72 | expressly stated in this notice, no other rights or licenses, express or
73 | implied, are granted by Apple herein, including but not limited to any
74 | patent rights that may be infringed by your derivative works or by other
75 | works in which the Apple Software may be incorporated.
76 |
77 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES
78 | NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
79 | IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR
80 | A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
81 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
82 |
83 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
84 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
85 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
86 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
87 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
88 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
89 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
90 | POSSIBILITY OF SUCH DAMAGE.
91 |
92 | EA1002
93 | 5/3/2013
94 | */
95 |
96 | #import "UIImage+ImageEffects.h"
97 | #import
98 | #import
99 |
100 | @implementation UIImage (ImageEffects)
101 |
102 |
103 | - (UIImage *)applySubtleEffect
104 | {
105 | UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
106 | return [self applyBlurWithRadius:3 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
107 | }
108 |
109 |
110 | - (UIImage *)applyLightEffect
111 | {
112 | UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
113 | return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
114 | }
115 |
116 |
117 | - (UIImage *)applyExtraLightEffect
118 | {
119 | UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
120 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
121 | }
122 |
123 |
124 | - (UIImage *)applyDarkEffect
125 | {
126 | UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
127 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
128 | }
129 |
130 |
131 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor
132 | {
133 | const CGFloat EffectColorAlpha = 0.6;
134 | UIColor *effectColor = tintColor;
135 | int componentCount = CGColorGetNumberOfComponents(tintColor.CGColor);
136 | if (componentCount == 2) {
137 | CGFloat b;
138 | if ([tintColor getWhite:&b alpha:NULL]) {
139 | effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
140 | }
141 | }
142 | else {
143 | CGFloat r, g, b;
144 | if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
145 | effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
146 | }
147 | }
148 | return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil];
149 | }
150 |
151 |
152 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
153 | {
154 | // Check pre-conditions.
155 | if (self.size.width < 1 || self.size.height < 1) {
156 | NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
157 | return nil;
158 | }
159 | if (!self.CGImage) {
160 | NSLog (@"*** error: image must be backed by a CGImage: %@", self);
161 | return nil;
162 | }
163 | if (maskImage && !maskImage.CGImage) {
164 | NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
165 | return nil;
166 | }
167 |
168 | CGRect imageRect = { CGPointZero, self.size };
169 | UIImage *effectImage = self;
170 |
171 | BOOL hasBlur = blurRadius > __FLT_EPSILON__;
172 | BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
173 | if (hasBlur || hasSaturationChange) {
174 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
175 | CGContextRef effectInContext = UIGraphicsGetCurrentContext();
176 | CGContextScaleCTM(effectInContext, 1.0, -1.0);
177 | CGContextTranslateCTM(effectInContext, 0, -self.size.height);
178 | CGContextDrawImage(effectInContext, imageRect, self.CGImage);
179 |
180 | vImage_Buffer effectInBuffer;
181 | effectInBuffer.data = CGBitmapContextGetData(effectInContext);
182 | effectInBuffer.width = CGBitmapContextGetWidth(effectInContext);
183 | effectInBuffer.height = CGBitmapContextGetHeight(effectInContext);
184 | effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);
185 |
186 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
187 | CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
188 | vImage_Buffer effectOutBuffer;
189 | effectOutBuffer.data = CGBitmapContextGetData(effectOutContext);
190 | effectOutBuffer.width = CGBitmapContextGetWidth(effectOutContext);
191 | effectOutBuffer.height = CGBitmapContextGetHeight(effectOutContext);
192 | effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);
193 |
194 | if (hasBlur) {
195 | // A description of how to compute the box kernel width from the Gaussian
196 | // radius (aka standard deviation) appears in the SVG spec:
197 | // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
198 | //
199 | // For larger values of 's' (s >= 2.0), an approximation can be used: Three
200 | // successive box-blurs build a piece-wise quadratic convolution kernel, which
201 | // approximates the Gaussian kernel to within roughly 3%.
202 | //
203 | // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
204 | //
205 | // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.
206 | //
207 | CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
208 | NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
209 | if (radius % 2 != 1) {
210 | radius += 1; // force radius to be odd so that the three box-blur methodology works.
211 | }
212 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
213 | vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
214 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
215 | }
216 | BOOL effectImageBuffersAreSwapped = NO;
217 | if (hasSaturationChange) {
218 | CGFloat s = saturationDeltaFactor;
219 | CGFloat floatingPointSaturationMatrix[] = {
220 | 0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0,
221 | 0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0,
222 | 0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0,
223 | 0, 0, 0, 1,
224 | };
225 | const int32_t divisor = 256;
226 | NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
227 | int16_t saturationMatrix[matrixSize];
228 | for (NSUInteger i = 0; i < matrixSize; ++i) {
229 | saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
230 | }
231 | if (hasBlur) {
232 | vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
233 | effectImageBuffersAreSwapped = YES;
234 | }
235 | else {
236 | vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
237 | }
238 | }
239 | if (!effectImageBuffersAreSwapped)
240 | effectImage = UIGraphicsGetImageFromCurrentImageContext();
241 | UIGraphicsEndImageContext();
242 |
243 | if (effectImageBuffersAreSwapped)
244 | effectImage = UIGraphicsGetImageFromCurrentImageContext();
245 | UIGraphicsEndImageContext();
246 | }
247 |
248 | // Set up output context.
249 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
250 | CGContextRef outputContext = UIGraphicsGetCurrentContext();
251 | CGContextScaleCTM(outputContext, 1.0, -1.0);
252 | CGContextTranslateCTM(outputContext, 0, -self.size.height);
253 |
254 | // Draw base image.
255 | CGContextDrawImage(outputContext, imageRect, self.CGImage);
256 |
257 | // Draw effect image.
258 | if (hasBlur) {
259 | CGContextSaveGState(outputContext);
260 | if (maskImage) {
261 | CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
262 | }
263 | CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
264 | CGContextRestoreGState(outputContext);
265 | }
266 |
267 | // Add in color tint.
268 | if (tintColor) {
269 | CGContextSaveGState(outputContext);
270 | CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
271 | CGContextFillRect(outputContext, imageRect);
272 | CGContextRestoreGState(outputContext);
273 | }
274 |
275 | // Output image is ready.
276 | UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
277 | UIGraphicsEndImageContext();
278 |
279 | return outputImage;
280 | }
281 |
282 |
283 | @end
--------------------------------------------------------------------------------
/HyParallaxCurveHeaderViewDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7A9FD1101D7432B200156442 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FD10F1D7432B200156442 /* main.m */; };
11 | 7A9FD1131D7432B200156442 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FD1121D7432B200156442 /* AppDelegate.m */; };
12 | 7A9FD1161D7432B200156442 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FD1151D7432B200156442 /* ViewController.m */; };
13 | 7A9FD1191D7432B200156442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A9FD1171D7432B200156442 /* Main.storyboard */; };
14 | 7A9FD11B1D7432B200156442 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A9FD11A1D7432B200156442 /* Assets.xcassets */; };
15 | 7A9FD11E1D7432B200156442 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A9FD11C1D7432B200156442 /* LaunchScreen.storyboard */; };
16 | 7A9FD1291D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FD1281D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests.m */; };
17 | 7A9FD1341D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FD1331D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests.m */; };
18 | 7A9FD14B1D74333000156442 /* TestViews.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FD1491D74333000156442 /* TestViews.m */; };
19 | 7A9FD14C1D74333000156442 /* TestViews.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7A9FD14A1D74333000156442 /* TestViews.xib */; };
20 | 7A9FD14E1D7435EE00156442 /* preview.gif in Resources */ = {isa = PBXBuildFile; fileRef = 7A9FD14D1D7435EE00156442 /* preview.gif */; };
21 | 7A9FD1541D75282D00156442 /* HyParallaxCurveHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FD1511D75282D00156442 /* HyParallaxCurveHeaderView.m */; };
22 | 7A9FD1551D75282D00156442 /* UIImage+ImageEffects.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FD1531D75282D00156442 /* UIImage+ImageEffects.m */; };
23 | /* End PBXBuildFile section */
24 |
25 | /* Begin PBXContainerItemProxy section */
26 | 7A9FD1251D7432B200156442 /* PBXContainerItemProxy */ = {
27 | isa = PBXContainerItemProxy;
28 | containerPortal = 7A9FD1031D7432B200156442 /* Project object */;
29 | proxyType = 1;
30 | remoteGlobalIDString = 7A9FD10A1D7432B200156442;
31 | remoteInfo = HyParallaxCurveHeaderViewDemo;
32 | };
33 | 7A9FD1301D7432B200156442 /* PBXContainerItemProxy */ = {
34 | isa = PBXContainerItemProxy;
35 | containerPortal = 7A9FD1031D7432B200156442 /* Project object */;
36 | proxyType = 1;
37 | remoteGlobalIDString = 7A9FD10A1D7432B200156442;
38 | remoteInfo = HyParallaxCurveHeaderViewDemo;
39 | };
40 | /* End PBXContainerItemProxy section */
41 |
42 | /* Begin PBXFileReference section */
43 | 7A9FD10B1D7432B200156442 /* HyParallaxCurveHeaderViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HyParallaxCurveHeaderViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
44 | 7A9FD10F1D7432B200156442 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
45 | 7A9FD1111D7432B200156442 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
46 | 7A9FD1121D7432B200156442 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
47 | 7A9FD1141D7432B200156442 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
48 | 7A9FD1151D7432B200156442 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
49 | 7A9FD1181D7432B200156442 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
50 | 7A9FD11A1D7432B200156442 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
51 | 7A9FD11D1D7432B200156442 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
52 | 7A9FD11F1D7432B200156442 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
53 | 7A9FD1241D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HyParallaxCurveHeaderViewDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
54 | 7A9FD1281D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HyParallaxCurveHeaderViewDemoTests.m; sourceTree = ""; };
55 | 7A9FD12A1D7432B200156442 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
56 | 7A9FD12F1D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HyParallaxCurveHeaderViewDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
57 | 7A9FD1331D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HyParallaxCurveHeaderViewDemoUITests.m; sourceTree = ""; };
58 | 7A9FD1351D7432B200156442 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
59 | 7A9FD1481D74333000156442 /* TestViews.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestViews.h; sourceTree = ""; };
60 | 7A9FD1491D74333000156442 /* TestViews.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestViews.m; sourceTree = ""; };
61 | 7A9FD14A1D74333000156442 /* TestViews.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TestViews.xib; sourceTree = ""; };
62 | 7A9FD14D1D7435EE00156442 /* preview.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = preview.gif; sourceTree = ""; };
63 | 7A9FD1501D75282D00156442 /* HyParallaxCurveHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HyParallaxCurveHeaderView.h; sourceTree = ""; };
64 | 7A9FD1511D75282D00156442 /* HyParallaxCurveHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HyParallaxCurveHeaderView.m; sourceTree = ""; };
65 | 7A9FD1521D75282D00156442 /* UIImage+ImageEffects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+ImageEffects.h"; sourceTree = ""; };
66 | 7A9FD1531D75282D00156442 /* UIImage+ImageEffects.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+ImageEffects.m"; sourceTree = ""; };
67 | /* End PBXFileReference section */
68 |
69 | /* Begin PBXFrameworksBuildPhase section */
70 | 7A9FD1081D7432B200156442 /* Frameworks */ = {
71 | isa = PBXFrameworksBuildPhase;
72 | buildActionMask = 2147483647;
73 | files = (
74 | );
75 | runOnlyForDeploymentPostprocessing = 0;
76 | };
77 | 7A9FD1211D7432B200156442 /* Frameworks */ = {
78 | isa = PBXFrameworksBuildPhase;
79 | buildActionMask = 2147483647;
80 | files = (
81 | );
82 | runOnlyForDeploymentPostprocessing = 0;
83 | };
84 | 7A9FD12C1D7432B200156442 /* Frameworks */ = {
85 | isa = PBXFrameworksBuildPhase;
86 | buildActionMask = 2147483647;
87 | files = (
88 | );
89 | runOnlyForDeploymentPostprocessing = 0;
90 | };
91 | /* End PBXFrameworksBuildPhase section */
92 |
93 | /* Begin PBXGroup section */
94 | 7A9FD1021D7432B200156442 = {
95 | isa = PBXGroup;
96 | children = (
97 | 7A9FD10D1D7432B200156442 /* HyParallaxCurveHeaderViewDemo */,
98 | 7A9FD1271D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests */,
99 | 7A9FD1321D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests */,
100 | 7A9FD10C1D7432B200156442 /* Products */,
101 | );
102 | sourceTree = "";
103 | };
104 | 7A9FD10C1D7432B200156442 /* Products */ = {
105 | isa = PBXGroup;
106 | children = (
107 | 7A9FD10B1D7432B200156442 /* HyParallaxCurveHeaderViewDemo.app */,
108 | 7A9FD1241D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests.xctest */,
109 | 7A9FD12F1D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests.xctest */,
110 | );
111 | name = Products;
112 | sourceTree = "";
113 | };
114 | 7A9FD10D1D7432B200156442 /* HyParallaxCurveHeaderViewDemo */ = {
115 | isa = PBXGroup;
116 | children = (
117 | 7A9FD14F1D75282D00156442 /* HyParallaxCurveHeaderViewClass */,
118 | 7A9FD1111D7432B200156442 /* AppDelegate.h */,
119 | 7A9FD1121D7432B200156442 /* AppDelegate.m */,
120 | 7A9FD1141D7432B200156442 /* ViewController.h */,
121 | 7A9FD1151D7432B200156442 /* ViewController.m */,
122 | 7A9FD1171D7432B200156442 /* Main.storyboard */,
123 | 7A9FD11A1D7432B200156442 /* Assets.xcassets */,
124 | 7A9FD11C1D7432B200156442 /* LaunchScreen.storyboard */,
125 | 7A9FD11F1D7432B200156442 /* Info.plist */,
126 | 7A9FD10E1D7432B200156442 /* Supporting Files */,
127 | );
128 | path = HyParallaxCurveHeaderViewDemo;
129 | sourceTree = "";
130 | };
131 | 7A9FD10E1D7432B200156442 /* Supporting Files */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 7A9FD1481D74333000156442 /* TestViews.h */,
135 | 7A9FD1491D74333000156442 /* TestViews.m */,
136 | 7A9FD14A1D74333000156442 /* TestViews.xib */,
137 | 7A9FD10F1D7432B200156442 /* main.m */,
138 | 7A9FD14D1D7435EE00156442 /* preview.gif */,
139 | );
140 | name = "Supporting Files";
141 | sourceTree = "";
142 | };
143 | 7A9FD1271D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests */ = {
144 | isa = PBXGroup;
145 | children = (
146 | 7A9FD1281D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests.m */,
147 | 7A9FD12A1D7432B200156442 /* Info.plist */,
148 | );
149 | path = HyParallaxCurveHeaderViewDemoTests;
150 | sourceTree = "";
151 | };
152 | 7A9FD1321D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests */ = {
153 | isa = PBXGroup;
154 | children = (
155 | 7A9FD1331D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests.m */,
156 | 7A9FD1351D7432B200156442 /* Info.plist */,
157 | );
158 | path = HyParallaxCurveHeaderViewDemoUITests;
159 | sourceTree = "";
160 | };
161 | 7A9FD14F1D75282D00156442 /* HyParallaxCurveHeaderViewClass */ = {
162 | isa = PBXGroup;
163 | children = (
164 | 7A9FD1501D75282D00156442 /* HyParallaxCurveHeaderView.h */,
165 | 7A9FD1511D75282D00156442 /* HyParallaxCurveHeaderView.m */,
166 | 7A9FD1521D75282D00156442 /* UIImage+ImageEffects.h */,
167 | 7A9FD1531D75282D00156442 /* UIImage+ImageEffects.m */,
168 | );
169 | path = HyParallaxCurveHeaderViewClass;
170 | sourceTree = "";
171 | };
172 | /* End PBXGroup section */
173 |
174 | /* Begin PBXNativeTarget section */
175 | 7A9FD10A1D7432B200156442 /* HyParallaxCurveHeaderViewDemo */ = {
176 | isa = PBXNativeTarget;
177 | buildConfigurationList = 7A9FD1381D7432B200156442 /* Build configuration list for PBXNativeTarget "HyParallaxCurveHeaderViewDemo" */;
178 | buildPhases = (
179 | 7A9FD1071D7432B200156442 /* Sources */,
180 | 7A9FD1081D7432B200156442 /* Frameworks */,
181 | 7A9FD1091D7432B200156442 /* Resources */,
182 | );
183 | buildRules = (
184 | );
185 | dependencies = (
186 | );
187 | name = HyParallaxCurveHeaderViewDemo;
188 | productName = HyParallaxCurveHeaderViewDemo;
189 | productReference = 7A9FD10B1D7432B200156442 /* HyParallaxCurveHeaderViewDemo.app */;
190 | productType = "com.apple.product-type.application";
191 | };
192 | 7A9FD1231D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests */ = {
193 | isa = PBXNativeTarget;
194 | buildConfigurationList = 7A9FD13B1D7432B200156442 /* Build configuration list for PBXNativeTarget "HyParallaxCurveHeaderViewDemoTests" */;
195 | buildPhases = (
196 | 7A9FD1201D7432B200156442 /* Sources */,
197 | 7A9FD1211D7432B200156442 /* Frameworks */,
198 | 7A9FD1221D7432B200156442 /* Resources */,
199 | );
200 | buildRules = (
201 | );
202 | dependencies = (
203 | 7A9FD1261D7432B200156442 /* PBXTargetDependency */,
204 | );
205 | name = HyParallaxCurveHeaderViewDemoTests;
206 | productName = HyParallaxCurveHeaderViewDemoTests;
207 | productReference = 7A9FD1241D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests.xctest */;
208 | productType = "com.apple.product-type.bundle.unit-test";
209 | };
210 | 7A9FD12E1D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests */ = {
211 | isa = PBXNativeTarget;
212 | buildConfigurationList = 7A9FD13E1D7432B200156442 /* Build configuration list for PBXNativeTarget "HyParallaxCurveHeaderViewDemoUITests" */;
213 | buildPhases = (
214 | 7A9FD12B1D7432B200156442 /* Sources */,
215 | 7A9FD12C1D7432B200156442 /* Frameworks */,
216 | 7A9FD12D1D7432B200156442 /* Resources */,
217 | );
218 | buildRules = (
219 | );
220 | dependencies = (
221 | 7A9FD1311D7432B200156442 /* PBXTargetDependency */,
222 | );
223 | name = HyParallaxCurveHeaderViewDemoUITests;
224 | productName = HyParallaxCurveHeaderViewDemoUITests;
225 | productReference = 7A9FD12F1D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests.xctest */;
226 | productType = "com.apple.product-type.bundle.ui-testing";
227 | };
228 | /* End PBXNativeTarget section */
229 |
230 | /* Begin PBXProject section */
231 | 7A9FD1031D7432B200156442 /* Project object */ = {
232 | isa = PBXProject;
233 | attributes = {
234 | LastUpgradeCheck = 0800;
235 | ORGANIZATIONNAME = "@Hy";
236 | TargetAttributes = {
237 | 7A9FD10A1D7432B200156442 = {
238 | CreatedOnToolsVersion = 8.0;
239 | DevelopmentTeam = 4GZ4P57LRH;
240 | ProvisioningStyle = Automatic;
241 | };
242 | 7A9FD1231D7432B200156442 = {
243 | CreatedOnToolsVersion = 8.0;
244 | ProvisioningStyle = Automatic;
245 | TestTargetID = 7A9FD10A1D7432B200156442;
246 | };
247 | 7A9FD12E1D7432B200156442 = {
248 | CreatedOnToolsVersion = 8.0;
249 | ProvisioningStyle = Automatic;
250 | TestTargetID = 7A9FD10A1D7432B200156442;
251 | };
252 | };
253 | };
254 | buildConfigurationList = 7A9FD1061D7432B200156442 /* Build configuration list for PBXProject "HyParallaxCurveHeaderViewDemo" */;
255 | compatibilityVersion = "Xcode 3.2";
256 | developmentRegion = English;
257 | hasScannedForEncodings = 0;
258 | knownRegions = (
259 | en,
260 | Base,
261 | );
262 | mainGroup = 7A9FD1021D7432B200156442;
263 | productRefGroup = 7A9FD10C1D7432B200156442 /* Products */;
264 | projectDirPath = "";
265 | projectRoot = "";
266 | targets = (
267 | 7A9FD10A1D7432B200156442 /* HyParallaxCurveHeaderViewDemo */,
268 | 7A9FD1231D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests */,
269 | 7A9FD12E1D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests */,
270 | );
271 | };
272 | /* End PBXProject section */
273 |
274 | /* Begin PBXResourcesBuildPhase section */
275 | 7A9FD1091D7432B200156442 /* Resources */ = {
276 | isa = PBXResourcesBuildPhase;
277 | buildActionMask = 2147483647;
278 | files = (
279 | 7A9FD14C1D74333000156442 /* TestViews.xib in Resources */,
280 | 7A9FD14E1D7435EE00156442 /* preview.gif in Resources */,
281 | 7A9FD11E1D7432B200156442 /* LaunchScreen.storyboard in Resources */,
282 | 7A9FD11B1D7432B200156442 /* Assets.xcassets in Resources */,
283 | 7A9FD1191D7432B200156442 /* Main.storyboard in Resources */,
284 | );
285 | runOnlyForDeploymentPostprocessing = 0;
286 | };
287 | 7A9FD1221D7432B200156442 /* Resources */ = {
288 | isa = PBXResourcesBuildPhase;
289 | buildActionMask = 2147483647;
290 | files = (
291 | );
292 | runOnlyForDeploymentPostprocessing = 0;
293 | };
294 | 7A9FD12D1D7432B200156442 /* Resources */ = {
295 | isa = PBXResourcesBuildPhase;
296 | buildActionMask = 2147483647;
297 | files = (
298 | );
299 | runOnlyForDeploymentPostprocessing = 0;
300 | };
301 | /* End PBXResourcesBuildPhase section */
302 |
303 | /* Begin PBXSourcesBuildPhase section */
304 | 7A9FD1071D7432B200156442 /* Sources */ = {
305 | isa = PBXSourcesBuildPhase;
306 | buildActionMask = 2147483647;
307 | files = (
308 | 7A9FD14B1D74333000156442 /* TestViews.m in Sources */,
309 | 7A9FD1541D75282D00156442 /* HyParallaxCurveHeaderView.m in Sources */,
310 | 7A9FD1551D75282D00156442 /* UIImage+ImageEffects.m in Sources */,
311 | 7A9FD1161D7432B200156442 /* ViewController.m in Sources */,
312 | 7A9FD1131D7432B200156442 /* AppDelegate.m in Sources */,
313 | 7A9FD1101D7432B200156442 /* main.m in Sources */,
314 | );
315 | runOnlyForDeploymentPostprocessing = 0;
316 | };
317 | 7A9FD1201D7432B200156442 /* Sources */ = {
318 | isa = PBXSourcesBuildPhase;
319 | buildActionMask = 2147483647;
320 | files = (
321 | 7A9FD1291D7432B200156442 /* HyParallaxCurveHeaderViewDemoTests.m in Sources */,
322 | );
323 | runOnlyForDeploymentPostprocessing = 0;
324 | };
325 | 7A9FD12B1D7432B200156442 /* Sources */ = {
326 | isa = PBXSourcesBuildPhase;
327 | buildActionMask = 2147483647;
328 | files = (
329 | 7A9FD1341D7432B200156442 /* HyParallaxCurveHeaderViewDemoUITests.m in Sources */,
330 | );
331 | runOnlyForDeploymentPostprocessing = 0;
332 | };
333 | /* End PBXSourcesBuildPhase section */
334 |
335 | /* Begin PBXTargetDependency section */
336 | 7A9FD1261D7432B200156442 /* PBXTargetDependency */ = {
337 | isa = PBXTargetDependency;
338 | target = 7A9FD10A1D7432B200156442 /* HyParallaxCurveHeaderViewDemo */;
339 | targetProxy = 7A9FD1251D7432B200156442 /* PBXContainerItemProxy */;
340 | };
341 | 7A9FD1311D7432B200156442 /* PBXTargetDependency */ = {
342 | isa = PBXTargetDependency;
343 | target = 7A9FD10A1D7432B200156442 /* HyParallaxCurveHeaderViewDemo */;
344 | targetProxy = 7A9FD1301D7432B200156442 /* PBXContainerItemProxy */;
345 | };
346 | /* End PBXTargetDependency section */
347 |
348 | /* Begin PBXVariantGroup section */
349 | 7A9FD1171D7432B200156442 /* Main.storyboard */ = {
350 | isa = PBXVariantGroup;
351 | children = (
352 | 7A9FD1181D7432B200156442 /* Base */,
353 | );
354 | name = Main.storyboard;
355 | sourceTree = "";
356 | };
357 | 7A9FD11C1D7432B200156442 /* LaunchScreen.storyboard */ = {
358 | isa = PBXVariantGroup;
359 | children = (
360 | 7A9FD11D1D7432B200156442 /* Base */,
361 | );
362 | name = LaunchScreen.storyboard;
363 | sourceTree = "";
364 | };
365 | /* End PBXVariantGroup section */
366 |
367 | /* Begin XCBuildConfiguration section */
368 | 7A9FD1361D7432B200156442 /* Debug */ = {
369 | isa = XCBuildConfiguration;
370 | buildSettings = {
371 | ALWAYS_SEARCH_USER_PATHS = NO;
372 | CLANG_ANALYZER_NONNULL = YES;
373 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
374 | CLANG_CXX_LIBRARY = "libc++";
375 | CLANG_ENABLE_MODULES = YES;
376 | CLANG_ENABLE_OBJC_ARC = YES;
377 | CLANG_WARN_BOOL_CONVERSION = YES;
378 | CLANG_WARN_CONSTANT_CONVERSION = YES;
379 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
380 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
381 | CLANG_WARN_EMPTY_BODY = YES;
382 | CLANG_WARN_ENUM_CONVERSION = YES;
383 | CLANG_WARN_INFINITE_RECURSION = YES;
384 | CLANG_WARN_INT_CONVERSION = YES;
385 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
386 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
387 | CLANG_WARN_UNREACHABLE_CODE = YES;
388 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
389 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
390 | COPY_PHASE_STRIP = NO;
391 | DEBUG_INFORMATION_FORMAT = dwarf;
392 | ENABLE_STRICT_OBJC_MSGSEND = YES;
393 | ENABLE_TESTABILITY = YES;
394 | GCC_C_LANGUAGE_STANDARD = gnu99;
395 | GCC_DYNAMIC_NO_PIC = NO;
396 | GCC_NO_COMMON_BLOCKS = YES;
397 | GCC_OPTIMIZATION_LEVEL = 0;
398 | GCC_PREPROCESSOR_DEFINITIONS = (
399 | "DEBUG=1",
400 | "$(inherited)",
401 | );
402 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
403 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
404 | GCC_WARN_UNDECLARED_SELECTOR = YES;
405 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
406 | GCC_WARN_UNUSED_FUNCTION = YES;
407 | GCC_WARN_UNUSED_VARIABLE = YES;
408 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
409 | MTL_ENABLE_DEBUG_INFO = YES;
410 | ONLY_ACTIVE_ARCH = YES;
411 | SDKROOT = iphoneos;
412 | };
413 | name = Debug;
414 | };
415 | 7A9FD1371D7432B200156442 /* Release */ = {
416 | isa = XCBuildConfiguration;
417 | buildSettings = {
418 | ALWAYS_SEARCH_USER_PATHS = NO;
419 | CLANG_ANALYZER_NONNULL = YES;
420 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
421 | CLANG_CXX_LIBRARY = "libc++";
422 | CLANG_ENABLE_MODULES = YES;
423 | CLANG_ENABLE_OBJC_ARC = YES;
424 | CLANG_WARN_BOOL_CONVERSION = YES;
425 | CLANG_WARN_CONSTANT_CONVERSION = YES;
426 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
427 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
428 | CLANG_WARN_EMPTY_BODY = YES;
429 | CLANG_WARN_ENUM_CONVERSION = YES;
430 | CLANG_WARN_INFINITE_RECURSION = YES;
431 | CLANG_WARN_INT_CONVERSION = YES;
432 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
433 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
434 | CLANG_WARN_UNREACHABLE_CODE = YES;
435 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
436 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
437 | COPY_PHASE_STRIP = NO;
438 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
439 | ENABLE_NS_ASSERTIONS = NO;
440 | ENABLE_STRICT_OBJC_MSGSEND = YES;
441 | GCC_C_LANGUAGE_STANDARD = gnu99;
442 | GCC_NO_COMMON_BLOCKS = YES;
443 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
444 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
445 | GCC_WARN_UNDECLARED_SELECTOR = YES;
446 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
447 | GCC_WARN_UNUSED_FUNCTION = YES;
448 | GCC_WARN_UNUSED_VARIABLE = YES;
449 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
450 | MTL_ENABLE_DEBUG_INFO = NO;
451 | SDKROOT = iphoneos;
452 | VALIDATE_PRODUCT = YES;
453 | };
454 | name = Release;
455 | };
456 | 7A9FD1391D7432B200156442 /* Debug */ = {
457 | isa = XCBuildConfiguration;
458 | buildSettings = {
459 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
460 | DEVELOPMENT_TEAM = 4GZ4P57LRH;
461 | INFOPLIST_FILE = HyParallaxCurveHeaderViewDemo/Info.plist;
462 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
463 | PRODUCT_BUNDLE_IDENTIFIER = Hy.HyParallaxCurveHeaderViewDemo;
464 | PRODUCT_NAME = "$(TARGET_NAME)";
465 | };
466 | name = Debug;
467 | };
468 | 7A9FD13A1D7432B200156442 /* Release */ = {
469 | isa = XCBuildConfiguration;
470 | buildSettings = {
471 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
472 | DEVELOPMENT_TEAM = 4GZ4P57LRH;
473 | INFOPLIST_FILE = HyParallaxCurveHeaderViewDemo/Info.plist;
474 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
475 | PRODUCT_BUNDLE_IDENTIFIER = Hy.HyParallaxCurveHeaderViewDemo;
476 | PRODUCT_NAME = "$(TARGET_NAME)";
477 | };
478 | name = Release;
479 | };
480 | 7A9FD13C1D7432B200156442 /* Debug */ = {
481 | isa = XCBuildConfiguration;
482 | buildSettings = {
483 | BUNDLE_LOADER = "$(TEST_HOST)";
484 | INFOPLIST_FILE = HyParallaxCurveHeaderViewDemoTests/Info.plist;
485 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
486 | PRODUCT_BUNDLE_IDENTIFIER = Hy.HyParallaxCurveHeaderViewDemoTests;
487 | PRODUCT_NAME = "$(TARGET_NAME)";
488 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HyParallaxCurveHeaderViewDemo.app/HyParallaxCurveHeaderViewDemo";
489 | };
490 | name = Debug;
491 | };
492 | 7A9FD13D1D7432B200156442 /* Release */ = {
493 | isa = XCBuildConfiguration;
494 | buildSettings = {
495 | BUNDLE_LOADER = "$(TEST_HOST)";
496 | INFOPLIST_FILE = HyParallaxCurveHeaderViewDemoTests/Info.plist;
497 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
498 | PRODUCT_BUNDLE_IDENTIFIER = Hy.HyParallaxCurveHeaderViewDemoTests;
499 | PRODUCT_NAME = "$(TARGET_NAME)";
500 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HyParallaxCurveHeaderViewDemo.app/HyParallaxCurveHeaderViewDemo";
501 | };
502 | name = Release;
503 | };
504 | 7A9FD13F1D7432B200156442 /* Debug */ = {
505 | isa = XCBuildConfiguration;
506 | buildSettings = {
507 | INFOPLIST_FILE = HyParallaxCurveHeaderViewDemoUITests/Info.plist;
508 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
509 | PRODUCT_BUNDLE_IDENTIFIER = Hy.HyParallaxCurveHeaderViewDemoUITests;
510 | PRODUCT_NAME = "$(TARGET_NAME)";
511 | TEST_TARGET_NAME = HyParallaxCurveHeaderViewDemo;
512 | };
513 | name = Debug;
514 | };
515 | 7A9FD1401D7432B200156442 /* Release */ = {
516 | isa = XCBuildConfiguration;
517 | buildSettings = {
518 | INFOPLIST_FILE = HyParallaxCurveHeaderViewDemoUITests/Info.plist;
519 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
520 | PRODUCT_BUNDLE_IDENTIFIER = Hy.HyParallaxCurveHeaderViewDemoUITests;
521 | PRODUCT_NAME = "$(TARGET_NAME)";
522 | TEST_TARGET_NAME = HyParallaxCurveHeaderViewDemo;
523 | };
524 | name = Release;
525 | };
526 | /* End XCBuildConfiguration section */
527 |
528 | /* Begin XCConfigurationList section */
529 | 7A9FD1061D7432B200156442 /* Build configuration list for PBXProject "HyParallaxCurveHeaderViewDemo" */ = {
530 | isa = XCConfigurationList;
531 | buildConfigurations = (
532 | 7A9FD1361D7432B200156442 /* Debug */,
533 | 7A9FD1371D7432B200156442 /* Release */,
534 | );
535 | defaultConfigurationIsVisible = 0;
536 | defaultConfigurationName = Release;
537 | };
538 | 7A9FD1381D7432B200156442 /* Build configuration list for PBXNativeTarget "HyParallaxCurveHeaderViewDemo" */ = {
539 | isa = XCConfigurationList;
540 | buildConfigurations = (
541 | 7A9FD1391D7432B200156442 /* Debug */,
542 | 7A9FD13A1D7432B200156442 /* Release */,
543 | );
544 | defaultConfigurationIsVisible = 0;
545 | };
546 | 7A9FD13B1D7432B200156442 /* Build configuration list for PBXNativeTarget "HyParallaxCurveHeaderViewDemoTests" */ = {
547 | isa = XCConfigurationList;
548 | buildConfigurations = (
549 | 7A9FD13C1D7432B200156442 /* Debug */,
550 | 7A9FD13D1D7432B200156442 /* Release */,
551 | );
552 | defaultConfigurationIsVisible = 0;
553 | };
554 | 7A9FD13E1D7432B200156442 /* Build configuration list for PBXNativeTarget "HyParallaxCurveHeaderViewDemoUITests" */ = {
555 | isa = XCConfigurationList;
556 | buildConfigurations = (
557 | 7A9FD13F1D7432B200156442 /* Debug */,
558 | 7A9FD1401D7432B200156442 /* Release */,
559 | );
560 | defaultConfigurationIsVisible = 0;
561 | };
562 | /* End XCConfigurationList section */
563 | };
564 | rootObject = 7A9FD1031D7432B200156442 /* Project object */;
565 | }
566 |
--------------------------------------------------------------------------------