├── .DS_Store
├── WSLineChart
├── .DS_Store
├── WSLineChart
│ ├── .DS_Store
│ ├── WSLineChartView
│ │ ├── .DS_Store
│ │ ├── SVProgressHUD
│ │ │ ├── .DS_Store
│ │ │ ├── SVProgressHUD.bundle
│ │ │ │ ├── error.png
│ │ │ │ ├── success.png
│ │ │ │ ├── error@2x.png
│ │ │ │ ├── error-black.png
│ │ │ │ ├── success@2x.png
│ │ │ │ ├── error-black@2x.png
│ │ │ │ ├── success-black.png
│ │ │ │ └── success-black@2x.png
│ │ │ ├── TBActivityView.h
│ │ │ ├── SVProgressHUD.h
│ │ │ ├── TBActivityView.m
│ │ │ └── SVProgressHUD.m
│ │ ├── YAxisView.h
│ │ ├── WSLineChartView.h
│ │ ├── XAxisView.h
│ │ ├── YAxisView.m
│ │ ├── WSLineChartView.m
│ │ └── XAxisView.m
│ ├── ViewController.h
│ ├── AppDelegate.h
│ ├── main.m
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ ├── ViewController.m
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── AppDelegate.m
└── WSLineChart.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── project.pbxproj
├── README.md
└── .gitignore
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/.DS_Store
--------------------------------------------------------------------------------
/WSLineChart/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/.DS_Store
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/.DS_Store
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/.DS_Store
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/.DS_Store
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/error.png
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/success.png
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/error@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/error@2x.png
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/error-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/error-black.png
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/success@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/success@2x.png
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/error-black@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/error-black@2x.png
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/success-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/success-black.png
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/success-black@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zws-China/WSLineChartView/HEAD/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.bundle/success-black@2x.png
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // WSLineChart
4 | //
5 | // Created by iMac on 16/11/14.
6 | // Copyright © 2016年 zws. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // WSLineChart
4 | //
5 | // Created by iMac on 16/11/14.
6 | // Copyright © 2016年 zws. 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 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/YAxisView.h:
--------------------------------------------------------------------------------
1 | //
2 | // yAxisView.h
3 | // 3333
4 | //
5 | // Created by iMac on 16/11/10.
6 | // Copyright © 2016年 zws. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface YAxisView : UIView
12 |
13 |
14 | - (id)initWithFrame:(CGRect)frame yMax:(CGFloat)yMax yMin:(CGFloat)yMin;
15 |
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // WSLineChart
4 | //
5 | // Created by iMac on 16/11/14.
6 | // Copyright © 2016年 zws. 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 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/WSLineChartView.h:
--------------------------------------------------------------------------------
1 | //
2 | // WSLineView.h
3 | // 3333
4 | //
5 | // Created by iMac on 16/11/10.
6 | // Copyright © 2016年 zws. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface WSLineChartView : UIView
12 |
13 | /***
14 | * xTitleArray: X轴数据数组
15 | * yValueArray: 数据值数组
16 | * yMax: Y轴最大值
17 | * yMin: Y轴最小值
18 | * yTypeName: 代表Y轴是什么类型
19 | * xTypeName: 代表X轴是什么类型
20 | * unit: 长按时弹出的数据单位
21 | * ***/
22 | - (id)initWithFrame:(CGRect)frame xTitleArray:(NSArray*)xTitleArray yValueArray:(NSArray*)yValueArray yMax:(CGFloat)yMax yMin:(CGFloat)yMin yTypeName:(NSString*)yTypeName xTypeName:(NSString*)xTypeName unit:(NSString*)unit;
23 |
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/TBActivityView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TBActivityView.h
3 | // TBActivityView
4 | //
5 | // Created by MacBook Pro on 14-6-19.
6 | // Copyright (c) 2014年 zhaoonline. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TBActivityView : UIView
12 | /**
13 | * 小方块个数
14 | */
15 | @property(readwrite , nonatomic) NSUInteger numberOfRect;
16 |
17 | /**
18 | * 小方块背景色
19 | */
20 | @property(strong , nonatomic) UIColor* rectBackgroundColor;
21 |
22 | /**
23 | * self.frame.size
24 | */
25 | @property(readwrite , nonatomic) CGSize defaultSize;
26 |
27 | /**
28 | * 小方块之间的间距
29 | */
30 | @property(readwrite , nonatomic) CGFloat spacing;
31 |
32 | /**
33 | * 开始动画
34 | */
35 | -(void)startAnimate;
36 |
37 |
38 | /**
39 | * 结束动画
40 | */
41 | -(void)stopAnimate;
42 | @end
43 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/XAxisView.h:
--------------------------------------------------------------------------------
1 | //
2 | // xAxisView.h
3 | // 3333
4 | //
5 | // Created by iMac on 16/11/10.
6 | // Copyright © 2016年 zws. All rights reserved.
7 | //
8 |
9 | #import
10 | #define wsScreenWidth [UIScreen mainScreen].bounds.size.width
11 |
12 | @interface XAxisView : UIView
13 |
14 |
15 | @property (assign, nonatomic) CGFloat pointGap;//点之间的距离
16 | @property (assign,nonatomic)BOOL isShowLabel;//是否显示文字
17 |
18 | @property (assign,nonatomic)BOOL isLongPress;//是不是长按状态
19 | @property (assign, nonatomic) CGPoint currentLoc; //长按时当前定位位置
20 | @property (assign, nonatomic) CGPoint screenLoc; //相对于屏幕位置
21 |
22 | /***
23 | * xTitleArray: X轴数据数组
24 | * yValueArray: 数据值数组
25 | * yMax: Y轴最大值
26 | * yMin: Y轴最小值
27 | * yTypeName: 代表Y轴是什么类型
28 | * xTypeName: 代表X轴是什么类型
29 | * unit: 长按时弹出的数据单位
30 | * ***/
31 | - (id)initWithFrame:(CGRect)frame xTitleArray:(NSArray*)xTitleArray yValueArray:(NSArray*)yValueArray yMax:(CGFloat)yMax yMin:(CGFloat)yMin yTypeName:(NSString*)yTypeName xTypeName:(NSString*)xTypeName unit:(NSString*)unit;
32 |
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/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 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // WSLineChart
4 | //
5 | // Created by iMac on 16/11/14.
6 | // Copyright © 2016年 zws. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "WSLineChartView.h"
11 |
12 |
13 | @interface ViewController ()
14 |
15 | @end
16 |
17 | @implementation ViewController
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 | self.view.backgroundColor = [UIColor whiteColor];
22 |
23 | NSMutableArray *xArray = [NSMutableArray array];
24 | NSMutableArray *yArray = [NSMutableArray array];
25 | for (NSInteger i = 0; i < 100; i++) {
26 |
27 | [xArray addObject:[NSString stringWithFormat:@"%ld",i]];
28 | [yArray addObject:[NSString stringWithFormat:@"%.2lf",20.0+arc4random_uniform(10)]];
29 |
30 | }
31 |
32 | //这里你可以计算出yArray的最大最小值。设置为曲线的最大最小值,这样画出来的线占据整个y轴高度。
33 | //..........
34 |
35 | WSLineChartView *wsLine = [[WSLineChartView alloc]initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, self.view.frame.size.height-200) xTitleArray:xArray yValueArray:yArray yMax:40 yMin:10 yTypeName:@"高考成绩" xTypeName:@"考生号" unit:@"分"];
36 | [self.view addSubview:wsLine];
37 |
38 | }
39 |
40 |
41 |
42 |
43 |
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WSLineChartView
2 | 折线图,支持放大缩小,横向定位放大,增加长按功能,y轴的值可以自己设置。采用贝塞尔曲线,核心绘图,左右滑动流畅
3 |
4 |
5 | # PhotoShoot
6 |
7 | 
8 |
9 | 
10 |
11 | # How To Use
12 |
13 | ```ruby
14 |
15 | 1.将WSLineChartView文件夹拖入工程中
16 |
17 | #import "WSLineChartView.h"
18 |
19 | NSMutableArray *xArray = [NSMutableArray array];
20 | NSMutableArray *yArray = [NSMutableArray array];
21 | for (NSInteger i = 0; i < 100; i++) {
22 |
23 | [xArray addObject:[NSString stringWithFormat:@"%ld",i]];
24 | [yArray addObject:[NSString stringWithFormat:@"%.2lf",20.0+arc4random_uniform(10)]];
25 |
26 | }
27 |
28 | //这里你可以计算出yArray的最大最小值。设置为曲线的最大最小值,这样画出来的线占据整个y轴高度。
29 | //..........
30 |
31 | WSLineChartView *wsLine = [[WSLineChartView alloc]initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, self.view.frame.size.height-200) xTitleArray:xArray yValueArray:yArray yMax:40 yMin:10 yTypeName:@"高考成绩" xTypeName:@"考生号" unit:@"分"];
32 | [self.view addSubview:wsLine];
33 |
34 | 喜欢的点个星。 (*^__^*)
35 |
36 | ```
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | # CocoaPods
31 | #
32 | # We recommend against adding the Pods directory to your .gitignore. However
33 | # you should judge for yourself, the pros and cons are mentioned at:
34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
35 | #
36 | # Pods/
37 |
38 | # Carthage
39 | #
40 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
41 | # Carthage/Checkouts
42 |
43 | Carthage/Build
44 |
45 | # fastlane
46 | #
47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
48 | # screenshots whenever they are needed.
49 | # For more information about the recommended setup visit:
50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
51 |
52 | fastlane/report.xml
53 | fastlane/screenshots
54 |
55 | #Code Injection
56 | #
57 | # After new code Injection tools there's a generated folder /iOSInjectionProject
58 | # https://github.com/johnno1962/injectionforxcode
59 |
60 | iOSInjectionProject/
61 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/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 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/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 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // WSLineChart
4 | //
5 | // Created by iMac on 16/11/14.
6 | // Copyright © 2016年 zws. 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 | - (void)applicationWillResignActive:(UIApplication *)application {
24 | // 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.
25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
26 | }
27 |
28 | - (void)applicationDidEnterBackground:(UIApplication *)application {
29 | // 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.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application {
34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
35 | }
36 |
37 | - (void)applicationDidBecomeActive:(UIApplication *)application {
38 | // 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.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/YAxisView.m:
--------------------------------------------------------------------------------
1 | //
2 | // yAxisView.m
3 | // 3333
4 | //
5 | // Created by iMac on 16/11/10.
6 | // Copyright © 2016年 zws. All rights reserved.
7 | //
8 |
9 | #import "YAxisView.h"
10 | #define topMargin 50 // 为顶部留出的空白
11 | #define xAxisTextGap 5 //x轴文字与坐标轴间隙
12 | #define numberOfYAxisElements 5 // y轴分为几段
13 | #define kChartLineColor [UIColor grayColor]
14 | #define kChartTextColor [UIColor blackColor]
15 |
16 |
17 | @implementation YAxisView
18 |
19 | - (id)initWithFrame:(CGRect)frame yMax:(CGFloat)yMax yMin:(CGFloat)yMin {
20 |
21 | if (self = [super initWithFrame:frame]) {
22 | self.backgroundColor = [UIColor whiteColor];
23 |
24 | // 计算坐标轴的位置以及大小
25 | NSDictionary *attr = @{NSFontAttributeName : [UIFont systemFontOfSize:10]};
26 | CGSize labelSize = [@"22-22\r\n22:22" sizeWithAttributes:attr];
27 | // 垂直坐标轴
28 | UIView *separate = [[UIView alloc] initWithFrame:CGRectMake(self.frame.size.width-1, 0, 1, self.frame.size.height - labelSize.height - xAxisTextGap)];
29 | separate.backgroundColor = kChartLineColor;
30 | [self addSubview:separate];
31 |
32 |
33 | // Label做占据的高度
34 | CGFloat allLabelHeight = self.frame.size.height - xAxisTextGap - labelSize.height;
35 | // Label之间的间隙
36 | CGFloat labelMargin = (allLabelHeight - topMargin) / numberOfYAxisElements;
37 |
38 | // 添加Label
39 | for (int i = 0; i < numberOfYAxisElements + 1; i++) {
40 | UILabel *label = [[UILabel alloc] init];
41 | double avgValue = (yMax - yMin) / numberOfYAxisElements;
42 |
43 | double value = yMin + avgValue * i;
44 |
45 | if (value >= 1000000) {
46 | label.text = [NSString stringWithFormat:@"%.0f万", value/10000.0];
47 | }
48 | else {
49 | // 判断是不是小数
50 | if ([self isPureFloat:value]) {
51 | label.text = [NSString stringWithFormat:@"%.2f", value];
52 | }
53 | else {
54 | label.text = [NSString stringWithFormat:@"%.0f", value];
55 | }
56 | }
57 |
58 | label.textAlignment = NSTextAlignmentRight;// UITextAlignmentRight;
59 | label.font = [UIFont systemFontOfSize:10];
60 | label.textColor = kChartTextColor;
61 | label.frame = CGRectMake(0, allLabelHeight - labelMargin* i - labelSize.height/2, self.frame.size.width - 1 - 5, labelSize.height);
62 |
63 | [self addSubview:label];
64 | }
65 |
66 |
67 |
68 | }
69 | return self;
70 | }
71 |
72 | // 判断是小数还是整数
73 | - (BOOL)isPureFloat:(double)num
74 | {
75 | int i = num;
76 |
77 | double result = num - i;
78 |
79 | // 当不等于0时,是小数
80 | return result != 0;
81 | }
82 |
83 |
84 | @end
85 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.h:
--------------------------------------------------------------------------------
1 | //
2 | // SVProgressHUD.h
3 | //
4 | // Created by Sam Vermette on 27.03.11.
5 | // Copyright 2011 Sam Vermette. All rights reserved.
6 | //
7 | // https://github.com/samvermette/SVProgressHUD
8 | //
9 |
10 | #import
11 | #import
12 |
13 | extern NSString * const SVProgressHUDDidReceiveTouchEventNotification;
14 | extern NSString * const SVProgressHUDWillDisappearNotification;
15 | extern NSString * const SVProgressHUDDidDisappearNotification;
16 | extern NSString * const SVProgressHUDWillAppearNotification;
17 | extern NSString * const SVProgressHUDDidAppearNotification;
18 |
19 | extern NSString * const SVProgressHUDStatusUserInfoKey;
20 |
21 | enum {
22 | SVProgressHUDMaskTypeNone = 1, // allow user interactions while HUD is displayed
23 | SVProgressHUDMaskTypeClear, // don't allow
24 | SVProgressHUDMaskTypeBlack, // don't allow and dim the UI in the back of the HUD
25 | SVProgressHUDMaskTypeGradient // don't allow and dim the UI with a a-la-alert-view bg gradient
26 | };
27 |
28 | typedef NSUInteger SVProgressHUDMaskType;
29 |
30 | @interface SVProgressHUD : UIView
31 |
32 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
33 | @property (readwrite, nonatomic, retain) UIColor *hudBackgroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
34 | @property (readwrite, nonatomic, retain) UIColor *hudForegroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
35 | @property (readwrite, nonatomic, retain) UIColor *hudStatusShadowColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
36 | @property (readwrite, nonatomic, retain) UIColor *hudRingBackgroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
37 | @property (readwrite, nonatomic, retain) UIColor *hudRingForegroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
38 | @property (readwrite, nonatomic, retain) UIFont *hudFont NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
39 | @property (readwrite, nonatomic, retain) UIImage *hudSuccessImage NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
40 | @property (readwrite, nonatomic, retain) UIImage *hudErrorImage NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
41 | #endif
42 |
43 | + (void)setOffsetFromCenter:(UIOffset)offset;
44 | + (void)resetOffsetFromCenter;
45 |
46 | + (void)show;
47 | + (void)showWithMaskType:(SVProgressHUDMaskType)maskType;
48 | + (void)showWithStatus:(NSString*)status;
49 | + (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType;
50 |
51 | + (void)showProgress:(float)progress;
52 | + (void)showProgress:(float)progress status:(NSString*)status;
53 | + (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType;
54 |
55 | + (void)setStatus:(NSString*)string; // change the HUD loading status while it's showing
56 |
57 | // stops the activity indicator, shows a glyph + status, and dismisses HUD 1s later
58 | + (void)showSuccessWithStatus:(NSString*)string;
59 | + (void)showErrorWithStatus:(NSString *)string;
60 | + (void)showImage:(UIImage*)image status:(NSString*)status; // use 28x28 white pngs
61 |
62 | + (void)popActivity;
63 | + (void)dismiss;
64 |
65 | + (BOOL)isVisible;
66 |
67 | @end
68 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/TBActivityView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TBActivityView.m
3 | // TBActivityView
4 | //
5 | // Created by MacBook Pro on 14-6-19.
6 | // Copyright (c) 2014年 zhaoonline. All rights reserved.
7 | //
8 |
9 | #import "TBActivityView.h"
10 | /**
11 | * defaultSize为空时,使用默认normalSize
12 | */
13 | static CGSize normalSize = {320,50};
14 |
15 | @implementation TBActivityView
16 |
17 | - (id)initWithFrame:(CGRect)frame
18 | {
19 | self = [super initWithFrame:frame];
20 | if (self) {
21 | [self setDefaultAttribute];
22 | }
23 | return self;
24 | }
25 |
26 |
27 | -(instancetype)init
28 | {
29 | self = [super init];
30 |
31 | if (self) {
32 | [self setDefaultAttribute];
33 | }
34 |
35 | return self;
36 | }
37 |
38 |
39 | /**
40 | * 设置默认属性
41 | */
42 | -(void)setDefaultAttribute
43 | {
44 | _numberOfRect = 6;
45 | self.rectBackgroundColor= [UIColor whiteColor];
46 | _defaultSize = normalSize;
47 | _spacing =1;
48 |
49 |
50 | [self setBackgroundColor:[UIColor clearColor]];
51 | if (CGRectEqualToRect(self.frame, CGRectZero)) {
52 | [self setFrame:CGRectMake(CGRectGetMinX(self.frame), CGRectGetMinY(self.frame), _defaultSize.width, _defaultSize.height)];
53 |
54 | }
55 | else
56 | {
57 | _defaultSize = self.frame.size;
58 | }
59 | }
60 |
61 |
62 | -(CAAnimation*)addAnimateWithDelay:(CGFloat)delay
63 | {
64 | CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
65 | animation.repeatCount = MAXFLOAT;
66 | animation.removedOnCompletion = YES;
67 | animation.autoreverses = NO;
68 | animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
69 | animation.fromValue = [NSNumber numberWithFloat:0];
70 | animation.toValue = [NSNumber numberWithFloat:M_PI];
71 | animation.duration = _numberOfRect * 0.1; //第一个翻转一周,最后一个开始翻转
72 | animation.beginTime = CACurrentMediaTime() + delay;
73 |
74 | return animation;
75 | }
76 |
77 |
78 | /**
79 | * 添加矩形
80 | */
81 | -(void)addRect
82 | {
83 |
84 | [self removeRect];
85 | [self setHidden:NO];
86 |
87 | for (int i = 0; i < _numberOfRect; i++) {
88 |
89 | UIView* rectView = [[UIView alloc] initWithFrame:CGRectMake((320 - _numberOfRect*(_defaultSize.height / 2. + _spacing))/2. + i *(_defaultSize.height / 2. + _spacing) , 0, _defaultSize.height/3., _defaultSize.height)];
90 | [rectView setBackgroundColor:_rectBackgroundColor];
91 | [rectView.layer addAnimation:[self addAnimateWithDelay:i*0.1] forKey:@"TBRotate"];
92 | [self addSubview:rectView];
93 |
94 |
95 | }
96 |
97 |
98 | }
99 |
100 | /**
101 | * 移除矩形
102 | */
103 | -(void)removeRect
104 | {
105 | if (self.subviews.count) {
106 | [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
107 | }
108 |
109 | [self setHidden:YES];
110 | }
111 |
112 |
113 |
114 | - (void)startAnimate
115 | {
116 | [self addRect];
117 | }
118 |
119 |
120 | - (void)stopAnimate
121 | {
122 | [self removeRect];
123 | }
124 | /*
125 | // Only override drawRect: if you perform custom drawing.
126 | // An empty implementation adversely affects performance during animation.
127 | - (void)drawRect:(CGRect)rect
128 | {
129 | // Drawing code
130 | }
131 | */
132 |
133 | @end
134 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/WSLineChartView.m:
--------------------------------------------------------------------------------
1 | //
2 | // WSLineView.m
3 | // 3333
4 | //
5 | // Created by iMac on 16/11/10.
6 | // Copyright © 2016年 zws. All rights reserved.
7 | //
8 |
9 | #import "WSLineChartView.h"
10 | #import "YAxisView.h"
11 | #import "XAxisView.h"
12 | #import "SVProgressHUD.h"
13 |
14 |
15 | #define leftMargin 45
16 | //#define defaultSpace 5
17 | #define lastSpace 10
18 |
19 |
20 |
21 | @interface WSLineChartView ()
22 |
23 | @property (strong, nonatomic) NSArray *xTitleArray;
24 | @property (strong, nonatomic) NSArray *yValueArray;
25 | @property (assign, nonatomic) CGFloat yMax;
26 | @property (assign, nonatomic) CGFloat yMin;
27 | @property (strong, nonatomic) NSString *xTypeName;
28 | @property (strong, nonatomic) NSString *yTypeName;
29 | @property (strong, nonatomic) NSString *unit;
30 |
31 | @property (strong, nonatomic) YAxisView *yAxisView;
32 | @property (strong, nonatomic) XAxisView *xAxisView;
33 | @property (strong, nonatomic) UIScrollView *scrollView;
34 | @property (assign, nonatomic) CGFloat pointGap;
35 | @property (assign, nonatomic) CGFloat defaultSpace;//X轴点之间的间隔
36 |
37 | @property (assign, nonatomic) CGFloat moveDistance;
38 |
39 | @end
40 |
41 | @implementation WSLineChartView
42 |
43 | - (id)initWithFrame:(CGRect)frame xTitleArray:(NSArray*)xTitleArray yValueArray:(NSArray*)yValueArray yMax:(CGFloat)yMax yMin:(CGFloat)yMin yTypeName:(NSString*)yTypeName xTypeName:(NSString*)xTypeName unit:(NSString*)unit {
44 |
45 | self = [super initWithFrame:frame];
46 | if (self) {
47 | self.backgroundColor = [UIColor clearColor];
48 |
49 | self.xTitleArray = xTitleArray;
50 | self.yValueArray = yValueArray;
51 | self.yMax = yMax;
52 | self.yMin = yMin;
53 | self.xTypeName = xTypeName;
54 | self.yTypeName = yTypeName;
55 | self.unit = unit;
56 |
57 | if (xTitleArray.count > 600) {
58 | _defaultSpace = 5;
59 | }
60 | else if (xTitleArray.count > 400 && xTitleArray.count <= 600){
61 | _defaultSpace = 10;
62 | }
63 | else if (xTitleArray.count > 200 && xTitleArray.count <= 400){
64 | _defaultSpace = 20;
65 | }
66 | else if (xTitleArray.count > 100 && xTitleArray.count <= 200){
67 | _defaultSpace = 30;
68 | }
69 | else if (xTitleArray.count > 10 && xTitleArray.count <= 100){
70 | _defaultSpace = 40;
71 | }
72 | else {
73 | _defaultSpace = (wsScreenWidth-leftMargin)/xTitleArray.count;
74 | }
75 |
76 |
77 | self.pointGap = (wsScreenWidth-leftMargin)/xTitleArray.count;
78 |
79 |
80 | [self creatYAxisView];
81 |
82 | [self creatXAxisView];
83 |
84 | // 2. 捏合手势
85 | UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGesture:)];
86 | [self.xAxisView addGestureRecognizer:pinch];
87 |
88 | //长按手势
89 | UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(event_longPressAction:)];
90 | [self.xAxisView addGestureRecognizer:longPress];
91 |
92 |
93 | }
94 |
95 | return self;
96 | }
97 |
98 | - (void)creatYAxisView {
99 |
100 | self.yAxisView = [[YAxisView alloc]initWithFrame:CGRectMake(0, 0, leftMargin, self.frame.size.height) yMax:self.yMax yMin:self.yMin];
101 | [self addSubview:self.yAxisView];
102 |
103 | }
104 |
105 | - (void)creatXAxisView {
106 |
107 | _scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(leftMargin, 0, self.frame.size.width-leftMargin, self.frame.size.height)];
108 | _scrollView.showsHorizontalScrollIndicator = NO;
109 | _scrollView.bounces = NO;
110 | _scrollView.scrollsToTop = NO;
111 | [self addSubview:_scrollView];
112 |
113 | self.xAxisView = [[XAxisView alloc] initWithFrame:CGRectMake(0, 0, self.xTitleArray.count * self.pointGap + lastSpace, self.frame.size.height) xTitleArray:self.xTitleArray yValueArray:self.yValueArray yMax:self.yMax yMin:self.yMin yTypeName:self.yTypeName xTypeName:self.xTypeName unit:self.unit];
114 |
115 | [_scrollView addSubview:self.xAxisView];
116 |
117 | _scrollView.contentSize = self.xAxisView.frame.size;
118 |
119 | }
120 |
121 | // 捏合手势监听方法
122 | - (void)pinchGesture:(UIPinchGestureRecognizer *)recognizer
123 | {
124 | if (recognizer.state == 3) {
125 |
126 | if (self.xAxisView.frame.size.width-lastSpace <= self.scrollView.frame.size.width) { //当缩小到小于屏幕宽时,松开回复屏幕宽度
127 |
128 | CGFloat scale = self.scrollView.frame.size.width / (self.xAxisView.frame.size.width-lastSpace);
129 |
130 | self.pointGap *= scale;
131 |
132 | [UIView animateWithDuration:0.25 animations:^{
133 |
134 | CGRect frame = self.xAxisView.frame;
135 | frame.size.width = self.scrollView.frame.size.width+lastSpace;
136 | self.xAxisView.frame = frame;
137 | }];
138 |
139 | self.xAxisView.pointGap = self.pointGap;
140 |
141 | }else if (self.xAxisView.frame.size.width-lastSpace >= self.xTitleArray.count * _defaultSpace){
142 |
143 | [UIView animateWithDuration:0.25 animations:^{
144 | CGRect frame = self.xAxisView.frame;
145 | frame.size.width = self.xTitleArray.count * _defaultSpace + lastSpace;
146 | self.xAxisView.frame = frame;
147 |
148 | }];
149 |
150 | self.pointGap = _defaultSpace;
151 |
152 | self.xAxisView.pointGap = self.pointGap;
153 | }
154 | }else{
155 |
156 | CGFloat currentIndex,leftMagin;
157 | if( recognizer.numberOfTouches == 2 ) {
158 | //2.获取捏合中心点 -> 捏合中心点距离scrollviewcontent左侧的距离
159 | CGPoint p1 = [recognizer locationOfTouch:0 inView:self.xAxisView];
160 | CGPoint p2 = [recognizer locationOfTouch:1 inView:self.xAxisView];
161 | CGFloat centerX = (p1.x+p2.x)/2;
162 | leftMagin = centerX - self.scrollView.contentOffset.x;
163 |
164 | currentIndex = centerX / self.pointGap;
165 |
166 |
167 | self.pointGap *= recognizer.scale;
168 | self.pointGap = self.pointGap > _defaultSpace ? _defaultSpace : self.pointGap;
169 | if (self.pointGap == _defaultSpace) {
170 |
171 | [SVProgressHUD showErrorWithStatus:@"已经放至最大"];
172 | }
173 | self.xAxisView.pointGap = self.pointGap;
174 | recognizer.scale = 1.0;
175 |
176 | self.xAxisView.frame = CGRectMake(0, 0, self.xTitleArray.count * self.pointGap + lastSpace, self.frame.size.height);
177 |
178 | self.scrollView.contentOffset = CGPointMake(currentIndex*self.pointGap-leftMagin, 0);
179 | // NSLog(@"contentOffset = %f",self.scrollView.contentOffset.x);
180 |
181 | }
182 |
183 |
184 |
185 |
186 |
187 | }
188 |
189 | self.scrollView.contentSize = CGSizeMake(self.xAxisView.frame.size.width, 0);
190 |
191 |
192 |
193 |
194 | }
195 |
196 |
197 | - (void)event_longPressAction:(UILongPressGestureRecognizer *)longPress {
198 |
199 | if(UIGestureRecognizerStateChanged == longPress.state || UIGestureRecognizerStateBegan == longPress.state) {
200 |
201 | CGPoint location = [longPress locationInView:self.xAxisView];
202 |
203 | //相对于屏幕的位置
204 | CGPoint screenLoc = CGPointMake(location.x - self.scrollView.contentOffset.x, location.y);
205 | [self.xAxisView setScreenLoc:screenLoc];
206 |
207 | if (ABS(location.x - _moveDistance) > self.pointGap) { //不能长按移动一点点就重新绘图 要让定位的点改变了再重新绘图
208 |
209 | [self.xAxisView setIsShowLabel:YES];
210 | [self.xAxisView setIsLongPress:YES];
211 | self.xAxisView.currentLoc = location;
212 | _moveDistance = location.x;
213 | }
214 | }
215 |
216 | if(longPress.state == UIGestureRecognizerStateEnded)
217 | {
218 | _moveDistance = 0;
219 | //恢复scrollView的滑动
220 | [self.xAxisView setIsLongPress:NO];
221 | [self.xAxisView setIsShowLabel:NO];
222 |
223 | }
224 | }
225 |
226 |
227 |
228 | @end
229 |
230 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 8882023D1DDD892B005AF441 /* WSLineChartView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8882023C1DDD892B005AF441 /* WSLineChartView.m */; };
11 | 888202401DDD8A2B005AF441 /* XAxisView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8882023F1DDD8A2B005AF441 /* XAxisView.m */; };
12 | 888202431DDD8A33005AF441 /* YAxisView.m in Sources */ = {isa = PBXBuildFile; fileRef = 888202421DDD8A33005AF441 /* YAxisView.m */; };
13 | 8882024A1DDD91D1005AF441 /* SVProgressHUD.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 888202451DDD91D1005AF441 /* SVProgressHUD.bundle */; };
14 | 8882024B1DDD91D1005AF441 /* SVProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 888202471DDD91D1005AF441 /* SVProgressHUD.m */; };
15 | 8882024C1DDD91D1005AF441 /* TBActivityView.m in Sources */ = {isa = PBXBuildFile; fileRef = 888202491DDD91D1005AF441 /* TBActivityView.m */; };
16 | 889097621DD9EAC700F2DEAF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 889097611DD9EAC700F2DEAF /* main.m */; };
17 | 889097651DD9EAC700F2DEAF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 889097641DD9EAC700F2DEAF /* AppDelegate.m */; };
18 | 889097681DD9EAC700F2DEAF /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 889097671DD9EAC700F2DEAF /* ViewController.m */; };
19 | 8890976B1DD9EAC700F2DEAF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 889097691DD9EAC700F2DEAF /* Main.storyboard */; };
20 | 8890976D1DD9EAC700F2DEAF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8890976C1DD9EAC700F2DEAF /* Assets.xcassets */; };
21 | 889097701DD9EAC700F2DEAF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8890976E1DD9EAC700F2DEAF /* LaunchScreen.storyboard */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXFileReference section */
25 | 8882023B1DDD892B005AF441 /* WSLineChartView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WSLineChartView.h; sourceTree = ""; };
26 | 8882023C1DDD892B005AF441 /* WSLineChartView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WSLineChartView.m; sourceTree = ""; };
27 | 8882023E1DDD8A2B005AF441 /* XAxisView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XAxisView.h; sourceTree = ""; };
28 | 8882023F1DDD8A2B005AF441 /* XAxisView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XAxisView.m; sourceTree = ""; };
29 | 888202411DDD8A33005AF441 /* YAxisView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YAxisView.h; sourceTree = ""; };
30 | 888202421DDD8A33005AF441 /* YAxisView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YAxisView.m; sourceTree = ""; };
31 | 888202451DDD91D1005AF441 /* SVProgressHUD.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = SVProgressHUD.bundle; sourceTree = ""; };
32 | 888202461DDD91D1005AF441 /* SVProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVProgressHUD.h; sourceTree = ""; };
33 | 888202471DDD91D1005AF441 /* SVProgressHUD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVProgressHUD.m; sourceTree = ""; };
34 | 888202481DDD91D1005AF441 /* TBActivityView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TBActivityView.h; sourceTree = ""; };
35 | 888202491DDD91D1005AF441 /* TBActivityView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TBActivityView.m; sourceTree = ""; };
36 | 8890975D1DD9EAC700F2DEAF /* WSLineChart.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WSLineChart.app; sourceTree = BUILT_PRODUCTS_DIR; };
37 | 889097611DD9EAC700F2DEAF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
38 | 889097631DD9EAC700F2DEAF /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
39 | 889097641DD9EAC700F2DEAF /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
40 | 889097661DD9EAC700F2DEAF /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
41 | 889097671DD9EAC700F2DEAF /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
42 | 8890976A1DD9EAC700F2DEAF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
43 | 8890976C1DD9EAC700F2DEAF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
44 | 8890976F1DD9EAC700F2DEAF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
45 | 889097711DD9EAC700F2DEAF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
46 | /* End PBXFileReference section */
47 |
48 | /* Begin PBXFrameworksBuildPhase section */
49 | 8890975A1DD9EAC700F2DEAF /* Frameworks */ = {
50 | isa = PBXFrameworksBuildPhase;
51 | buildActionMask = 2147483647;
52 | files = (
53 | );
54 | runOnlyForDeploymentPostprocessing = 0;
55 | };
56 | /* End PBXFrameworksBuildPhase section */
57 |
58 | /* Begin PBXGroup section */
59 | 888202371DDD88C9005AF441 /* WSLineChartView */ = {
60 | isa = PBXGroup;
61 | children = (
62 | 888202441DDD91D1005AF441 /* SVProgressHUD */,
63 | 8882023B1DDD892B005AF441 /* WSLineChartView.h */,
64 | 8882023C1DDD892B005AF441 /* WSLineChartView.m */,
65 | 8882023E1DDD8A2B005AF441 /* XAxisView.h */,
66 | 8882023F1DDD8A2B005AF441 /* XAxisView.m */,
67 | 888202411DDD8A33005AF441 /* YAxisView.h */,
68 | 888202421DDD8A33005AF441 /* YAxisView.m */,
69 | );
70 | path = WSLineChartView;
71 | sourceTree = "";
72 | };
73 | 888202441DDD91D1005AF441 /* SVProgressHUD */ = {
74 | isa = PBXGroup;
75 | children = (
76 | 888202451DDD91D1005AF441 /* SVProgressHUD.bundle */,
77 | 888202461DDD91D1005AF441 /* SVProgressHUD.h */,
78 | 888202471DDD91D1005AF441 /* SVProgressHUD.m */,
79 | 888202481DDD91D1005AF441 /* TBActivityView.h */,
80 | 888202491DDD91D1005AF441 /* TBActivityView.m */,
81 | );
82 | path = SVProgressHUD;
83 | sourceTree = "";
84 | };
85 | 889097541DD9EAC700F2DEAF = {
86 | isa = PBXGroup;
87 | children = (
88 | 8890975F1DD9EAC700F2DEAF /* WSLineChart */,
89 | 8890975E1DD9EAC700F2DEAF /* Products */,
90 | );
91 | sourceTree = "";
92 | };
93 | 8890975E1DD9EAC700F2DEAF /* Products */ = {
94 | isa = PBXGroup;
95 | children = (
96 | 8890975D1DD9EAC700F2DEAF /* WSLineChart.app */,
97 | );
98 | name = Products;
99 | sourceTree = "";
100 | };
101 | 8890975F1DD9EAC700F2DEAF /* WSLineChart */ = {
102 | isa = PBXGroup;
103 | children = (
104 | 889097631DD9EAC700F2DEAF /* AppDelegate.h */,
105 | 889097641DD9EAC700F2DEAF /* AppDelegate.m */,
106 | 889097661DD9EAC700F2DEAF /* ViewController.h */,
107 | 889097671DD9EAC700F2DEAF /* ViewController.m */,
108 | 888202371DDD88C9005AF441 /* WSLineChartView */,
109 | 889097691DD9EAC700F2DEAF /* Main.storyboard */,
110 | 8890976C1DD9EAC700F2DEAF /* Assets.xcassets */,
111 | 8890976E1DD9EAC700F2DEAF /* LaunchScreen.storyboard */,
112 | 889097711DD9EAC700F2DEAF /* Info.plist */,
113 | 889097601DD9EAC700F2DEAF /* Supporting Files */,
114 | );
115 | path = WSLineChart;
116 | sourceTree = "";
117 | };
118 | 889097601DD9EAC700F2DEAF /* Supporting Files */ = {
119 | isa = PBXGroup;
120 | children = (
121 | 889097611DD9EAC700F2DEAF /* main.m */,
122 | );
123 | name = "Supporting Files";
124 | sourceTree = "";
125 | };
126 | /* End PBXGroup section */
127 |
128 | /* Begin PBXNativeTarget section */
129 | 8890975C1DD9EAC700F2DEAF /* WSLineChart */ = {
130 | isa = PBXNativeTarget;
131 | buildConfigurationList = 889097741DD9EAC700F2DEAF /* Build configuration list for PBXNativeTarget "WSLineChart" */;
132 | buildPhases = (
133 | 889097591DD9EAC700F2DEAF /* Sources */,
134 | 8890975A1DD9EAC700F2DEAF /* Frameworks */,
135 | 8890975B1DD9EAC700F2DEAF /* Resources */,
136 | );
137 | buildRules = (
138 | );
139 | dependencies = (
140 | );
141 | name = WSLineChart;
142 | productName = WSLineChart;
143 | productReference = 8890975D1DD9EAC700F2DEAF /* WSLineChart.app */;
144 | productType = "com.apple.product-type.application";
145 | };
146 | /* End PBXNativeTarget section */
147 |
148 | /* Begin PBXProject section */
149 | 889097551DD9EAC700F2DEAF /* Project object */ = {
150 | isa = PBXProject;
151 | attributes = {
152 | LastUpgradeCheck = 0730;
153 | ORGANIZATIONNAME = zws;
154 | TargetAttributes = {
155 | 8890975C1DD9EAC700F2DEAF = {
156 | CreatedOnToolsVersion = 7.3.1;
157 | };
158 | };
159 | };
160 | buildConfigurationList = 889097581DD9EAC700F2DEAF /* Build configuration list for PBXProject "WSLineChart" */;
161 | compatibilityVersion = "Xcode 3.2";
162 | developmentRegion = English;
163 | hasScannedForEncodings = 0;
164 | knownRegions = (
165 | en,
166 | Base,
167 | );
168 | mainGroup = 889097541DD9EAC700F2DEAF;
169 | productRefGroup = 8890975E1DD9EAC700F2DEAF /* Products */;
170 | projectDirPath = "";
171 | projectRoot = "";
172 | targets = (
173 | 8890975C1DD9EAC700F2DEAF /* WSLineChart */,
174 | );
175 | };
176 | /* End PBXProject section */
177 |
178 | /* Begin PBXResourcesBuildPhase section */
179 | 8890975B1DD9EAC700F2DEAF /* Resources */ = {
180 | isa = PBXResourcesBuildPhase;
181 | buildActionMask = 2147483647;
182 | files = (
183 | 889097701DD9EAC700F2DEAF /* LaunchScreen.storyboard in Resources */,
184 | 8890976D1DD9EAC700F2DEAF /* Assets.xcassets in Resources */,
185 | 8890976B1DD9EAC700F2DEAF /* Main.storyboard in Resources */,
186 | 8882024A1DDD91D1005AF441 /* SVProgressHUD.bundle in Resources */,
187 | );
188 | runOnlyForDeploymentPostprocessing = 0;
189 | };
190 | /* End PBXResourcesBuildPhase section */
191 |
192 | /* Begin PBXSourcesBuildPhase section */
193 | 889097591DD9EAC700F2DEAF /* Sources */ = {
194 | isa = PBXSourcesBuildPhase;
195 | buildActionMask = 2147483647;
196 | files = (
197 | 889097681DD9EAC700F2DEAF /* ViewController.m in Sources */,
198 | 8882024C1DDD91D1005AF441 /* TBActivityView.m in Sources */,
199 | 888202431DDD8A33005AF441 /* YAxisView.m in Sources */,
200 | 889097651DD9EAC700F2DEAF /* AppDelegate.m in Sources */,
201 | 8882024B1DDD91D1005AF441 /* SVProgressHUD.m in Sources */,
202 | 889097621DD9EAC700F2DEAF /* main.m in Sources */,
203 | 888202401DDD8A2B005AF441 /* XAxisView.m in Sources */,
204 | 8882023D1DDD892B005AF441 /* WSLineChartView.m in Sources */,
205 | );
206 | runOnlyForDeploymentPostprocessing = 0;
207 | };
208 | /* End PBXSourcesBuildPhase section */
209 |
210 | /* Begin PBXVariantGroup section */
211 | 889097691DD9EAC700F2DEAF /* Main.storyboard */ = {
212 | isa = PBXVariantGroup;
213 | children = (
214 | 8890976A1DD9EAC700F2DEAF /* Base */,
215 | );
216 | name = Main.storyboard;
217 | sourceTree = "";
218 | };
219 | 8890976E1DD9EAC700F2DEAF /* LaunchScreen.storyboard */ = {
220 | isa = PBXVariantGroup;
221 | children = (
222 | 8890976F1DD9EAC700F2DEAF /* Base */,
223 | );
224 | name = LaunchScreen.storyboard;
225 | sourceTree = "";
226 | };
227 | /* End PBXVariantGroup section */
228 |
229 | /* Begin XCBuildConfiguration section */
230 | 889097721DD9EAC700F2DEAF /* Debug */ = {
231 | isa = XCBuildConfiguration;
232 | buildSettings = {
233 | ALWAYS_SEARCH_USER_PATHS = NO;
234 | CLANG_ANALYZER_NONNULL = YES;
235 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
236 | CLANG_CXX_LIBRARY = "libc++";
237 | CLANG_ENABLE_MODULES = YES;
238 | CLANG_ENABLE_OBJC_ARC = YES;
239 | CLANG_WARN_BOOL_CONVERSION = YES;
240 | CLANG_WARN_CONSTANT_CONVERSION = YES;
241 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
242 | CLANG_WARN_EMPTY_BODY = YES;
243 | CLANG_WARN_ENUM_CONVERSION = YES;
244 | CLANG_WARN_INT_CONVERSION = YES;
245 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
246 | CLANG_WARN_UNREACHABLE_CODE = YES;
247 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
248 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
249 | COPY_PHASE_STRIP = NO;
250 | DEBUG_INFORMATION_FORMAT = dwarf;
251 | ENABLE_STRICT_OBJC_MSGSEND = YES;
252 | ENABLE_TESTABILITY = YES;
253 | GCC_C_LANGUAGE_STANDARD = gnu99;
254 | GCC_DYNAMIC_NO_PIC = NO;
255 | GCC_NO_COMMON_BLOCKS = YES;
256 | GCC_OPTIMIZATION_LEVEL = 0;
257 | GCC_PREPROCESSOR_DEFINITIONS = (
258 | "DEBUG=1",
259 | "$(inherited)",
260 | );
261 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
262 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
263 | GCC_WARN_UNDECLARED_SELECTOR = YES;
264 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
265 | GCC_WARN_UNUSED_FUNCTION = YES;
266 | GCC_WARN_UNUSED_VARIABLE = YES;
267 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
268 | MTL_ENABLE_DEBUG_INFO = YES;
269 | ONLY_ACTIVE_ARCH = YES;
270 | SDKROOT = iphoneos;
271 | };
272 | name = Debug;
273 | };
274 | 889097731DD9EAC700F2DEAF /* Release */ = {
275 | isa = XCBuildConfiguration;
276 | buildSettings = {
277 | ALWAYS_SEARCH_USER_PATHS = NO;
278 | CLANG_ANALYZER_NONNULL = YES;
279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
280 | CLANG_CXX_LIBRARY = "libc++";
281 | CLANG_ENABLE_MODULES = YES;
282 | CLANG_ENABLE_OBJC_ARC = YES;
283 | CLANG_WARN_BOOL_CONVERSION = YES;
284 | CLANG_WARN_CONSTANT_CONVERSION = YES;
285 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
286 | CLANG_WARN_EMPTY_BODY = YES;
287 | CLANG_WARN_ENUM_CONVERSION = YES;
288 | CLANG_WARN_INT_CONVERSION = YES;
289 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
290 | CLANG_WARN_UNREACHABLE_CODE = YES;
291 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
292 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
293 | COPY_PHASE_STRIP = NO;
294 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
295 | ENABLE_NS_ASSERTIONS = NO;
296 | ENABLE_STRICT_OBJC_MSGSEND = YES;
297 | GCC_C_LANGUAGE_STANDARD = gnu99;
298 | GCC_NO_COMMON_BLOCKS = YES;
299 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
300 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
301 | GCC_WARN_UNDECLARED_SELECTOR = YES;
302 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
303 | GCC_WARN_UNUSED_FUNCTION = YES;
304 | GCC_WARN_UNUSED_VARIABLE = YES;
305 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
306 | MTL_ENABLE_DEBUG_INFO = NO;
307 | SDKROOT = iphoneos;
308 | VALIDATE_PRODUCT = YES;
309 | };
310 | name = Release;
311 | };
312 | 889097751DD9EAC700F2DEAF /* Debug */ = {
313 | isa = XCBuildConfiguration;
314 | buildSettings = {
315 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
316 | INFOPLIST_FILE = WSLineChart/Info.plist;
317 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
318 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
319 | PRODUCT_BUNDLE_IDENTIFIER = com.sinfotek.WSLineChart;
320 | PRODUCT_NAME = "$(TARGET_NAME)";
321 | };
322 | name = Debug;
323 | };
324 | 889097761DD9EAC700F2DEAF /* Release */ = {
325 | isa = XCBuildConfiguration;
326 | buildSettings = {
327 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
328 | INFOPLIST_FILE = WSLineChart/Info.plist;
329 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
330 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
331 | PRODUCT_BUNDLE_IDENTIFIER = com.sinfotek.WSLineChart;
332 | PRODUCT_NAME = "$(TARGET_NAME)";
333 | };
334 | name = Release;
335 | };
336 | /* End XCBuildConfiguration section */
337 |
338 | /* Begin XCConfigurationList section */
339 | 889097581DD9EAC700F2DEAF /* Build configuration list for PBXProject "WSLineChart" */ = {
340 | isa = XCConfigurationList;
341 | buildConfigurations = (
342 | 889097721DD9EAC700F2DEAF /* Debug */,
343 | 889097731DD9EAC700F2DEAF /* Release */,
344 | );
345 | defaultConfigurationIsVisible = 0;
346 | defaultConfigurationName = Release;
347 | };
348 | 889097741DD9EAC700F2DEAF /* Build configuration list for PBXNativeTarget "WSLineChart" */ = {
349 | isa = XCConfigurationList;
350 | buildConfigurations = (
351 | 889097751DD9EAC700F2DEAF /* Debug */,
352 | 889097761DD9EAC700F2DEAF /* Release */,
353 | );
354 | defaultConfigurationIsVisible = 0;
355 | defaultConfigurationName = Release;
356 | };
357 | /* End XCConfigurationList section */
358 | };
359 | rootObject = 889097551DD9EAC700F2DEAF /* Project object */;
360 | }
361 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/XAxisView.m:
--------------------------------------------------------------------------------
1 | //
2 | // xAxisView.m
3 | // 3333
4 | //
5 | // Created by iMac on 16/11/10.
6 | // Copyright © 2016年 zws. All rights reserved.
7 | //
8 |
9 | #import "XAxisView.h"
10 | #define topMargin 50 // 为顶部留出的空白
11 | #define kChartLineColor [UIColor grayColor]
12 | #define kChartTextColor [UIColor blackColor]
13 | #define pointColor [UIColor colorWithRed:27/255.0 green:168/255.0 blue:248/255.0 alpha:.5]
14 | #define leftMargin 45
15 | #define wsRGBA(r, g, b, a) ([UIColor colorWithRed:(r / 255.0) green:(g / 255.0) blue:(b / 255.0) alpha:a])
16 |
17 |
18 |
19 | @interface XAxisView ()
20 |
21 | @property (strong, nonatomic) NSArray *xTitleArray;
22 | @property (strong, nonatomic) NSArray *yValueArray;
23 | @property (assign, nonatomic) CGFloat yMax;
24 | @property (assign, nonatomic) CGFloat yMin;
25 | @property (strong, nonatomic) NSString *xTypeName;
26 | @property (strong, nonatomic) NSString *yTypeName;
27 | @property (strong, nonatomic) NSString *unit;
28 |
29 | @property (assign, nonatomic) CGFloat defaultSpace;//X轴点之间的间隔
30 |
31 | /**
32 | * 记录坐标轴的第一个frame
33 | */
34 | @property (assign, nonatomic) CGRect firstFrame;
35 | @property (assign, nonatomic) CGRect firstStrFrame;//第一个点的文字的frame
36 |
37 |
38 | @end
39 |
40 |
41 |
42 | @implementation XAxisView
43 |
44 | - (id)initWithFrame:(CGRect)frame xTitleArray:(NSArray*)xTitleArray yValueArray:(NSArray*)yValueArray yMax:(CGFloat)yMax yMin:(CGFloat)yMin yTypeName:(NSString*)yTypeName xTypeName:(NSString*)xTypeName unit:(NSString*)unit {
45 |
46 | self = [super initWithFrame:frame];
47 | if (self) {
48 | self.backgroundColor = [UIColor whiteColor];
49 | self.xTitleArray = xTitleArray;
50 | self.yValueArray = yValueArray;
51 | self.yMax = yMax;
52 | self.yMin = yMin;
53 | self.xTypeName = xTypeName;
54 | self.yTypeName = yTypeName;
55 | self.unit = unit;
56 |
57 | if (xTitleArray.count > 600) {
58 | _defaultSpace = 5;
59 | }
60 | else if (xTitleArray.count > 400 && xTitleArray.count <= 600){
61 | _defaultSpace = 10;
62 | }
63 | else if (xTitleArray.count > 200 && xTitleArray.count <= 400){
64 | _defaultSpace = 20;
65 | }
66 | else if (xTitleArray.count > 100 && xTitleArray.count <= 200){
67 | _defaultSpace = 30;
68 | }
69 | else if (xTitleArray.count > 10 && xTitleArray.count <= 100){
70 | _defaultSpace = 40;
71 | }
72 | else {
73 | _defaultSpace = (wsScreenWidth-leftMargin)/xTitleArray.count;
74 | }
75 |
76 |
77 | self.pointGap = (wsScreenWidth-leftMargin)/xTitleArray.count;
78 |
79 |
80 | }
81 |
82 | return self;
83 | }
84 |
85 | - (void)setPointGap:(CGFloat)pointGap {
86 | _pointGap = pointGap;
87 |
88 | [self setNeedsDisplay];
89 | }
90 |
91 | - (void)setIsLongPress:(BOOL)isLongPress {
92 | _isLongPress = isLongPress;
93 |
94 | [self setNeedsDisplay];
95 | }
96 |
97 | - (void)drawRect:(CGRect)rect {
98 | [super drawRect:rect];
99 |
100 | CGContextRef context = UIGraphicsGetCurrentContext();
101 |
102 | [self drawShadow];//画渐变色背景
103 |
104 | ////////////////////// X轴文字 //////////////////////////
105 | // 添加坐标轴Label
106 | for (int i = 0; i < self.xTitleArray.count; i++) {
107 | NSString *title = self.xTitleArray[i];
108 | title = [title stringByReplacingOccurrencesOfString:@" " withString:@"\r\n"];
109 |
110 | [[UIColor blackColor] set];
111 | NSDictionary *attr = @{NSFontAttributeName : [UIFont systemFontOfSize:10]};
112 | CGSize labelSize = [title sizeWithAttributes:attr];
113 |
114 | CGRect titleRect = CGRectMake((i + 1) * self.pointGap - labelSize.width / 2,self.frame.size.height - labelSize.height,labelSize.width,labelSize.height);
115 |
116 | if (i == 0) {
117 | self.firstFrame = titleRect;
118 | if (titleRect.origin.x < 0) {
119 | titleRect.origin.x = 0;
120 | }
121 |
122 | [title drawInRect:titleRect withAttributes:@{NSFontAttributeName :[UIFont systemFontOfSize:10],NSForegroundColorAttributeName:kChartTextColor}];
123 |
124 | //画垂直X轴的竖线
125 | [self drawLine:context
126 | startPoint:CGPointMake(titleRect.origin.x+labelSize.width/2, self.frame.size.height - labelSize.height-5)
127 | endPoint:CGPointMake(titleRect.origin.x+labelSize.width/2, self.frame.size.height - labelSize.height-10)
128 | lineColor:kChartLineColor
129 | lineWidth:1];
130 | }
131 | // 如果Label的文字有重叠,那么不绘制
132 | CGFloat maxX = CGRectGetMaxX(self.firstFrame);
133 | if (i != 0) {
134 | if ((maxX + 5) > titleRect.origin.x) {
135 | //不绘制
136 |
137 | }else{
138 |
139 | [title drawInRect:titleRect withAttributes:@{NSFontAttributeName :[UIFont systemFontOfSize:10],NSForegroundColorAttributeName:kChartTextColor}];
140 | //画垂直X轴的竖线
141 | [self drawLine:context
142 | startPoint:CGPointMake(titleRect.origin.x+labelSize.width/2, self.frame.size.height - labelSize.height-5)
143 | endPoint:CGPointMake(titleRect.origin.x+labelSize.width/2, self.frame.size.height - labelSize.height-10)
144 | lineColor:kChartLineColor
145 | lineWidth:1];
146 |
147 | self.firstFrame = titleRect;
148 | }
149 | }else {
150 | if (self.firstFrame.origin.x < 0) {
151 |
152 | CGRect frame = self.firstFrame;
153 | frame.origin.x = 0;
154 | self.firstFrame = frame;
155 | }
156 | }
157 |
158 | }
159 |
160 | //////////////// 画原点上的x轴 ///////////////////////
161 | NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:10]};
162 | CGSize textSize = [@"22-22\r\n22:22" sizeWithAttributes:attribute];
163 |
164 | [self drawLine:context
165 | startPoint:CGPointMake(0, self.frame.size.height - textSize.height - 5)
166 | endPoint:CGPointMake(self.frame.size.width, self.frame.size.height - textSize.height - 5)
167 | lineColor:kChartLineColor
168 | lineWidth:1];
169 |
170 |
171 | //////////////// 画横向分割线 ///////////////////////
172 | CGFloat separateMargin = (self.frame.size.height - topMargin - textSize.height - 5 - 5 * 1) / 5;
173 | for (int i = 0; i < 5; i++) {
174 |
175 | [self drawLine:context
176 | startPoint:CGPointMake(0, self.frame.size.height - textSize.height - 5 - (i + 1) *(separateMargin + 1))
177 | endPoint:CGPointMake(self.frame.size.width, self.frame.size.height - textSize.height - 5 - (i + 1) *(separateMargin + 1))
178 | lineColor:[UIColor lightGrayColor]
179 | lineWidth:.3];
180 | }
181 |
182 |
183 | /////////////////////// 根据数据源画折线 /////////////////////////
184 | if (self.yValueArray && self.yValueArray.count > 0) {
185 |
186 | //画折线
187 | for (NSInteger i = 0; i < self.yValueArray.count; i++) {
188 |
189 | //如果是最后一个点
190 | if (i == self.yValueArray.count-1) {
191 |
192 | NSNumber *endValue = self.yValueArray[i];
193 | CGFloat chartHeight = self.frame.size.height - textSize.height - 5 - topMargin;
194 | CGPoint endPoint = CGPointMake((i+1)*self.pointGap, chartHeight - (endValue.floatValue-self.yMin)/(self.yMax-self.yMin) * chartHeight+topMargin);
195 |
196 | //画最后一个点
197 | UIColor*aColor = pointColor; //点的颜色
198 | CGContextSetFillColorWithColor(context, aColor.CGColor);//填充颜色
199 | CGContextAddArc(context, endPoint.x, endPoint.y, 1, 0, 2*M_PI, 0); //添加一个圆
200 | CGContextDrawPath(context, kCGPathFill);//绘制填充
201 |
202 |
203 | //画点上的文字
204 | NSString *str = [self removeZeroInFloatString:[NSString stringWithFormat:@"%@",endValue]];
205 |
206 |
207 | NSDictionary *attr = @{NSFontAttributeName : [UIFont systemFontOfSize:10]};
208 | CGSize strSize = [str sizeWithAttributes:attr];
209 |
210 | CGRect strRect = CGRectMake(endPoint.x-strSize.width/2,endPoint.y-strSize.height,strSize.width,strSize.height);
211 |
212 | // 如果点的文字有重叠,那么不绘制
213 | CGFloat maxX = CGRectGetMaxX(self.firstStrFrame);
214 | if (i != 0) {
215 | if ((maxX + 6) > strRect.origin.x) {
216 | //不绘制
217 |
218 | }else{
219 | [str drawInRect:strRect withAttributes:@{NSFontAttributeName :[UIFont systemFontOfSize:10],NSForegroundColorAttributeName:kChartTextColor}];
220 |
221 | self.firstStrFrame = strRect;
222 | }
223 | }else {
224 | if (self.firstStrFrame.origin.x < 0) {
225 |
226 | CGRect frame = self.firstStrFrame;
227 | frame.origin.x = 0;
228 | self.firstStrFrame = frame;
229 | }
230 | }
231 |
232 | }else {
233 |
234 | NSNumber *startValue = self.yValueArray[i];
235 | NSNumber *endValue = self.yValueArray[i+1];
236 | CGFloat chartHeight = self.frame.size.height - textSize.height - 5 - topMargin;
237 |
238 | CGPoint startPoint = CGPointMake((i+1)*self.pointGap, chartHeight - (startValue.floatValue-self.yMin)/(self.yMax-self.yMin) * chartHeight+topMargin);
239 | CGPoint endPoint = CGPointMake((i+2)*self.pointGap, chartHeight - (endValue.floatValue-self.yMin)/(self.yMax-self.yMin) * chartHeight+topMargin);
240 |
241 | CGFloat normal[1]={1};
242 | CGContextSetLineDash(context,0,normal,0); //画实线
243 |
244 | [self drawLine:context startPoint:startPoint endPoint:endPoint lineColor:[UIColor colorWithRed:26/255.0 green:135/255.0 blue:254/255.0 alpha:1] lineWidth:1];
245 |
246 |
247 | //画点
248 | UIColor*aColor = pointColor; //点的颜色
249 | CGContextSetFillColorWithColor(context, aColor.CGColor);//填充颜色
250 | CGContextAddArc(context, startPoint.x, startPoint.y, 1, 0, 2*M_PI, 0); //添加一个圆
251 | CGContextDrawPath(context, kCGPathFill);//绘制填充
252 |
253 |
254 | if (!_isShowLabel) {
255 |
256 | //画点上的文字
257 | NSString *str = [self removeZeroInFloatString:[NSString stringWithFormat:@"%@",startValue]];
258 |
259 |
260 | NSDictionary *attr = @{NSFontAttributeName : [UIFont systemFontOfSize:10]};
261 | CGSize strSize = [str sizeWithAttributes:attr];
262 |
263 | CGRect strRect = CGRectMake(startPoint.x-strSize.width/2,startPoint.y-strSize.height,strSize.width,strSize.height);
264 | if (i == 0) {
265 | self.firstStrFrame = strRect;
266 | if (strRect.origin.x < 0) {
267 | strRect.origin.x = 0;
268 | }
269 |
270 | [str drawInRect:strRect withAttributes:@{NSFontAttributeName :[UIFont systemFontOfSize:10],NSForegroundColorAttributeName:kChartTextColor}];
271 | }
272 | // 如果点的文字有重叠,那么不绘制
273 | CGFloat maxX = CGRectGetMaxX(self.firstStrFrame);
274 | if (i != 0) {
275 | if ((maxX + 6) > strRect.origin.x) {
276 |
277 | }else{
278 |
279 | [str drawInRect:strRect withAttributes:@{NSFontAttributeName :[UIFont systemFontOfSize:10],NSForegroundColorAttributeName:kChartTextColor}];
280 |
281 | self.firstStrFrame = strRect;
282 | }
283 | }else {
284 | if (self.firstStrFrame.origin.x < 0) {
285 |
286 | CGRect frame = self.firstStrFrame;
287 | frame.origin.x = 0;
288 | self.firstStrFrame = frame;
289 | }
290 | }
291 | }
292 | }
293 |
294 |
295 | }
296 | }
297 |
298 |
299 | //长按时进入
300 | if(self.isLongPress)
301 | {
302 | int nowPoint = _currentLoc.x/self.pointGap;
303 | if(nowPoint >= 0 && nowPoint < [self.yValueArray count]) {
304 |
305 | NSNumber *num = [self.yValueArray objectAtIndex:nowPoint];
306 | CGFloat chartHeight = self.frame.size.height - textSize.height - 5 - topMargin;
307 |
308 | CGPoint selectPoint = CGPointMake((nowPoint+1)*self.pointGap, chartHeight - (num.floatValue-self.yMin)/(self.yMax-self.yMin) * chartHeight+topMargin);
309 |
310 |
311 | CGContextSaveGState(context);
312 |
313 |
314 | //计算文字最大长度,以便于设置背景宽度
315 | CGFloat timeWidth = [[NSString stringWithFormat:@"%@:%@",self.xTypeName,self.xTitleArray[nowPoint]] sizeWithAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:13],NSForegroundColorAttributeName:[UIColor whiteColor]}].width;
316 | CGFloat dataWidth = [[NSString stringWithFormat:@"%@:%@%@", self.yTypeName,[NSString stringWithFormat:@"%@",num],self.unit] sizeWithAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:13],NSForegroundColorAttributeName:[UIColor whiteColor]}].width;
317 | CGFloat with = timeWidth > dataWidth ? timeWidth : dataWidth;
318 | CGFloat shadowWith = with+20;
319 |
320 | //画文字所在的位置 动态变化
321 | CGPoint drawPoint = CGPointZero;
322 | if(_screenLoc.x-shadowWith/2 > 0 && _screenLoc.x
323 | +shadowWith/2 < wsScreenWidth-leftMargin) {
324 | //如果按住的位置在屏幕靠右边边并且在屏幕靠上面的地方 那么字就显示在按住位置的左上角40 60位置
325 | drawPoint = CGPointMake(selectPoint.x-shadowWith/2, selectPoint.y-45);
326 | }
327 | else if(_screenLoc.x >((wsScreenWidth-leftMargin)/2)) {
328 | //如果按住的位置在屏幕靠右边边并且在屏幕靠上面的地方 那么字就显示在按住位置的左上角40 60位置
329 | drawPoint = CGPointMake(selectPoint.x-shadowWith-5, selectPoint.y-20);
330 | }
331 | else if (_screenLoc.x <= ((wsScreenWidth-leftMargin)/2)) {
332 | //如果按住的位置在屏幕靠左边边并且在屏幕靠上面的地方 那么字就显示在按住位置的右上角上角40 40位置
333 | drawPoint = CGPointMake(selectPoint.x+5, selectPoint.y-20);
334 |
335 | }
336 |
337 | //画竖线
338 | [self drawLine:context startPoint:CGPointMake(selectPoint.x, 0) endPoint:CGPointMake(selectPoint.x, self.frame.size.height- textSize.height - 5) lineColor:[UIColor lightGrayColor] lineWidth:1];
339 |
340 | // 交界点
341 | CGRect myOval = {selectPoint.x-2, selectPoint.y-2, 4, 4};
342 | CGContextSetFillColorWithColor(context, [UIColor orangeColor].CGColor);
343 | CGContextAddEllipseInRect(context, myOval);
344 | CGContextFillPath(context);
345 |
346 |
347 | //设置数据背景,放在竖线之后加载,不会被竖线遮住
348 | CGContextSetFillColorWithColor(context, wsRGBA(1, 0, 0, 0.5).CGColor);
349 | CGPathRef clippath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(drawPoint.x, drawPoint.y, with+20, 40) cornerRadius:10].CGPath;
350 | CGContextAddPath(context, clippath);
351 | CGContextClosePath(context);
352 | CGContextDrawPath(context, kCGPathFill);
353 |
354 | [[NSString stringWithFormat:@"%@:%@",self.xTypeName,self.xTitleArray[nowPoint]] drawInRect:CGRectMake(drawPoint.x+10, drawPoint.y+5, with, 15) withAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:13],NSForegroundColorAttributeName:[UIColor whiteColor]}];
355 | [[NSString stringWithFormat:@"%@:%@%@", self.yTypeName,[NSString stringWithFormat:@"%@",num],self.unit] drawInRect:CGRectMake(drawPoint.x+10, drawPoint.y+20, with, 15) withAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:13],NSForegroundColorAttributeName:[UIColor whiteColor]}];
356 |
357 |
358 |
359 | }
360 | }
361 |
362 |
363 |
364 | }
365 |
366 | - (void)drawShadow {
367 | CGContextRef context = UIGraphicsGetCurrentContext();
368 | CGMutablePathRef path = CGPathCreateMutable();
369 | NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:10]};
370 | CGSize textSize = [@"22-22\r\n22:22" sizeWithAttributes:attribute];
371 |
372 | CGPathMoveToPoint(path, NULL, self.pointGap, self.frame.size.height - textSize.height-5);
373 | NSNumber *startValue = self.yValueArray[0];
374 | CGFloat chartHeight = self.frame.size.height - textSize.height - 5 - topMargin;
375 | CGPoint firstStartPoint = CGPointMake(self.pointGap, chartHeight - (startValue.floatValue-self.yMin)/(self.yMax-self.yMin) * chartHeight+topMargin);
376 | CGPathAddCurveToPoint(path, NULL,(self.pointGap+firstStartPoint.x)/2, self.pointGap, (self.pointGap+firstStartPoint.x)/2, firstStartPoint.y, firstStartPoint.x, firstStartPoint.y);
377 |
378 |
379 | //画折线
380 | for (NSInteger i = 0; i < self.yValueArray.count; i++) {
381 | CGFloat chartHeight = self.frame.size.height - textSize.height - 5 - topMargin;
382 | NSNumber *startValue = self.yValueArray[i];
383 | CGPoint startPoint = CGPointMake((i+1)*self.pointGap, chartHeight - (startValue.floatValue-self.yMin)/(self.yMax-self.yMin) * chartHeight+topMargin);
384 |
385 | if (i == self.yValueArray.count-1) {
386 | CGPathAddLineToPoint(path, NULL, startPoint.x,startPoint.y);
387 | }
388 | else {
389 | NSNumber *endValue = self.yValueArray[i+1];
390 | CGPoint endPoint = CGPointMake((i+2)*self.pointGap, chartHeight - (endValue.floatValue-self.yMin)/(self.yMax-self.yMin) * chartHeight+topMargin);
391 |
392 | CGPathAddCurveToPoint(path, NULL,(startPoint.x+endPoint.x)/2, startPoint.y, (startPoint.x+endPoint.x)/2, endPoint.y, endPoint.x, endPoint.y);
393 | }
394 |
395 | }
396 |
397 | CGPathAddLineToPoint(path, NULL, self.pointGap*self.yValueArray.count, self.frame.size.height - textSize.height-5);
398 | CGPathCloseSubpath(path);
399 | //绘制渐变
400 | [self drawLinearGradient:context path:path startColor:[UIColor colorWithRed:26/255.0 green:135/255.0 blue:254/255.0 alpha:1].CGColor endColor:[UIColor whiteColor].CGColor];
401 | //注意释放CGMutablePathRef
402 | CGPathRelease(path);
403 | }
404 |
405 |
406 | - (void)drawLine:(CGContextRef)context startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint lineColor:(UIColor *)lineColor lineWidth:(CGFloat)width {
407 |
408 | CGContextSetShouldAntialias(context, YES ); //抗锯齿
409 | CGColorSpaceRef Linecolorspace1 = CGColorSpaceCreateDeviceRGB();
410 | CGContextSetStrokeColorSpace(context, Linecolorspace1);
411 | CGContextSetLineWidth(context, width);
412 | CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
413 | CGContextMoveToPoint(context, startPoint.x, startPoint.y);
414 | // CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
415 | CGContextAddCurveToPoint(context, (startPoint.x+endPoint.x)/2, startPoint.y, (startPoint.x+endPoint.x)/2, endPoint.y, endPoint.x, endPoint.y);
416 | CGContextStrokePath(context);
417 | CGColorSpaceRelease(Linecolorspace1);
418 |
419 | }
420 |
421 |
422 | - (void)drawLinearGradient:(CGContextRef)context path:(CGPathRef)path startColor:(CGColorRef)startColor endColor:(CGColorRef)endColor{
423 |
424 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
425 | CGFloat locations[] = { 0.0, 1.0 };
426 | NSArray *colors = @[(__bridge id) startColor, (__bridge id) endColor];
427 | CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);
428 | CGRect pathRect = CGPathGetBoundingBox(path);
429 | //具体方向可根据需求修改
430 | CGPoint startPoint = CGPointMake(CGRectGetMidX(pathRect), CGRectGetMinY(pathRect));
431 | CGPoint endPoint = CGPointMake(CGRectGetMidX(pathRect), CGRectGetMaxY(pathRect));
432 | CGContextSaveGState(context);
433 | CGContextAddPath(context, path);
434 | CGContextClip(context);
435 | CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
436 | CGContextRestoreGState(context);
437 | CGGradientRelease(gradient);
438 | CGColorSpaceRelease(colorSpace);
439 | }
440 |
441 | //去掉小数点之后的无效0;
442 | -(NSString*)removeZeroInFloatString:(NSString*)floatString {
443 | NSString *outNumber = [NSString stringWithFormat:@"%@",@(floatString.longLongValue)];
444 | return outNumber;
445 | }
446 |
447 | @end
448 |
--------------------------------------------------------------------------------
/WSLineChart/WSLineChart/WSLineChartView/SVProgressHUD/SVProgressHUD.m:
--------------------------------------------------------------------------------
1 | //
2 | // SVProgressHUD.m
3 | //
4 | // Created by Sam Vermette on 27.03.11.
5 | // Copyright 2011 Sam Vermette. All rights reserved.
6 | //
7 | // https://github.com/samvermette/SVProgressHUD
8 | //
9 |
10 | #if !__has_feature(objc_arc)
11 | #error SVProgressHUD is ARC only. Either turn on ARC for the project or use -fobjc-arc flag
12 | #endif
13 |
14 | #import "SVProgressHUD.h"
15 | #import
16 | #import "TBActivityView.h"
17 |
18 | NSString * const SVProgressHUDDidReceiveTouchEventNotification = @"SVProgressHUDDidReceiveTouchEventNotification";
19 | NSString * const SVProgressHUDWillDisappearNotification = @"SVProgressHUDWillDisappearNotification";
20 | NSString * const SVProgressHUDDidDisappearNotification = @"SVProgressHUDDidDisappearNotification";
21 | NSString * const SVProgressHUDWillAppearNotification = @"SVProgressHUDWillAppearNotification";
22 | NSString * const SVProgressHUDDidAppearNotification = @"SVProgressHUDDidAppearNotification";
23 |
24 | NSString * const SVProgressHUDStatusUserInfoKey = @"SVProgressHUDStatusUserInfoKey";
25 |
26 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
27 | CGFloat SVProgressHUDRingRadius = 3;
28 | CGFloat SVProgressHUDRingThickness = 1;
29 | #else
30 | CGFloat SVProgressHUDRingRadius = 3;
31 | CGFloat SVProgressHUDRingThickness = 6;
32 | #endif
33 |
34 | @interface SVProgressHUD ()
35 |
36 | @property (nonatomic, readwrite) SVProgressHUDMaskType maskType;
37 | @property (nonatomic, strong, readonly) NSTimer *fadeOutTimer;
38 | @property (nonatomic, readonly, getter = isClear) BOOL clear;
39 |
40 | @property (nonatomic, strong, readonly) UIControl *overlayView;
41 | @property (nonatomic, strong, readonly) UIView *hudView;
42 | @property (nonatomic, strong, readonly) UILabel *stringLabel;
43 | @property (nonatomic, strong, readonly) UIImageView *imageView;
44 | @property (nonatomic, strong, readonly) TBActivityView *spinnerView;
45 |
46 | @property (nonatomic, readwrite) CGFloat progress;
47 | @property (nonatomic, readwrite) NSUInteger activityCount;
48 | @property (nonatomic, strong) CAShapeLayer *backgroundRingLayer;
49 | @property (nonatomic, strong) CAShapeLayer *ringLayer;
50 |
51 | @property (nonatomic, readonly) CGFloat visibleKeyboardHeight;
52 | @property (nonatomic, assign) UIOffset offsetFromCenter;
53 |
54 | - (void)showProgress:(float)progress
55 | status:(NSString*)string
56 | maskType:(SVProgressHUDMaskType)hudMaskType;
57 |
58 | - (void)showImage:(UIImage*)image
59 | status:(NSString*)status
60 | duration:(NSTimeInterval)duration;
61 |
62 | - (void)dismiss;
63 |
64 | - (void)setStatus:(NSString*)string;
65 | - (void)registerNotifications;
66 | - (NSDictionary *)notificationUserInfo;
67 | - (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle;
68 | - (void)positionHUD:(NSNotification*)notification;
69 | - (NSTimeInterval)displayDurationForString:(NSString*)string;
70 |
71 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < 50000
72 | - (UIColor *)hudBackgroundColor;
73 | - (UIColor *)hudForegroundColor;
74 | - (UIColor *)hudStatusShadowColor;
75 | - (UIColor *)hudRingBackgroundColor;
76 | - (UIColor *)hudRingForegroundColor;
77 | - (UIFont *)hudFont;
78 | - (UIImage *)hudSuccessImage;
79 | - (UIImage *)hudErrorImage;
80 | #endif
81 |
82 | @end
83 |
84 |
85 | @implementation SVProgressHUD
86 |
87 | @synthesize overlayView, hudView, maskType, fadeOutTimer, stringLabel, imageView, spinnerView, visibleKeyboardHeight;
88 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
89 | @synthesize hudBackgroundColor = _uiHudBgColor;
90 | @synthesize hudForegroundColor = _uiHudFgColor;
91 | @synthesize hudStatusShadowColor = _uiHudStatusShColor;
92 | @synthesize hudRingBackgroundColor = _uiHudRingBgColor;
93 | @synthesize hudRingForegroundColor = _uiHudRingFgColor;
94 | @synthesize hudFont = _uiHudFont;
95 | @synthesize hudSuccessImage = _uiHudSuccessImage;
96 | @synthesize hudErrorImage = _uiHudErrorImage;
97 | #endif
98 |
99 |
100 | + (SVProgressHUD*)sharedView {
101 | static dispatch_once_t once;
102 | static SVProgressHUD *sharedView;
103 | dispatch_once(&once, ^ { sharedView = [[self alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; });
104 | return sharedView;
105 | }
106 |
107 |
108 | + (void)setStatus:(NSString *)string {
109 | [[self sharedView] setStatus:string];
110 | }
111 |
112 | #pragma mark - Show Methods
113 |
114 | + (void)show {
115 | [[self sharedView] showProgress:-1 status:nil maskType:SVProgressHUDMaskTypeNone];
116 | }
117 |
118 | + (void)showWithStatus:(NSString *)status {
119 | [[self sharedView] showProgress:-1 status:status maskType:SVProgressHUDMaskTypeNone];
120 | }
121 |
122 | + (void)showWithMaskType:(SVProgressHUDMaskType)maskType {
123 | [[self sharedView] showProgress:-1 status:nil maskType:maskType];
124 | }
125 |
126 | + (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType {
127 | [[self sharedView] showProgress:-1 status:status maskType:maskType];
128 | }
129 |
130 | + (void)showProgress:(float)progress {
131 | [[self sharedView] showProgress:progress status:nil maskType:SVProgressHUDMaskTypeNone];
132 | }
133 |
134 | + (void)showProgress:(float)progress status:(NSString *)status {
135 | [[self sharedView] showProgress:progress status:status maskType:SVProgressHUDMaskTypeNone];
136 | }
137 |
138 | + (void)showProgress:(float)progress status:(NSString *)status maskType:(SVProgressHUDMaskType)maskType {
139 | [[self sharedView] showProgress:progress status:status maskType:maskType];
140 | }
141 |
142 | #pragma mark - Show then dismiss methods
143 |
144 | + (void)showSuccessWithStatus:(NSString *)string {
145 | [self showImage:[[self sharedView] hudSuccessImage] status:string];
146 | }
147 |
148 | + (void)showErrorWithStatus:(NSString *)string {
149 | NSTimeInterval displayInterval = [[SVProgressHUD sharedView] displayDurationForString:string];
150 | [[self sharedView] showStringWithStatus:string duration:displayInterval];
151 | }
152 |
153 | + (void)showImage:(UIImage *)image status:(NSString *)string {
154 | NSTimeInterval displayInterval = [[SVProgressHUD sharedView] displayDurationForString:string];
155 | [[self sharedView] showImage:image status:string duration:displayInterval];
156 | }
157 |
158 | -(void)showStringWithStatus:(NSString *)string duration:(NSTimeInterval )duration{
159 | self.progress = -1;
160 | [self cancelRingLayerAnimation];
161 |
162 | if(![self.class isVisible])
163 | [self.class show];
164 |
165 | self.imageView.image=nil;
166 | self.imageView.hidden = NO;
167 |
168 | self.stringLabel.text = string;
169 | [self updatePosition];
170 | [self.spinnerView stopAnimate];
171 |
172 | if(self.maskType != SVProgressHUDMaskTypeNone) {
173 | self.accessibilityLabel = string;
174 | self.isAccessibilityElement = YES;
175 | } else {
176 | self.hudView.accessibilityLabel = string;
177 | self.hudView.isAccessibilityElement = YES;
178 | }
179 |
180 | UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
181 | UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, string);
182 |
183 | self.fadeOutTimer = [NSTimer timerWithTimeInterval:duration target:self selector:@selector(dismiss) userInfo:nil repeats:NO];
184 | [[NSRunLoop mainRunLoop] addTimer:self.fadeOutTimer forMode:NSRunLoopCommonModes];
185 | }
186 | #pragma mark - Dismiss Methods
187 |
188 | + (void)popActivity {
189 | [self sharedView].activityCount--;
190 | if([self sharedView].activityCount == 0)
191 | [[self sharedView] dismiss];
192 | }
193 |
194 | + (void)dismiss {
195 | if ([self isVisible]) {
196 | [[self sharedView] dismiss];
197 | }
198 | }
199 |
200 |
201 | #pragma mark - Offset
202 |
203 | + (void)setOffsetFromCenter:(UIOffset)offset {
204 | [self sharedView].offsetFromCenter = offset;
205 | }
206 |
207 | + (void)resetOffsetFromCenter {
208 | [self setOffsetFromCenter:UIOffsetZero];
209 | }
210 |
211 | #pragma mark - Instance Methods
212 |
213 | - (id)initWithFrame:(CGRect)frame {
214 |
215 | if ((self = [super initWithFrame:frame])) {
216 | self.userInteractionEnabled = NO;
217 | self.backgroundColor = [UIColor clearColor];
218 | self.alpha = 0;
219 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
220 | self.activityCount = 0;
221 | }
222 |
223 | return self;
224 | }
225 |
226 | - (void)drawRect:(CGRect)rect {
227 |
228 | CGContextRef context = UIGraphicsGetCurrentContext();
229 |
230 | switch (self.maskType) {
231 |
232 | case SVProgressHUDMaskTypeBlack: {
233 | [[UIColor colorWithWhite:0 alpha:0.5] set];
234 | CGContextFillRect(context, self.bounds);
235 | break;
236 | }
237 |
238 | case SVProgressHUDMaskTypeGradient: {
239 |
240 | size_t locationsCount = 2;
241 | CGFloat locations[2] = {0.0f, 1.0f};
242 | CGFloat colors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.75f};
243 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
244 | CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount);
245 | CGColorSpaceRelease(colorSpace);
246 |
247 | CGFloat freeHeight = self.bounds.size.height - self.visibleKeyboardHeight;
248 |
249 | CGPoint center = CGPointMake(self.bounds.size.width/2, freeHeight/2);
250 | float radius = MIN(self.bounds.size.width , self.bounds.size.height) ;
251 | CGContextDrawRadialGradient (context, gradient, center, 0, center, radius, kCGGradientDrawsAfterEndLocation);
252 | CGGradientRelease(gradient);
253 |
254 | break;
255 | }
256 | }
257 | }
258 |
259 | - (void)updatePosition {
260 |
261 | CGFloat hudWidth = 100;
262 | CGFloat hudHeight = 100;
263 | CGFloat stringHeightBuffer = 20;
264 | CGFloat stringAndImageHeightBuffer = 80;
265 |
266 | CGFloat stringWidth = 0;
267 | CGFloat stringHeight = 0;
268 | CGRect labelRect = CGRectZero;
269 |
270 | NSString *string = self.stringLabel.text;
271 | // False if it's text-only
272 | BOOL imageUsed = (self.imageView.image) || (self.imageView.hidden);
273 |
274 | if(string) {
275 | CGSize constraintSize = CGSizeMake(200, 300);
276 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
277 | CGRect stringRect = [string boundingRectWithSize:constraintSize options:(NSStringDrawingUsesFontLeading|NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin) attributes:@{NSFontAttributeName: self.stringLabel.font} context:NULL];
278 | stringWidth = stringRect.size.width;
279 | stringHeight = stringRect.size.height;
280 | #else
281 | CGSize stringSize = [string sizeWithFont:self.stringLabel.font constrainedToSize:constraintSize];
282 | stringWidth = stringSize.width;
283 | stringHeight = stringSize.height;
284 | #endif
285 |
286 | if (imageUsed)
287 | hudHeight = stringAndImageHeightBuffer + stringHeight;
288 | else
289 | hudHeight = stringHeightBuffer + stringHeight;
290 |
291 | if(stringWidth >= hudWidth)
292 | hudWidth = ceil(stringWidth/2)*2;
293 | hudWidth+=20;
294 | CGFloat labelRectY = imageUsed ? 66 : 9;
295 |
296 | // if(hudHeight > 100) {
297 | labelRect = CGRectMake(12, labelRectY, hudWidth, stringHeight);
298 | hudWidth+=24;
299 | // } else {
300 | // hudWidth+=24;
301 | // labelRect = CGRectMake(0, labelRectY, hudWidth, stringHeight);
302 | // }
303 | }
304 |
305 | self.hudView.bounds = CGRectMake(0, 0, hudWidth, hudHeight);
306 |
307 | if(string)
308 | self.imageView.center = CGPointMake(CGRectGetWidth(self.hudView.bounds)/2, 36);
309 | else
310 | self.imageView.center = CGPointMake(CGRectGetWidth(self.hudView.bounds)/2, CGRectGetHeight(self.hudView.bounds)/2);
311 |
312 | self.stringLabel.hidden = NO;
313 | self.stringLabel.frame = labelRect;
314 |
315 | if(string) {
316 | self.spinnerView.center = CGPointMake(ceil(CGRectGetWidth(self.hudView.bounds)/2)+0.5, 40.5);
317 |
318 | if(self.progress != -1)
319 | self.backgroundRingLayer.position = self.ringLayer.position = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), 36);
320 | }
321 | else {
322 | self.spinnerView.center = CGPointMake(ceil(CGRectGetWidth(self.hudView.bounds)/2)+0.5, ceil(self.hudView.bounds.size.height/2)+0.5);
323 |
324 | if(self.progress != -1)
325 | self.backgroundRingLayer.position = self.ringLayer.position = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), CGRectGetHeight(self.hudView.bounds)/2);
326 | }
327 |
328 | }
329 |
330 | - (void)setStatus:(NSString *)string {
331 |
332 | self.stringLabel.text = string;
333 | [self updatePosition];
334 |
335 | }
336 |
337 | - (void)setFadeOutTimer:(NSTimer *)newTimer {
338 |
339 | if(fadeOutTimer)
340 | [fadeOutTimer invalidate], fadeOutTimer = nil;
341 |
342 | if(newTimer)
343 | fadeOutTimer = newTimer;
344 | }
345 |
346 |
347 | - (void)registerNotifications {
348 | [[NSNotificationCenter defaultCenter] addObserver:self
349 | selector:@selector(positionHUD:)
350 | name:UIApplicationDidChangeStatusBarOrientationNotification
351 | object:nil];
352 |
353 | [[NSNotificationCenter defaultCenter] addObserver:self
354 | selector:@selector(positionHUD:)
355 | name:UIKeyboardWillHideNotification
356 | object:nil];
357 |
358 | [[NSNotificationCenter defaultCenter] addObserver:self
359 | selector:@selector(positionHUD:)
360 | name:UIKeyboardDidHideNotification
361 | object:nil];
362 |
363 | [[NSNotificationCenter defaultCenter] addObserver:self
364 | selector:@selector(positionHUD:)
365 | name:UIKeyboardWillShowNotification
366 | object:nil];
367 |
368 | [[NSNotificationCenter defaultCenter] addObserver:self
369 | selector:@selector(positionHUD:)
370 | name:UIKeyboardDidShowNotification
371 | object:nil];
372 | }
373 |
374 |
375 | - (NSDictionary *)notificationUserInfo
376 | {
377 | return (self.stringLabel.text ? @{SVProgressHUDStatusUserInfoKey : self.stringLabel.text} : nil);
378 | }
379 |
380 |
381 | - (void)positionHUD:(NSNotification*)notification {
382 |
383 | CGFloat keyboardHeight;
384 | double animationDuration = 0.0;
385 |
386 | UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
387 |
388 | if(notification) {
389 | NSDictionary* keyboardInfo = [notification userInfo];
390 | CGRect keyboardFrame = [[keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
391 | animationDuration = [[keyboardInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
392 |
393 | if(notification.name == UIKeyboardWillShowNotification || notification.name == UIKeyboardDidShowNotification) {
394 | if(UIInterfaceOrientationIsPortrait(orientation))
395 | keyboardHeight = keyboardFrame.size.height;
396 | else
397 | keyboardHeight = keyboardFrame.size.width;
398 | } else
399 | keyboardHeight = 0;
400 | } else {
401 | keyboardHeight = self.visibleKeyboardHeight;
402 | }
403 |
404 | CGRect orientationFrame = [UIScreen mainScreen].bounds;
405 | CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
406 |
407 | if(UIInterfaceOrientationIsLandscape(orientation)) {
408 | float temp = orientationFrame.size.width;
409 | orientationFrame.size.width = orientationFrame.size.height;
410 | orientationFrame.size.height = temp;
411 |
412 | temp = statusBarFrame.size.width;
413 | statusBarFrame.size.width = statusBarFrame.size.height;
414 | statusBarFrame.size.height = temp;
415 | }
416 |
417 | CGFloat activeHeight = orientationFrame.size.height;
418 |
419 | if(keyboardHeight > 0)
420 | activeHeight += statusBarFrame.size.height*2;
421 |
422 | activeHeight -= keyboardHeight;
423 | CGFloat posY = floor(activeHeight*0.45);
424 | CGFloat posX = orientationFrame.size.width/2;
425 |
426 | CGPoint newCenter;
427 | CGFloat rotateAngle;
428 |
429 | switch (orientation) {
430 | case UIInterfaceOrientationPortraitUpsideDown:
431 | rotateAngle = M_PI;
432 | newCenter = CGPointMake(posX, orientationFrame.size.height-posY);
433 | break;
434 | case UIInterfaceOrientationLandscapeLeft:
435 | rotateAngle = -M_PI/2.0f;
436 | newCenter = CGPointMake(posY, posX);
437 | break;
438 | case UIInterfaceOrientationLandscapeRight:
439 | rotateAngle = M_PI/2.0f;
440 | newCenter = CGPointMake(orientationFrame.size.height-posY, posX);
441 | break;
442 | default: // as UIInterfaceOrientationPortrait
443 | rotateAngle = 0.0;
444 | newCenter = CGPointMake(posX, posY);
445 | break;
446 | }
447 |
448 | if(notification) {
449 | [UIView animateWithDuration:animationDuration
450 | delay:0
451 | options:UIViewAnimationOptionAllowUserInteraction
452 | animations:^{
453 | [self moveToPoint:newCenter rotateAngle:rotateAngle];
454 | } completion:NULL];
455 | }
456 |
457 | else {
458 | [self moveToPoint:newCenter rotateAngle:rotateAngle];
459 | }
460 |
461 | }
462 |
463 | - (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle {
464 | self.hudView.transform = CGAffineTransformMakeRotation(angle);
465 | self.hudView.center = CGPointMake(newCenter.x + self.offsetFromCenter.horizontal, newCenter.y + self.offsetFromCenter.vertical);
466 | }
467 |
468 | - (void)overlayViewDidReceiveTouchEvent:(id)sender forEvent:(UIEvent *)event {
469 | [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidReceiveTouchEventNotification object:event];
470 | }
471 |
472 | #pragma mark - Master show/dismiss methods
473 |
474 | - (void)showProgress:(float)progress status:(NSString*)string maskType:(SVProgressHUDMaskType)hudMaskType {
475 |
476 | if(!self.overlayView.superview){
477 | NSEnumerator *frontToBackWindows = [[[UIApplication sharedApplication]windows]reverseObjectEnumerator];
478 |
479 | for (UIWindow *window in frontToBackWindows)
480 | if (window.windowLevel == UIWindowLevelNormal) {
481 | [window addSubview:self.overlayView];
482 | break;
483 | }
484 | }
485 |
486 | if(!self.superview)
487 | [self.overlayView addSubview:self];
488 |
489 | self.fadeOutTimer = nil;
490 | self.imageView.hidden = YES;
491 | self.maskType = hudMaskType;
492 | self.progress = progress;
493 |
494 | self.stringLabel.text = string;
495 | [self updatePosition];
496 |
497 | if(progress >= 0) {
498 | self.imageView.image = nil;
499 | self.imageView.hidden = NO;
500 | [self.spinnerView stopAnimate];
501 | self.ringLayer.strokeEnd = progress;
502 |
503 | if(progress == 0)
504 | self.activityCount++;
505 | }
506 | else {
507 | self.activityCount++;
508 | [self cancelRingLayerAnimation];
509 | [self.spinnerView startAnimate];
510 | }
511 |
512 | if(self.maskType != SVProgressHUDMaskTypeNone) {
513 | self.overlayView.userInteractionEnabled = YES;
514 | self.accessibilityLabel = string;
515 | self.isAccessibilityElement = YES;
516 | }
517 | else {
518 | self.overlayView.userInteractionEnabled = NO;
519 | self.hudView.accessibilityLabel = string;
520 | self.hudView.isAccessibilityElement = YES;
521 | }
522 |
523 | [self.overlayView setHidden:NO];
524 | [self positionHUD:nil];
525 |
526 | if(self.alpha != 1) {
527 | NSDictionary *userInfo = [self notificationUserInfo];
528 | [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillAppearNotification
529 | object:nil
530 | userInfo:userInfo];
531 |
532 | [self registerNotifications];
533 | self.hudView.transform = CGAffineTransformScale(self.hudView.transform, 1.3, 1.3);
534 |
535 | if(self.isClear) {
536 | self.alpha = 1;
537 | self.hudView.alpha = 0;
538 | }
539 |
540 | [UIView animateWithDuration:0.15
541 | delay:0
542 | options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState
543 | animations:^{
544 | self.hudView.transform = CGAffineTransformScale(self.hudView.transform, 1/1.3, 1/1.3);
545 |
546 | if(self.isClear){ // handle iOS 7 UIToolbar not answer well to hierarchy opacity change
547 | self.hudView.alpha = 1;
548 | }
549 | else
550 | self.alpha = 1;
551 | }
552 | completion:^(BOOL finished){
553 | [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidAppearNotification
554 | object:nil
555 | userInfo:userInfo];
556 | UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
557 | UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, string);
558 | }];
559 |
560 | [self setNeedsDisplay];
561 | }
562 | }
563 |
564 |
565 | - (void)showImage:(UIImage *)image status:(NSString *)string duration:(NSTimeInterval)duration {
566 | self.progress = -1;
567 | [self cancelRingLayerAnimation];
568 |
569 | if(![self.class isVisible])
570 | [self.class show];
571 |
572 | self.imageView.image = image;
573 | self.imageView.hidden = NO;
574 |
575 | self.stringLabel.text = string;
576 | [self updatePosition];
577 | [self.spinnerView stopAnimate];
578 |
579 | if(self.maskType != SVProgressHUDMaskTypeNone) {
580 | self.accessibilityLabel = string;
581 | self.isAccessibilityElement = YES;
582 | } else {
583 | self.hudView.accessibilityLabel = string;
584 | self.hudView.isAccessibilityElement = YES;
585 | }
586 |
587 | UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
588 | UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, string);
589 |
590 | self.fadeOutTimer = [NSTimer timerWithTimeInterval:duration target:self selector:@selector(dismiss) userInfo:nil repeats:NO];
591 | [[NSRunLoop mainRunLoop] addTimer:self.fadeOutTimer forMode:NSRunLoopCommonModes];
592 | }
593 |
594 | - (void)dismiss {
595 | NSDictionary *userInfo = [self notificationUserInfo];
596 | [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillDisappearNotification
597 | object:nil
598 | userInfo:userInfo];
599 |
600 | self.activityCount = 0;
601 | [UIView animateWithDuration:0.15
602 | delay:0
603 | options:UIViewAnimationCurveEaseIn | UIViewAnimationOptionAllowUserInteraction
604 | animations:^{
605 | self.hudView.transform = CGAffineTransformScale(self.hudView.transform, 0.8, 0.8);
606 | if(self.isClear) // handle iOS 7 UIToolbar not answer well to hierarchy opacity change
607 | self.hudView.alpha = 0;
608 | else
609 | self.alpha = 0;
610 | }
611 | completion:^(BOOL finished){
612 | if(self.alpha == 0 || self.hudView.alpha == 0) {
613 | self.alpha = 0;
614 | self.hudView.alpha = 0;
615 |
616 | [[NSNotificationCenter defaultCenter] removeObserver:self];
617 | [self cancelRingLayerAnimation];
618 | [hudView removeFromSuperview];
619 | hudView = nil;
620 |
621 | [overlayView removeFromSuperview];
622 | overlayView = nil;
623 |
624 | UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
625 |
626 | [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidDisappearNotification
627 | object:nil
628 | userInfo:userInfo];
629 |
630 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
631 | // Tell the rootViewController to update the StatusBar appearance
632 | UIViewController *rootController = [[UIApplication sharedApplication] keyWindow].rootViewController;
633 | if ([rootController respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
634 | [rootController setNeedsStatusBarAppearanceUpdate];
635 | }
636 | #endif
637 | // uncomment to make sure UIWindow is gone from app.windows
638 | //NSLog(@"%@", [UIApplication sharedApplication].windows);
639 | //NSLog(@"keyWindow = %@", [UIApplication sharedApplication].keyWindow);
640 | }
641 | }];
642 | }
643 |
644 |
645 | #pragma mark -
646 | #pragma mark Ring progress animation
647 |
648 | - (CAShapeLayer *)ringLayer {
649 | if(!_ringLayer) {
650 | CGPoint center = CGPointMake(CGRectGetWidth(hudView.frame)/2, CGRectGetHeight(hudView.frame)/2);
651 | _ringLayer = [self createRingLayerWithCenter:center radius:SVProgressHUDRingRadius lineWidth:SVProgressHUDRingThickness color:self.hudRingForegroundColor];
652 | [self.hudView.layer addSublayer:_ringLayer];
653 | }
654 | return _ringLayer;
655 | }
656 |
657 | - (CAShapeLayer *)backgroundRingLayer {
658 | if(!_backgroundRingLayer) {
659 | CGPoint center = CGPointMake(CGRectGetWidth(hudView.frame)/2, CGRectGetHeight(hudView.frame)/2);
660 | _backgroundRingLayer = [self createRingLayerWithCenter:center radius:SVProgressHUDRingRadius lineWidth:SVProgressHUDRingThickness color:self.hudRingBackgroundColor];
661 | _backgroundRingLayer.strokeEnd = 1;
662 | [self.hudView.layer addSublayer:_backgroundRingLayer];
663 | }
664 | return _backgroundRingLayer;
665 | }
666 |
667 | - (void)cancelRingLayerAnimation {
668 | [CATransaction begin];
669 | [CATransaction setDisableActions:YES];
670 | [hudView.layer removeAllAnimations];
671 |
672 | _ringLayer.strokeEnd = 0.0f;
673 | if (_ringLayer.superlayer) {
674 | [_ringLayer removeFromSuperlayer];
675 | }
676 | _ringLayer = nil;
677 |
678 | if (_backgroundRingLayer.superlayer) {
679 | [_backgroundRingLayer removeFromSuperlayer];
680 | }
681 | _backgroundRingLayer = nil;
682 |
683 | [CATransaction commit];
684 | }
685 |
686 | - (CGPoint)pointOnCircleWithCenter:(CGPoint)center radius:(double)radius angleInDegrees:(double)angleInDegrees {
687 | float x = (float)(radius * cos(angleInDegrees * M_PI / 180)) + radius;
688 | float y = (float)(radius * sin(angleInDegrees * M_PI / 180)) + radius;
689 | return CGPointMake(x, y);
690 | }
691 |
692 |
693 | - (UIBezierPath *)createCirclePathWithCenter:(CGPoint)center radius:(CGFloat)radius sampleCount:(NSInteger)sampleCount {
694 |
695 | UIBezierPath *smoothedPath = [UIBezierPath bezierPath];
696 | CGPoint startPoint = [self pointOnCircleWithCenter:center radius:radius angleInDegrees:-90];
697 |
698 | [smoothedPath moveToPoint:startPoint];
699 |
700 | CGFloat delta = 360.0f/sampleCount;
701 | CGFloat angleInDegrees = -90;
702 | for (NSInteger i=1; i= 70000
759 | hudView = [[UIView alloc] initWithFrame:CGRectZero];
760 | // ((UIView *)hudView).translucent = YES;
761 | ((UIView *)hudView).backgroundColor= self.hudBackgroundColor;
762 | #else
763 | hudView = [[UIView alloc] initWithFrame:CGRectZero];
764 |
765 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
766 |
767 | // UIAppearance is used when iOS >= 5.0
768 | hudView.backgroundColor = self.hudBackgroundColor;
769 | #endif
770 | #endif
771 |
772 | hudView.layer.cornerRadius = 3;
773 | hudView.layer.masksToBounds = YES;
774 |
775 | hudView.autoresizingMask = (UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin |
776 | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin);
777 |
778 | [self addSubview:hudView];
779 | }
780 | return hudView;
781 | }
782 |
783 | - (UILabel *)stringLabel {
784 | if (stringLabel == nil) {
785 | stringLabel = [[UILabel alloc] initWithFrame:CGRectZero];
786 | stringLabel.backgroundColor = [UIColor clearColor];
787 | stringLabel.adjustsFontSizeToFitWidth = YES;
788 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000
789 | stringLabel.textAlignment = UITextAlignmentCenter;
790 | #else
791 | stringLabel.textAlignment = NSTextAlignmentCenter;
792 | #endif
793 |
794 | stringLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
795 |
796 | // UIAppearance is used when iOS >= 5.0
797 | stringLabel.textColor = self.hudForegroundColor;
798 | stringLabel.font = self.hudFont;
799 |
800 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < 70000
801 | stringLabel.shadowColor = self.hudStatusShadowColor;
802 | stringLabel.shadowOffset = CGSizeMake(0, -1);
803 | #endif
804 | stringLabel.numberOfLines = 0;
805 | }
806 |
807 | if(!stringLabel.superview)
808 | [self.hudView addSubview:stringLabel];
809 |
810 | return stringLabel;
811 | }
812 |
813 | - (UIImageView *)imageView {
814 | if (imageView == nil)
815 | imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 28, 28)];
816 |
817 | if(!imageView.superview)
818 | [self.hudView addSubview:imageView];
819 |
820 | return imageView;
821 | }
822 |
823 | - (TBActivityView *)spinnerView {
824 | if (spinnerView == nil) {
825 | spinnerView = [[TBActivityView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
826 |
827 | }
828 |
829 | if(!spinnerView.superview)
830 | [self.hudView addSubview:spinnerView];
831 |
832 | return spinnerView;
833 | }
834 |
835 | - (CGFloat)visibleKeyboardHeight {
836 |
837 | UIWindow *keyboardWindow = nil;
838 | for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
839 | if(![[testWindow class] isEqual:[UIWindow class]]) {
840 | keyboardWindow = testWindow;
841 | break;
842 | }
843 | }
844 |
845 | for (__strong UIView *possibleKeyboard in [keyboardWindow subviews]) {
846 | if([possibleKeyboard isKindOfClass:NSClassFromString(@"UIPeripheralHostView")] || [possibleKeyboard isKindOfClass:NSClassFromString(@"UIKeyboard")])
847 | return possibleKeyboard.bounds.size.height;
848 | }
849 |
850 | return 0;
851 | }
852 |
853 | #pragma mark - UIAppearance getters
854 |
855 | - (UIColor *)hudBackgroundColor {
856 |
857 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
858 | if(_uiHudBgColor == nil) {
859 | _uiHudBgColor = [[[self class] appearance] hudBackgroundColor];
860 | }
861 |
862 | if(_uiHudBgColor != nil) {
863 | return _uiHudBgColor;
864 | }
865 | #endif
866 |
867 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
868 | return [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
869 | #else
870 | return [UIColor colorWithWhite:0 alpha:0.8];
871 | #endif
872 | }
873 |
874 | - (UIColor *)hudForegroundColor {
875 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
876 | if(_uiHudFgColor == nil) {
877 | _uiHudFgColor = [[[self class] appearance] hudForegroundColor];
878 | }
879 |
880 | if(_uiHudFgColor != nil) {
881 | return _uiHudFgColor;
882 | }
883 | #endif
884 |
885 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
886 | return [UIColor colorWithWhite:1 alpha:0.8];
887 | #else
888 | return [UIColor whiteColor];
889 | #endif
890 | }
891 |
892 | - (UIColor *)hudRingBackgroundColor {
893 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
894 | if(_uiHudRingBgColor == nil) {
895 | _uiHudRingBgColor = [[[self class] appearance] hudRingBackgroundColor];
896 | }
897 |
898 | if(_uiHudRingBgColor != nil) {
899 | return _uiHudRingBgColor;
900 | }
901 | #endif
902 |
903 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
904 | return [UIColor whiteColor];
905 | #else
906 | return [UIColor colorWithWhite:0 alpha:0.8];
907 | #endif
908 | }
909 |
910 | - (UIColor *)hudRingForegroundColor {
911 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
912 | if(_uiHudRingFgColor == nil) {
913 | _uiHudRingFgColor = [[[self class] appearance] hudRingForegroundColor];
914 | }
915 |
916 | if(_uiHudRingFgColor != nil) {
917 | return _uiHudRingFgColor;
918 | }
919 | #endif
920 |
921 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
922 | return self.tintColor;
923 | #else
924 | return [UIColor whiteColor];
925 | #endif
926 | }
927 |
928 | - (UIColor *)hudStatusShadowColor {
929 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
930 | if(_uiHudStatusShColor == nil) {
931 | _uiHudStatusShColor = [[[self class] appearance] hudStatusShadowColor];
932 | }
933 |
934 | if(_uiHudStatusShColor != nil) {
935 | return _uiHudStatusShColor;
936 | }
937 | #endif
938 |
939 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
940 | return [UIColor colorWithWhite:200.0f/255.0f alpha:0.8];
941 | #else
942 | return [UIColor blackColor];
943 | #endif
944 | }
945 |
946 | - (UIFont *)hudFont {
947 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
948 | if(_uiHudFont == nil) {
949 | _uiHudFont = [[[self class] appearance] hudFont];
950 | }
951 |
952 | if(_uiHudFont != nil) {
953 | return _uiHudFont;
954 | }
955 | #endif
956 |
957 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
958 | return [UIFont systemFontOfSize:15];
959 | #else
960 | return [UIFont boldSystemFontOfSize:15];
961 | #endif
962 | }
963 |
964 | - (UIImage *)hudSuccessImage {
965 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
966 | if(_uiHudSuccessImage == nil) {
967 | _uiHudSuccessImage = [[[self class] appearance] hudSuccessImage];
968 | }
969 |
970 | if(_uiHudSuccessImage != nil) {
971 | return _uiHudSuccessImage;
972 | }
973 | #endif
974 |
975 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
976 | return [UIImage imageNamed:@"SVProgressHUD.bundle/success"];
977 | #else
978 | return [UIImage imageNamed:@"SVProgressHUD.bundle/success.png"];
979 | #endif
980 | }
981 |
982 | - (UIImage *)hudErrorImage {
983 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
984 | if(_uiHudErrorImage == nil) {
985 | _uiHudErrorImage = [[[self class] appearance] hudErrorImage];
986 | }
987 |
988 | if(_uiHudErrorImage != nil) {
989 | return _uiHudErrorImage;
990 | }
991 | #endif
992 |
993 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
994 | return [UIImage imageNamed:@"SVProgressHUD.bundle/error"];
995 | #else
996 | return [UIImage imageNamed:@"SVProgressHUD.bundle/error.png"];
997 | #endif
998 | }
999 |
1000 | @end
1001 |
--------------------------------------------------------------------------------