├── gif
└── Untitled.gif
├── TagGroupDemo
├── TagGroupDemo
│ ├── meinv.jpg
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── camera_color_other.imageset
│ │ │ ├── camera_color_other.png
│ │ │ ├── camera_color_other@2x.png
│ │ │ ├── camera_color_other@3x.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── ViewController.h
│ ├── AppDelegate.h
│ ├── main.m
│ ├── NSTimer
│ │ ├── NSTimer+Addition.h
│ │ └── NSTimer+Addition.m
│ ├── NSString+SizeWithFont.h
│ ├── MaxLightingView.h
│ ├── Info.plist
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ ├── NSString+SizeWithFont.m
│ ├── AppDelegate.m
│ ├── ViewController.m
│ ├── MaxLightingView.m
│ ├── MaxShapeView.h
│ └── MaxShapeView.m
├── TagGroupDemo.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ │ ├── zmw.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ │ └── chanli.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ ├── xcuserdata
│ │ ├── zmw.xcuserdatad
│ │ │ ├── xcschemes
│ │ │ │ ├── xcschememanagement.plist
│ │ │ │ └── TagGroupDemo.xcscheme
│ │ │ └── xcdebugger
│ │ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── chanli.xcuserdatad
│ │ │ ├── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── TagGroupDemo.xcscheme
│ │ │ └── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ └── project.pbxproj
├── TagGroupDemoTests
│ ├── Info.plist
│ └── TagGroupDemoTests.m
└── TagGroupDemoUITests
│ ├── Info.plist
│ └── TagGroupDemoUITests.m
└── README.md
/gif/Untitled.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zmw123/ShapeView/HEAD/gif/Untitled.gif
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/meinv.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zmw123/ShapeView/HEAD/TagGroupDemo/TagGroupDemo/meinv.jpg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ShapeView
2 | 模仿小红书的标签选择
3 | 支持一个、两个、三个的标签
4 | 
5 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/Assets.xcassets/camera_color_other.imageset/camera_color_other.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zmw123/ShapeView/HEAD/TagGroupDemo/TagGroupDemo/Assets.xcassets/camera_color_other.imageset/camera_color_other.png
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/Assets.xcassets/camera_color_other.imageset/camera_color_other@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zmw123/ShapeView/HEAD/TagGroupDemo/TagGroupDemo/Assets.xcassets/camera_color_other.imageset/camera_color_other@2x.png
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/Assets.xcassets/camera_color_other.imageset/camera_color_other@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zmw123/ShapeView/HEAD/TagGroupDemo/TagGroupDemo/Assets.xcassets/camera_color_other.imageset/camera_color_other@3x.png
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/project.xcworkspace/xcuserdata/zmw.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zmw123/ShapeView/HEAD/TagGroupDemo/TagGroupDemo.xcodeproj/project.xcworkspace/xcuserdata/zmw.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/project.xcworkspace/xcuserdata/chanli.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zmw123/ShapeView/HEAD/TagGroupDemo/TagGroupDemo.xcodeproj/project.xcworkspace/xcuserdata/chanli.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // TagGroupDemo
4 | //
5 | // Created by chanli on 16/3/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // TagGroupDemo
4 | //
5 | // Created by chanli on 16/3/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. 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 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // TagGroupDemo
4 | //
5 | // Created by chanli on 16/3/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. 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 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/NSTimer/NSTimer+Addition.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSTimer+Addition.h
3 | // YXLScrollView
4 | //
5 | // Created by Yexinglong on 14/10/9.
6 | // Copyright (c) 2014年 Yexinglong. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSTimer (Addition)
12 | //关闭定时器
13 | - (void)pauseTimer;
14 | //启动定时器
15 | - (void)resumeTimer;
16 | //添加一个定时器
17 | - (void)resumeTimerAfterTimeInterval:(NSTimeInterval)interval;
18 | @end
19 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/Assets.xcassets/camera_color_other.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "camera_color_other.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "camera_color_other@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "camera_color_other@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/NSString+SizeWithFont.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+SizeWithFont.h
3 | // TagGroupDemo
4 | //
5 | // Created by chanli on 16/3/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights
7 | // reserved.
8 | //
9 |
10 | #import
11 | #import
12 |
13 | @interface NSString (SizeWithFont)
14 |
15 | + (CGFloat)widthWithAttributes:(NSDictionary *)attrs
16 | text:(NSString *)string;
17 |
18 | + (CGFloat)maxestWidthWithStringArray:(NSArray *)array;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/MaxLightingView.h:
--------------------------------------------------------------------------------
1 | //
2 | // MaxLightingView.h
3 | // TagGroupDemo
4 | //
5 | // Created by chanli on 16/5/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights
7 | // reserved.
8 | //
9 |
10 | #import
11 |
12 | @interface MaxLightingView : UIView
13 |
14 | /**
15 | * 初始化 闪烁
16 | *
17 | * @param frame frame
18 | * @param times 闪烁次数 1 一直闪烁,0,闪烁一次
19 | *
20 | * @return MaxLightingView
21 | */
22 | - (id)initWithFrame:(CGRect)frame animationRepeats:(BOOL)repeats;
23 |
24 | @property(assign, nonatomic) CGPoint centerPoint;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/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 | }
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/NSTimer/NSTimer+Addition.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSTimer+Addition.m
3 | // YXLScrollView
4 | //
5 | // Created by Yexinglong on 14/10/9.
6 | // Copyright (c) 2014年 Yexinglong. All rights reserved.
7 | //
8 |
9 | #import "NSTimer+Addition.h"
10 |
11 | @implementation NSTimer (Addition)
12 |
13 | -(void)pauseTimer
14 | {
15 | if (![self isValid]) {
16 | return ;
17 | }
18 | [self setFireDate:[NSDate distantFuture]];
19 | }
20 |
21 | -(void)resumeTimer
22 | {
23 | if (![self isValid]) {
24 | return ;
25 | }
26 | [self setFireDate:[NSDate date]];
27 | }
28 |
29 | - (void)resumeTimerAfterTimeInterval:(NSTimeInterval)interval
30 | {
31 | if (![self isValid]) {
32 | return ;
33 | }
34 | [self setFireDate:[NSDate dateWithTimeIntervalSinceNow:interval]];
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemoTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemoUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/xcuserdata/zmw.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TagGroupDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | C4F4EAA21C88335400494A7E
16 |
17 | primary
18 |
19 |
20 | C4F4EABB1C88335400494A7E
21 |
22 | primary
23 |
24 |
25 | C4F4EAC61C88335400494A7E
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/xcuserdata/chanli.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TagGroupDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | C4F4EAA21C88335400494A7E
16 |
17 | primary
18 |
19 |
20 | C4F4EABB1C88335400494A7E
21 |
22 | primary
23 |
24 |
25 | C4F4EAC61C88335400494A7E
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemoTests/TagGroupDemoTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TagGroupDemoTests.m
3 | // TagGroupDemoTests
4 | //
5 | // Created by chanli on 16/3/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TagGroupDemoTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation TagGroupDemoTests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | }
21 |
22 | - (void)tearDown {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | [super tearDown];
25 | }
26 |
27 | - (void)testExample {
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/xcuserdata/chanli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
14 |
15 |
16 |
18 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/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 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemoUITests/TagGroupDemoUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // TagGroupDemoUITests.m
3 | // TagGroupDemoUITests
4 | //
5 | // Created by chanli on 16/3/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TagGroupDemoUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation TagGroupDemoUITests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 |
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 |
22 | // In UI tests it is usually best to stop immediately when a failure occurs.
23 | self.continueAfterFailure = NO;
24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
25 | [[[XCUIApplication alloc] init] launch];
26 |
27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
28 | }
29 |
30 | - (void)tearDown {
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | [super tearDown];
33 | }
34 |
35 | - (void)testExample {
36 | // Use recording to get started writing UI tests.
37 | // Use XCTAssert and related functions to verify your tests produce the correct results.
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/xcuserdata/zmw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
20 |
21 |
22 |
24 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/NSString+SizeWithFont.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+SizeWithFont.m
3 | // TagGroupDemo
4 | //
5 | // Created by chanli on 16/3/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights
7 | // reserved.
8 | //
9 |
10 | #import "NSString+SizeWithFont.h"
11 | #define kEdgeDistance 5
12 |
13 | @implementation NSString (SizeWithFont)
14 |
15 | + (CGFloat)widthWithAttributes:(NSDictionary *)attrs
16 | text:(NSString *)string {
17 |
18 | NSMutableDictionary *attrsDic =
19 | [NSMutableDictionary dictionaryWithDictionary:@{
20 | NSFontAttributeName : [UIFont systemFontOfSize:12],
21 | NSForegroundColorAttributeName : [UIColor redColor]
22 | }];
23 | if (attrs != nil) {
24 | attrsDic = [NSMutableDictionary dictionaryWithDictionary:attrs];
25 | }
26 |
27 | CGRect rect =
28 | [string boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, 15)
29 | options:NSStringDrawingUsesLineFragmentOrigin |
30 | NSStringDrawingUsesFontLeading
31 | attributes:attrsDic
32 | context:nil];
33 | //6是小白点宽度
34 | return rect.size.width + 2 * kEdgeDistance + 6;
35 | }
36 |
37 | + (CGFloat)maxestWidthWithStringArray:(NSArray *)array {
38 |
39 | __block CGFloat maxLength = 0;
40 |
41 | [array enumerateObjectsUsingBlock:^(NSString *_Nonnull obj, NSUInteger idx,
42 | BOOL *_Nonnull stop) {
43 |
44 | CGFloat length = [NSString widthWithAttributes:nil text:obj];
45 | maxLength = maxLength > length ? maxLength : length;
46 |
47 | }];
48 |
49 | return maxLength;
50 | }
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/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 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // TagGroupDemo
4 | //
5 | // Created by chanli on 16/3/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. 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 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // TagGroupDemo
4 | //
5 | // Created by chanli on 16/3/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights
7 | // reserved.
8 | //
9 |
10 | #import "MaxShapeView.h"
11 | #import "ViewController.h"
12 | #import "MaxLightingView.h"
13 |
14 | @interface ViewController ()
15 |
16 | @property(strong, nonatomic) UIImageView *imageView;
17 | @property (strong, nonatomic) MaxShapeView *pathShapeView;
18 | @end
19 |
20 | @implementation ViewController
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 |
25 | // Do any additional setup after loading the view, typically from a nib.
26 | // [self buildWebView];
27 | [self buildTag];
28 | }
29 |
30 | - (void)buildTag {
31 | self.imageView =
32 | [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"meinv.jpg"]];
33 | self.imageView.userInteractionEnabled = YES;
34 |
35 | self.imageView.frame = self.view.bounds;
36 |
37 | [self.view addSubview:self.imageView];
38 | self.view.backgroundColor = [UIColor whiteColor];
39 |
40 | CGPoint point = CGPointMake(100, 200);
41 |
42 | NSArray *tagGroup = @[ @"Moschino", @"裤子", @"¥2000" ];
43 | // tagGroup = @[ @"Moschino", @"裤子"];
44 | tagGroup = @[ @"Moschino"];
45 |
46 | //添加path的UIView
47 | self.pathShapeView =
48 | [[MaxShapeView alloc] initWithFrame:CGRectZero
49 | point:point
50 | tagGroup:tagGroup
51 | tagType:kMaxTagGroupTypeDefault
52 | superFrame:self.view.frame];
53 |
54 | // pathShapeView.backgroundColor = [UIColor grayColor];
55 |
56 | [self.view addSubview:self.pathShapeView];
57 |
58 |
59 | __weak typeof(self) weakSelf = self;
60 | self.pathShapeView.tapBlock = ^(MaxShapeView *shapeView, UILabel *tapLabel) {
61 |
62 | if (tapLabel)
63 | {
64 | UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"选择后标签个数" message:@"" delegate:weakSelf cancelButtonTitle:@"取消" otherButtonTitles:@"0", @"1", @"2", @"3", nil];
65 | [alertView show];
66 | }
67 | };
68 |
69 | self.pathShapeView.longPressBlock = ^(MaxShapeView *shapeView){
70 |
71 | //长按
72 | NSLog(@"%s__%d", __func__, __LINE__);
73 | };
74 | }
75 |
76 | - (void)didReceiveMemoryWarning {
77 | [super didReceiveMemoryWarning];
78 | // Dispose of any resources that can be recreated.
79 | }
80 |
81 | #pragma mark - alertView
82 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
83 | {
84 | if (buttonIndex == 1)
85 | {
86 | //删除
87 | [self.pathShapeView removeFromSuperview];
88 | }
89 | else if (buttonIndex == 2)
90 | {
91 | self.pathShapeView.tagGroup = @[@"Moschino"];
92 | }
93 | else if (buttonIndex == 3)
94 | {
95 | self.pathShapeView.tagGroup = @[ @"Moschino", @"裤子"];
96 | }
97 | else if (buttonIndex == 4)
98 | {
99 | self.pathShapeView.tagGroup = @[ @"Moschino", @"裤子", @"¥2000"];
100 | }
101 |
102 | if (self.pathShapeView.tagGroup.count == 1)
103 | {
104 | self.pathShapeView.type = kMaxTagGroupOneTagTypeRight;
105 | } else if (self.pathShapeView.tagGroup.count == 2) {
106 | self.pathShapeView.type = kMaxTagGroupTwoTagTypeBrokenRight;
107 | } else if (self.pathShapeView.tagGroup.count == 3) {
108 | self.pathShapeView.type = kMaxTagGroupThreeTagTypeLeftBottom;
109 | }
110 |
111 | [self.pathShapeView drawLine];
112 | }
113 | @end
114 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/MaxLightingView.m:
--------------------------------------------------------------------------------
1 | //
2 | // MaxLightingView.m
3 | // TagGroupDemo
4 | //
5 | // Created by chanli on 16/5/3.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights
7 | // reserved.
8 | //
9 |
10 | #import "MaxLightingView.h"
11 | #import "NSTimer+Addition.h"
12 |
13 | #define kWidthCircle 8
14 |
15 | #define kTransformScle 2
16 |
17 | #define UIColorRGBA(r, g, b, a) \
18 | [UIColor colorWithRed:(r) / 255.0 \
19 | green:(g) / 255.0 \
20 | blue:(b) / 255.0 \
21 | alpha:(a)]
22 |
23 | @interface MaxLightingView () {
24 | NSTimer *timerAnimation;
25 | UIView *viewSpread;
26 | UIView *viewTapDot;
27 | UIImageView *viewTapDotImageView;
28 | }
29 |
30 | @end
31 |
32 | @implementation MaxLightingView
33 |
34 | - (id)initWithFrame:(CGRect)frame animationRepeats:(BOOL)repeats {
35 |
36 | if (self = [super initWithFrame:frame]) {
37 |
38 | timerAnimation = [NSTimer
39 | scheduledTimerWithTimeInterval:3
40 | target:self
41 | selector:@selector(animationTimerDidFired)
42 | userInfo:nil
43 | repeats:repeats];
44 |
45 | [self setup];
46 | }
47 |
48 | return self;
49 | }
50 |
51 |
52 | - (void)setCenterPoint:(CGPoint)centerPoint {
53 |
54 | _centerPoint = centerPoint;
55 | [self setFrame:CGRectMake(centerPoint.x - kWidthCircle / 2,
56 | centerPoint.y - kWidthCircle / 2, kWidthCircle,
57 | kWidthCircle)];
58 |
59 | [self setup];
60 |
61 | }
62 |
63 | - (void)setup {
64 |
65 | viewSpread = [self getViewSpread];
66 | viewSpread.layer.cornerRadius = viewSpread.frame.size.width / 2;
67 | viewSpread.layer.masksToBounds = YES;
68 | [self addSubview:viewSpread];
69 | viewTapDotImageView = [self getViewTapDotImageView];
70 | [self addSubview:viewTapDotImageView];
71 | viewSpread.center = viewTapDotImageView.center;
72 | [timerAnimation resumeTimer];
73 | }
74 |
75 | #pragma - mark init
76 |
77 | - (UIView *)getViewSpread {
78 | UIView *view = [[UIView alloc]
79 | initWithFrame:CGRectMake(0, 0, kWidthCircle / 3, kWidthCircle / 3)];
80 | view.backgroundColor = UIColorRGBA(255, 255, 255, 1);
81 | view.userInteractionEnabled = NO;
82 | view.center = self.center;
83 | return view;
84 | }
85 |
86 | - (UIView *)getViewTapDot {
87 | UIView *view = [UIView new];
88 | view.backgroundColor = UIColorRGBA(255, 255, 255, 1); //主题颜色;
89 | view.userInteractionEnabled = NO;
90 | view.center = self.center;
91 | return view;
92 | }
93 |
94 | - (UIImageView *)getViewTapDotImageView {
95 | UIImageView *getViewTapDotImageView = [[UIImageView alloc]
96 | initWithFrame:CGRectMake(0, 0, kWidthCircle, kWidthCircle)];
97 | // getViewTapDotImageView.center = self.center;
98 |
99 | getViewTapDotImageView.contentMode = UIViewContentModeScaleAspectFit;
100 | getViewTapDotImageView.image = [UIImage imageNamed:@"camera_color_other"];
101 | getViewTapDotImageView.userInteractionEnabled = NO;
102 | return getViewTapDotImageView;
103 | }
104 | #pragma - mark 监听
105 | /**
106 | * 播放动画
107 | */
108 | - (void)animationTimerDidFired {
109 | [UIView animateWithDuration:1
110 | animations:^{
111 | viewTapDot.transform = CGAffineTransformMakeScale(1.3 * kTransformScle,
112 | 1.3 * kTransformScle);
113 | }
114 | completion:^(BOOL finished) {
115 | [UIView animateWithDuration:1
116 | animations:^{
117 | viewTapDot.transform = CGAffineTransformIdentity;
118 | }
119 | completion:^(BOOL finished) {
120 | viewSpread.alpha = 1;
121 | [UIView animateWithDuration:1
122 | animations:^{
123 | viewSpread.alpha = 0;
124 | viewSpread.transform = CGAffineTransformMakeScale(
125 | kWidthCircle / 2 * kTransformScle,
126 | kWidthCircle / 2 * kTransformScle);
127 | }
128 | completion:^(BOOL finished) {
129 | viewSpread.transform = CGAffineTransformIdentity;
130 | }];
131 | }];
132 |
133 | }];
134 | }
135 |
136 | @end
137 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/MaxShapeView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ShapeView.h
3 | // TagGroupDemo
4 | //
5 | // Created by zmw on 16/5/4.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights reserved.
7 | //
8 |
9 | #import
10 | /**
11 |
12 | * * * * *
13 | --------------- width 50
14 |
15 |
16 | * * * * Hello
17 | *
18 | *
19 | *
20 | *
21 | *
22 | *
23 | *
24 | * * * * string
25 | --------------- height 100 width 40
26 |
27 | * * * * Hello
28 | *
29 | *
30 | *
31 | * * * Hello
32 | *
33 | *
34 | *
35 | * * * * Hello
36 | --------------- height 120 width 40 midWidth 30
37 | kMaxTagGroupTypeRight
38 |
39 |
40 |
41 | *
42 | *
43 | *
44 | *
45 | * * * Hello
46 | --------------- brokenLine 50 width 30
47 |
48 | * * * Hello
49 | *
50 | *
51 | *
52 | *
53 | *
54 | *
55 | *
56 | * * * Hello
57 | --------------- brokenLine 50 width 30
58 |
59 | * * * Hello
60 | *
61 | *
62 | *
63 | * * * * * * * Hello
64 | *
65 | *
66 | *
67 | * * * Hello
68 | --------------- brokenLine 50 width 30 midWidth 70
69 | kMaxTagGroupTypeBrokenRight
70 |
71 |
72 |
73 | Hello * * * * *
74 | --------------- width 50
75 |
76 | Hello * * * *
77 | *
78 | *
79 | *
80 | *
81 | *
82 | *
83 | *
84 | Hello * * * *
85 | --------------- height 120 width 40
86 |
87 | Hello * * * *
88 | *
89 | *
90 | *
91 | Hello * * *
92 | *
93 | *
94 | *
95 | Hello * * * *
96 | --------------- height 120 width 40 midWidth 30
97 | kMaxTagGroupTypeLeft
98 |
99 |
100 |
101 |
102 | *
103 | *
104 | *
105 | *
106 | Hello * * *
107 | --------------- brokenLine 50 width 30
108 |
109 | * * * Hello
110 | *
111 | *
112 | *
113 | *
114 | *
115 | *
116 | *
117 | * * * Hello
118 | --------------- brokenLine 50 width 30
119 |
120 | * * * Hello
121 | *
122 | *
123 | *
124 | * * * * * * * Hello
125 | *
126 | *
127 | *
128 | * * * Hello
129 | --------------- brokenLine 50 width 30 midWidth 70
130 |
131 | kMaxTagGroupTypeBrokenLeft
132 |
133 | ************
134 | *
135 | *
136 | *
137 | * *
138 | * *
139 | **** ***********
140 | kMaxTagGroupTypeLeftBottom
141 |
142 |
143 | *********
144 | *
145 | *
146 | *
147 | * *
148 | * *
149 | ********** *********
150 | kMaxTagGroupTypeRightBottom,
151 | */
152 |
153 | typedef enum : NSUInteger {
154 | kMaxTagGroupTypeDefault = 0,
155 |
156 | kMaxTagGroupOneTagTypeRight = 10,
157 | kMaxTagGroupOneTagTypeLeft,
158 | kMaxTagGroupOneTagTypeRightBottom,
159 | kMaxTagGroupOneTagTypeLeftBottom,
160 |
161 | kMaxTagGroupTwoTagTypeBrokenRight = 20,
162 | kMaxTagGroupTypeBrokenBrokenLeft,
163 | kMaxTagGroupTwoTagTypeRight,
164 | kMaxTagGroupTwoTagTypeLeft,
165 |
166 | kMaxTagGroupThreeTagTypeLeftBottom = 30,
167 | kMaxTagGroupThreeTagTypeLeftTop,
168 | kMaxTagGroupThreeTagTypeRightTop,
169 | kMaxTagGroupThreeTagTypeRightBottom,
170 | kMaxTagGroupThreeTagTypeBrokenRight,
171 | kMaxTagGroupThreeTagTypeBrokenLeft,
172 | kMaxTagGroupThreeTagTypeRight,
173 | kMaxTagGroupThreeTagTypeLeft,
174 | } kMaxTagGroupType;
175 |
176 | @interface MaxShapeView : UIView
177 |
178 | @property(nonatomic, readonly) CAShapeLayer *shapeLayer;
179 |
180 | @property(nonatomic, assign) BOOL reverse;
181 | @property(nonatomic, assign) kMaxTagGroupType type;
182 | @property(assign, nonatomic) CGPoint point; //中心点
183 | @property(strong, nonatomic) NSArray *tagGroup; //标签数组
184 | @property(strong, nonatomic) NSArray *oneTagGroup; //多的一侧的标签
185 | @property(strong, nonatomic) NSArray *twoTagGroup; //少的一侧的标签
186 |
187 | @property(strong, nonatomic) NSMutableArray *tagPointsArry; //点数组
188 |
189 | @property(strong, nonatomic) NSMutableArray *animationGroup; //动画数组
190 |
191 | @property(nonatomic, copy) void (^longPressBlock)(MaxShapeView *tagView);
192 | @property(nonatomic, copy) void (^tapBlock)(MaxShapeView *tagView, UILabel *tapLabel);
193 | @property(nonatomic, copy) void (^doubleTapBlock)(MaxShapeView *tagView);
194 | @property(nonatomic, copy) void (^dragDoneBlock)(MaxShapeView *tagView);
195 | @property(nonatomic, copy) void (^dragCancelBlock)(MaxShapeView *tagView);
196 |
197 | - (id)initWithFrame:(CGRect)frame
198 | point:(CGPoint)point
199 | tagGroup:(NSArray *)tagGroup
200 | tagType:(kMaxTagGroupType)type
201 | superFrame:(CGRect)superFrame;
202 |
203 | - (void)drawLine;
204 |
205 | @end
206 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/xcuserdata/chanli.xcuserdatad/xcschemes/TagGroupDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/xcuserdata/zmw.xcuserdatad/xcschemes/TagGroupDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | C40C70EE1CD839760099AF6A /* NSTimer+Addition.m in Sources */ = {isa = PBXBuildFile; fileRef = C40C70ED1CD839760099AF6A /* NSTimer+Addition.m */; };
11 | C40C70F11CD83A500099AF6A /* MaxLightingView.m in Sources */ = {isa = PBXBuildFile; fileRef = C40C70F01CD83A500099AF6A /* MaxLightingView.m */; };
12 | C4B124D61CD36AE1009B302A /* meinv.jpg in Resources */ = {isa = PBXBuildFile; fileRef = C4B124D51CD36AE1009B302A /* meinv.jpg */; };
13 | C4F4EAA81C88335400494A7E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F4EAA71C88335400494A7E /* main.m */; };
14 | C4F4EAAB1C88335400494A7E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F4EAAA1C88335400494A7E /* AppDelegate.m */; };
15 | C4F4EAAE1C88335400494A7E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F4EAAD1C88335400494A7E /* ViewController.m */; };
16 | C4F4EAB11C88335400494A7E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C4F4EAAF1C88335400494A7E /* Main.storyboard */; };
17 | C4F4EAB31C88335400494A7E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C4F4EAB21C88335400494A7E /* Assets.xcassets */; };
18 | C4F4EAB61C88335400494A7E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C4F4EAB41C88335400494A7E /* LaunchScreen.storyboard */; };
19 | C4F4EAC11C88335400494A7E /* TagGroupDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F4EAC01C88335400494A7E /* TagGroupDemoTests.m */; };
20 | C4F4EACC1C88335400494A7E /* TagGroupDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F4EACB1C88335400494A7E /* TagGroupDemoUITests.m */; };
21 | C4F4EADB1C8833B000494A7E /* MaxShapeView.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F4EADA1C8833B000494A7E /* MaxShapeView.m */; };
22 | C4F4EADE1C88450600494A7E /* NSString+SizeWithFont.m in Sources */ = {isa = PBXBuildFile; fileRef = C4F4EADD1C88450600494A7E /* NSString+SizeWithFont.m */; };
23 | /* End PBXBuildFile section */
24 |
25 | /* Begin PBXContainerItemProxy section */
26 | C4F4EABD1C88335400494A7E /* PBXContainerItemProxy */ = {
27 | isa = PBXContainerItemProxy;
28 | containerPortal = C4F4EA9B1C88335400494A7E /* Project object */;
29 | proxyType = 1;
30 | remoteGlobalIDString = C4F4EAA21C88335400494A7E;
31 | remoteInfo = TagGroupDemo;
32 | };
33 | C4F4EAC81C88335400494A7E /* PBXContainerItemProxy */ = {
34 | isa = PBXContainerItemProxy;
35 | containerPortal = C4F4EA9B1C88335400494A7E /* Project object */;
36 | proxyType = 1;
37 | remoteGlobalIDString = C4F4EAA21C88335400494A7E;
38 | remoteInfo = TagGroupDemo;
39 | };
40 | /* End PBXContainerItemProxy section */
41 |
42 | /* Begin PBXFileReference section */
43 | C40C70EC1CD839760099AF6A /* NSTimer+Addition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTimer+Addition.h"; sourceTree = ""; };
44 | C40C70ED1CD839760099AF6A /* NSTimer+Addition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTimer+Addition.m"; sourceTree = ""; };
45 | C40C70EF1CD83A500099AF6A /* MaxLightingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MaxLightingView.h; sourceTree = ""; };
46 | C40C70F01CD83A500099AF6A /* MaxLightingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MaxLightingView.m; sourceTree = ""; };
47 | C4B124D51CD36AE1009B302A /* meinv.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = meinv.jpg; sourceTree = ""; };
48 | C4F4EAA31C88335400494A7E /* TagGroupDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TagGroupDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
49 | C4F4EAA71C88335400494A7E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
50 | C4F4EAA91C88335400494A7E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
51 | C4F4EAAA1C88335400494A7E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
52 | C4F4EAAC1C88335400494A7E /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
53 | C4F4EAAD1C88335400494A7E /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
54 | C4F4EAB01C88335400494A7E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
55 | C4F4EAB21C88335400494A7E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
56 | C4F4EAB51C88335400494A7E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
57 | C4F4EAB71C88335400494A7E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | C4F4EABC1C88335400494A7E /* TagGroupDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TagGroupDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
59 | C4F4EAC01C88335400494A7E /* TagGroupDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TagGroupDemoTests.m; sourceTree = ""; };
60 | C4F4EAC21C88335400494A7E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
61 | C4F4EAC71C88335400494A7E /* TagGroupDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TagGroupDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
62 | C4F4EACB1C88335400494A7E /* TagGroupDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TagGroupDemoUITests.m; sourceTree = ""; };
63 | C4F4EACD1C88335400494A7E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
64 | C4F4EAD91C8833B000494A7E /* MaxShapeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MaxShapeView.h; sourceTree = ""; };
65 | C4F4EADA1C8833B000494A7E /* MaxShapeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MaxShapeView.m; sourceTree = ""; };
66 | C4F4EADC1C88450600494A7E /* NSString+SizeWithFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+SizeWithFont.h"; sourceTree = ""; };
67 | C4F4EADD1C88450600494A7E /* NSString+SizeWithFont.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+SizeWithFont.m"; sourceTree = ""; };
68 | /* End PBXFileReference section */
69 |
70 | /* Begin PBXFrameworksBuildPhase section */
71 | C4F4EAA01C88335400494A7E /* Frameworks */ = {
72 | isa = PBXFrameworksBuildPhase;
73 | buildActionMask = 2147483647;
74 | files = (
75 | );
76 | runOnlyForDeploymentPostprocessing = 0;
77 | };
78 | C4F4EAB91C88335400494A7E /* Frameworks */ = {
79 | isa = PBXFrameworksBuildPhase;
80 | buildActionMask = 2147483647;
81 | files = (
82 | );
83 | runOnlyForDeploymentPostprocessing = 0;
84 | };
85 | C4F4EAC41C88335400494A7E /* Frameworks */ = {
86 | isa = PBXFrameworksBuildPhase;
87 | buildActionMask = 2147483647;
88 | files = (
89 | );
90 | runOnlyForDeploymentPostprocessing = 0;
91 | };
92 | /* End PBXFrameworksBuildPhase section */
93 |
94 | /* Begin PBXGroup section */
95 | C40C70EB1CD839760099AF6A /* NSTimer */ = {
96 | isa = PBXGroup;
97 | children = (
98 | C40C70EC1CD839760099AF6A /* NSTimer+Addition.h */,
99 | C40C70ED1CD839760099AF6A /* NSTimer+Addition.m */,
100 | );
101 | path = NSTimer;
102 | sourceTree = "";
103 | };
104 | C4F4EA9A1C88335400494A7E = {
105 | isa = PBXGroup;
106 | children = (
107 | C4F4EAA51C88335400494A7E /* TagGroupDemo */,
108 | C4F4EABF1C88335400494A7E /* TagGroupDemoTests */,
109 | C4F4EACA1C88335400494A7E /* TagGroupDemoUITests */,
110 | C4F4EAA41C88335400494A7E /* Products */,
111 | );
112 | sourceTree = "";
113 | };
114 | C4F4EAA41C88335400494A7E /* Products */ = {
115 | isa = PBXGroup;
116 | children = (
117 | C4F4EAA31C88335400494A7E /* TagGroupDemo.app */,
118 | C4F4EABC1C88335400494A7E /* TagGroupDemoTests.xctest */,
119 | C4F4EAC71C88335400494A7E /* TagGroupDemoUITests.xctest */,
120 | );
121 | name = Products;
122 | sourceTree = "";
123 | };
124 | C4F4EAA51C88335400494A7E /* TagGroupDemo */ = {
125 | isa = PBXGroup;
126 | children = (
127 | C40C70EB1CD839760099AF6A /* NSTimer */,
128 | C4B124D51CD36AE1009B302A /* meinv.jpg */,
129 | C4F4EAA91C88335400494A7E /* AppDelegate.h */,
130 | C4F4EAAA1C88335400494A7E /* AppDelegate.m */,
131 | C4F4EAAC1C88335400494A7E /* ViewController.h */,
132 | C4F4EAAD1C88335400494A7E /* ViewController.m */,
133 | C4F4EAAF1C88335400494A7E /* Main.storyboard */,
134 | C4F4EAB21C88335400494A7E /* Assets.xcassets */,
135 | C4F4EAB41C88335400494A7E /* LaunchScreen.storyboard */,
136 | C4F4EAB71C88335400494A7E /* Info.plist */,
137 | C4F4EAA61C88335400494A7E /* Supporting Files */,
138 | C4F4EAD91C8833B000494A7E /* MaxShapeView.h */,
139 | C4F4EADA1C8833B000494A7E /* MaxShapeView.m */,
140 | C40C70EF1CD83A500099AF6A /* MaxLightingView.h */,
141 | C40C70F01CD83A500099AF6A /* MaxLightingView.m */,
142 | C4F4EADC1C88450600494A7E /* NSString+SizeWithFont.h */,
143 | C4F4EADD1C88450600494A7E /* NSString+SizeWithFont.m */,
144 | );
145 | path = TagGroupDemo;
146 | sourceTree = "";
147 | };
148 | C4F4EAA61C88335400494A7E /* Supporting Files */ = {
149 | isa = PBXGroup;
150 | children = (
151 | C4F4EAA71C88335400494A7E /* main.m */,
152 | );
153 | name = "Supporting Files";
154 | sourceTree = "";
155 | };
156 | C4F4EABF1C88335400494A7E /* TagGroupDemoTests */ = {
157 | isa = PBXGroup;
158 | children = (
159 | C4F4EAC01C88335400494A7E /* TagGroupDemoTests.m */,
160 | C4F4EAC21C88335400494A7E /* Info.plist */,
161 | );
162 | path = TagGroupDemoTests;
163 | sourceTree = "";
164 | };
165 | C4F4EACA1C88335400494A7E /* TagGroupDemoUITests */ = {
166 | isa = PBXGroup;
167 | children = (
168 | C4F4EACB1C88335400494A7E /* TagGroupDemoUITests.m */,
169 | C4F4EACD1C88335400494A7E /* Info.plist */,
170 | );
171 | path = TagGroupDemoUITests;
172 | sourceTree = "";
173 | };
174 | /* End PBXGroup section */
175 |
176 | /* Begin PBXNativeTarget section */
177 | C4F4EAA21C88335400494A7E /* TagGroupDemo */ = {
178 | isa = PBXNativeTarget;
179 | buildConfigurationList = C4F4EAD01C88335400494A7E /* Build configuration list for PBXNativeTarget "TagGroupDemo" */;
180 | buildPhases = (
181 | C4F4EA9F1C88335400494A7E /* Sources */,
182 | C4F4EAA01C88335400494A7E /* Frameworks */,
183 | C4F4EAA11C88335400494A7E /* Resources */,
184 | );
185 | buildRules = (
186 | );
187 | dependencies = (
188 | );
189 | name = TagGroupDemo;
190 | productName = TagGroupDemo;
191 | productReference = C4F4EAA31C88335400494A7E /* TagGroupDemo.app */;
192 | productType = "com.apple.product-type.application";
193 | };
194 | C4F4EABB1C88335400494A7E /* TagGroupDemoTests */ = {
195 | isa = PBXNativeTarget;
196 | buildConfigurationList = C4F4EAD31C88335400494A7E /* Build configuration list for PBXNativeTarget "TagGroupDemoTests" */;
197 | buildPhases = (
198 | C4F4EAB81C88335400494A7E /* Sources */,
199 | C4F4EAB91C88335400494A7E /* Frameworks */,
200 | C4F4EABA1C88335400494A7E /* Resources */,
201 | );
202 | buildRules = (
203 | );
204 | dependencies = (
205 | C4F4EABE1C88335400494A7E /* PBXTargetDependency */,
206 | );
207 | name = TagGroupDemoTests;
208 | productName = TagGroupDemoTests;
209 | productReference = C4F4EABC1C88335400494A7E /* TagGroupDemoTests.xctest */;
210 | productType = "com.apple.product-type.bundle.unit-test";
211 | };
212 | C4F4EAC61C88335400494A7E /* TagGroupDemoUITests */ = {
213 | isa = PBXNativeTarget;
214 | buildConfigurationList = C4F4EAD61C88335400494A7E /* Build configuration list for PBXNativeTarget "TagGroupDemoUITests" */;
215 | buildPhases = (
216 | C4F4EAC31C88335400494A7E /* Sources */,
217 | C4F4EAC41C88335400494A7E /* Frameworks */,
218 | C4F4EAC51C88335400494A7E /* Resources */,
219 | );
220 | buildRules = (
221 | );
222 | dependencies = (
223 | C4F4EAC91C88335400494A7E /* PBXTargetDependency */,
224 | );
225 | name = TagGroupDemoUITests;
226 | productName = TagGroupDemoUITests;
227 | productReference = C4F4EAC71C88335400494A7E /* TagGroupDemoUITests.xctest */;
228 | productType = "com.apple.product-type.bundle.ui-testing";
229 | };
230 | /* End PBXNativeTarget section */
231 |
232 | /* Begin PBXProject section */
233 | C4F4EA9B1C88335400494A7E /* Project object */ = {
234 | isa = PBXProject;
235 | attributes = {
236 | LastUpgradeCheck = 0720;
237 | ORGANIZATIONNAME = "Beijing ChunFengShiLi Technology Co., Ltd.";
238 | TargetAttributes = {
239 | C4F4EAA21C88335400494A7E = {
240 | CreatedOnToolsVersion = 7.2.1;
241 | };
242 | C4F4EABB1C88335400494A7E = {
243 | CreatedOnToolsVersion = 7.2.1;
244 | TestTargetID = C4F4EAA21C88335400494A7E;
245 | };
246 | C4F4EAC61C88335400494A7E = {
247 | CreatedOnToolsVersion = 7.2.1;
248 | TestTargetID = C4F4EAA21C88335400494A7E;
249 | };
250 | };
251 | };
252 | buildConfigurationList = C4F4EA9E1C88335400494A7E /* Build configuration list for PBXProject "TagGroupDemo" */;
253 | compatibilityVersion = "Xcode 3.2";
254 | developmentRegion = English;
255 | hasScannedForEncodings = 0;
256 | knownRegions = (
257 | en,
258 | Base,
259 | );
260 | mainGroup = C4F4EA9A1C88335400494A7E;
261 | productRefGroup = C4F4EAA41C88335400494A7E /* Products */;
262 | projectDirPath = "";
263 | projectRoot = "";
264 | targets = (
265 | C4F4EAA21C88335400494A7E /* TagGroupDemo */,
266 | C4F4EABB1C88335400494A7E /* TagGroupDemoTests */,
267 | C4F4EAC61C88335400494A7E /* TagGroupDemoUITests */,
268 | );
269 | };
270 | /* End PBXProject section */
271 |
272 | /* Begin PBXResourcesBuildPhase section */
273 | C4F4EAA11C88335400494A7E /* Resources */ = {
274 | isa = PBXResourcesBuildPhase;
275 | buildActionMask = 2147483647;
276 | files = (
277 | C4F4EAB61C88335400494A7E /* LaunchScreen.storyboard in Resources */,
278 | C4F4EAB31C88335400494A7E /* Assets.xcassets in Resources */,
279 | C4B124D61CD36AE1009B302A /* meinv.jpg in Resources */,
280 | C4F4EAB11C88335400494A7E /* Main.storyboard in Resources */,
281 | );
282 | runOnlyForDeploymentPostprocessing = 0;
283 | };
284 | C4F4EABA1C88335400494A7E /* Resources */ = {
285 | isa = PBXResourcesBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | );
289 | runOnlyForDeploymentPostprocessing = 0;
290 | };
291 | C4F4EAC51C88335400494A7E /* Resources */ = {
292 | isa = PBXResourcesBuildPhase;
293 | buildActionMask = 2147483647;
294 | files = (
295 | );
296 | runOnlyForDeploymentPostprocessing = 0;
297 | };
298 | /* End PBXResourcesBuildPhase section */
299 |
300 | /* Begin PBXSourcesBuildPhase section */
301 | C4F4EA9F1C88335400494A7E /* Sources */ = {
302 | isa = PBXSourcesBuildPhase;
303 | buildActionMask = 2147483647;
304 | files = (
305 | C40C70F11CD83A500099AF6A /* MaxLightingView.m in Sources */,
306 | C4F4EAAE1C88335400494A7E /* ViewController.m in Sources */,
307 | C4F4EAAB1C88335400494A7E /* AppDelegate.m in Sources */,
308 | C4F4EADE1C88450600494A7E /* NSString+SizeWithFont.m in Sources */,
309 | C4F4EAA81C88335400494A7E /* main.m in Sources */,
310 | C4F4EADB1C8833B000494A7E /* MaxShapeView.m in Sources */,
311 | C40C70EE1CD839760099AF6A /* NSTimer+Addition.m in Sources */,
312 | );
313 | runOnlyForDeploymentPostprocessing = 0;
314 | };
315 | C4F4EAB81C88335400494A7E /* Sources */ = {
316 | isa = PBXSourcesBuildPhase;
317 | buildActionMask = 2147483647;
318 | files = (
319 | C4F4EAC11C88335400494A7E /* TagGroupDemoTests.m in Sources */,
320 | );
321 | runOnlyForDeploymentPostprocessing = 0;
322 | };
323 | C4F4EAC31C88335400494A7E /* Sources */ = {
324 | isa = PBXSourcesBuildPhase;
325 | buildActionMask = 2147483647;
326 | files = (
327 | C4F4EACC1C88335400494A7E /* TagGroupDemoUITests.m in Sources */,
328 | );
329 | runOnlyForDeploymentPostprocessing = 0;
330 | };
331 | /* End PBXSourcesBuildPhase section */
332 |
333 | /* Begin PBXTargetDependency section */
334 | C4F4EABE1C88335400494A7E /* PBXTargetDependency */ = {
335 | isa = PBXTargetDependency;
336 | target = C4F4EAA21C88335400494A7E /* TagGroupDemo */;
337 | targetProxy = C4F4EABD1C88335400494A7E /* PBXContainerItemProxy */;
338 | };
339 | C4F4EAC91C88335400494A7E /* PBXTargetDependency */ = {
340 | isa = PBXTargetDependency;
341 | target = C4F4EAA21C88335400494A7E /* TagGroupDemo */;
342 | targetProxy = C4F4EAC81C88335400494A7E /* PBXContainerItemProxy */;
343 | };
344 | /* End PBXTargetDependency section */
345 |
346 | /* Begin PBXVariantGroup section */
347 | C4F4EAAF1C88335400494A7E /* Main.storyboard */ = {
348 | isa = PBXVariantGroup;
349 | children = (
350 | C4F4EAB01C88335400494A7E /* Base */,
351 | );
352 | name = Main.storyboard;
353 | sourceTree = "";
354 | };
355 | C4F4EAB41C88335400494A7E /* LaunchScreen.storyboard */ = {
356 | isa = PBXVariantGroup;
357 | children = (
358 | C4F4EAB51C88335400494A7E /* Base */,
359 | );
360 | name = LaunchScreen.storyboard;
361 | sourceTree = "";
362 | };
363 | /* End PBXVariantGroup section */
364 |
365 | /* Begin XCBuildConfiguration section */
366 | C4F4EACE1C88335400494A7E /* Debug */ = {
367 | isa = XCBuildConfiguration;
368 | buildSettings = {
369 | ALWAYS_SEARCH_USER_PATHS = NO;
370 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
371 | CLANG_CXX_LIBRARY = "libc++";
372 | CLANG_ENABLE_MODULES = YES;
373 | CLANG_ENABLE_OBJC_ARC = YES;
374 | CLANG_WARN_BOOL_CONVERSION = YES;
375 | CLANG_WARN_CONSTANT_CONVERSION = YES;
376 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
377 | CLANG_WARN_EMPTY_BODY = YES;
378 | CLANG_WARN_ENUM_CONVERSION = YES;
379 | CLANG_WARN_INT_CONVERSION = YES;
380 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
381 | CLANG_WARN_UNREACHABLE_CODE = YES;
382 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
383 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
384 | COPY_PHASE_STRIP = NO;
385 | DEBUG_INFORMATION_FORMAT = dwarf;
386 | ENABLE_STRICT_OBJC_MSGSEND = YES;
387 | ENABLE_TESTABILITY = YES;
388 | GCC_C_LANGUAGE_STANDARD = gnu99;
389 | GCC_DYNAMIC_NO_PIC = NO;
390 | GCC_NO_COMMON_BLOCKS = YES;
391 | GCC_OPTIMIZATION_LEVEL = 0;
392 | GCC_PREPROCESSOR_DEFINITIONS = (
393 | "DEBUG=1",
394 | "$(inherited)",
395 | );
396 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
397 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
398 | GCC_WARN_UNDECLARED_SELECTOR = YES;
399 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
400 | GCC_WARN_UNUSED_FUNCTION = YES;
401 | GCC_WARN_UNUSED_VARIABLE = YES;
402 | IPHONEOS_DEPLOYMENT_TARGET = 9.2;
403 | MTL_ENABLE_DEBUG_INFO = YES;
404 | ONLY_ACTIVE_ARCH = YES;
405 | SDKROOT = iphoneos;
406 | };
407 | name = Debug;
408 | };
409 | C4F4EACF1C88335400494A7E /* Release */ = {
410 | isa = XCBuildConfiguration;
411 | buildSettings = {
412 | ALWAYS_SEARCH_USER_PATHS = NO;
413 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
414 | CLANG_CXX_LIBRARY = "libc++";
415 | CLANG_ENABLE_MODULES = YES;
416 | CLANG_ENABLE_OBJC_ARC = YES;
417 | CLANG_WARN_BOOL_CONVERSION = YES;
418 | CLANG_WARN_CONSTANT_CONVERSION = YES;
419 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
420 | CLANG_WARN_EMPTY_BODY = YES;
421 | CLANG_WARN_ENUM_CONVERSION = YES;
422 | CLANG_WARN_INT_CONVERSION = YES;
423 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
424 | CLANG_WARN_UNREACHABLE_CODE = YES;
425 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
426 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
427 | COPY_PHASE_STRIP = NO;
428 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
429 | ENABLE_NS_ASSERTIONS = NO;
430 | ENABLE_STRICT_OBJC_MSGSEND = YES;
431 | GCC_C_LANGUAGE_STANDARD = gnu99;
432 | GCC_NO_COMMON_BLOCKS = YES;
433 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
434 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
435 | GCC_WARN_UNDECLARED_SELECTOR = YES;
436 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
437 | GCC_WARN_UNUSED_FUNCTION = YES;
438 | GCC_WARN_UNUSED_VARIABLE = YES;
439 | IPHONEOS_DEPLOYMENT_TARGET = 9.2;
440 | MTL_ENABLE_DEBUG_INFO = NO;
441 | SDKROOT = iphoneos;
442 | VALIDATE_PRODUCT = YES;
443 | };
444 | name = Release;
445 | };
446 | C4F4EAD11C88335400494A7E /* Debug */ = {
447 | isa = XCBuildConfiguration;
448 | buildSettings = {
449 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
450 | INFOPLIST_FILE = TagGroupDemo/Info.plist;
451 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
453 | PRODUCT_BUNDLE_IDENTIFIER = com.aotumanlady..TagGroupDemo;
454 | PRODUCT_NAME = "$(TARGET_NAME)";
455 | };
456 | name = Debug;
457 | };
458 | C4F4EAD21C88335400494A7E /* Release */ = {
459 | isa = XCBuildConfiguration;
460 | buildSettings = {
461 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
462 | INFOPLIST_FILE = TagGroupDemo/Info.plist;
463 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
464 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
465 | PRODUCT_BUNDLE_IDENTIFIER = com.aotumanlady..TagGroupDemo;
466 | PRODUCT_NAME = "$(TARGET_NAME)";
467 | };
468 | name = Release;
469 | };
470 | C4F4EAD41C88335400494A7E /* Debug */ = {
471 | isa = XCBuildConfiguration;
472 | buildSettings = {
473 | BUNDLE_LOADER = "$(TEST_HOST)";
474 | INFOPLIST_FILE = TagGroupDemoTests/Info.plist;
475 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
476 | PRODUCT_BUNDLE_IDENTIFIER = com.aotumanlady..TagGroupDemoTests;
477 | PRODUCT_NAME = "$(TARGET_NAME)";
478 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TagGroupDemo.app/TagGroupDemo";
479 | };
480 | name = Debug;
481 | };
482 | C4F4EAD51C88335400494A7E /* Release */ = {
483 | isa = XCBuildConfiguration;
484 | buildSettings = {
485 | BUNDLE_LOADER = "$(TEST_HOST)";
486 | INFOPLIST_FILE = TagGroupDemoTests/Info.plist;
487 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
488 | PRODUCT_BUNDLE_IDENTIFIER = com.aotumanlady..TagGroupDemoTests;
489 | PRODUCT_NAME = "$(TARGET_NAME)";
490 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TagGroupDemo.app/TagGroupDemo";
491 | };
492 | name = Release;
493 | };
494 | C4F4EAD71C88335400494A7E /* Debug */ = {
495 | isa = XCBuildConfiguration;
496 | buildSettings = {
497 | INFOPLIST_FILE = TagGroupDemoUITests/Info.plist;
498 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
499 | PRODUCT_BUNDLE_IDENTIFIER = com.aotumanlady..TagGroupDemoUITests;
500 | PRODUCT_NAME = "$(TARGET_NAME)";
501 | TEST_TARGET_NAME = TagGroupDemo;
502 | USES_XCTRUNNER = YES;
503 | };
504 | name = Debug;
505 | };
506 | C4F4EAD81C88335400494A7E /* Release */ = {
507 | isa = XCBuildConfiguration;
508 | buildSettings = {
509 | INFOPLIST_FILE = TagGroupDemoUITests/Info.plist;
510 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
511 | PRODUCT_BUNDLE_IDENTIFIER = com.aotumanlady..TagGroupDemoUITests;
512 | PRODUCT_NAME = "$(TARGET_NAME)";
513 | TEST_TARGET_NAME = TagGroupDemo;
514 | USES_XCTRUNNER = YES;
515 | };
516 | name = Release;
517 | };
518 | /* End XCBuildConfiguration section */
519 |
520 | /* Begin XCConfigurationList section */
521 | C4F4EA9E1C88335400494A7E /* Build configuration list for PBXProject "TagGroupDemo" */ = {
522 | isa = XCConfigurationList;
523 | buildConfigurations = (
524 | C4F4EACE1C88335400494A7E /* Debug */,
525 | C4F4EACF1C88335400494A7E /* Release */,
526 | );
527 | defaultConfigurationIsVisible = 0;
528 | defaultConfigurationName = Release;
529 | };
530 | C4F4EAD01C88335400494A7E /* Build configuration list for PBXNativeTarget "TagGroupDemo" */ = {
531 | isa = XCConfigurationList;
532 | buildConfigurations = (
533 | C4F4EAD11C88335400494A7E /* Debug */,
534 | C4F4EAD21C88335400494A7E /* Release */,
535 | );
536 | defaultConfigurationIsVisible = 0;
537 | defaultConfigurationName = Release;
538 | };
539 | C4F4EAD31C88335400494A7E /* Build configuration list for PBXNativeTarget "TagGroupDemoTests" */ = {
540 | isa = XCConfigurationList;
541 | buildConfigurations = (
542 | C4F4EAD41C88335400494A7E /* Debug */,
543 | C4F4EAD51C88335400494A7E /* Release */,
544 | );
545 | defaultConfigurationIsVisible = 0;
546 | defaultConfigurationName = Release;
547 | };
548 | C4F4EAD61C88335400494A7E /* Build configuration list for PBXNativeTarget "TagGroupDemoUITests" */ = {
549 | isa = XCConfigurationList;
550 | buildConfigurations = (
551 | C4F4EAD71C88335400494A7E /* Debug */,
552 | C4F4EAD81C88335400494A7E /* Release */,
553 | );
554 | defaultConfigurationIsVisible = 0;
555 | defaultConfigurationName = Release;
556 | };
557 | /* End XCConfigurationList section */
558 | };
559 | rootObject = C4F4EA9B1C88335400494A7E /* Project object */;
560 | }
561 |
--------------------------------------------------------------------------------
/TagGroupDemo/TagGroupDemo/MaxShapeView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ShapeView.m
3 | // TagGroupDemo
4 | //
5 | // Created by zmw on 16/5/4.
6 | // Copyright © 2016年 Beijing ChunFengShiLi Technology Co., Ltd. All rights reserved.
7 | //
8 |
9 | #import "MaxLightingView.h"
10 | #import "MaxShapeView.h"
11 | #import "NSString+SizeWithFont.h"
12 | //
13 | #define kHeight50DPDistance 25
14 | #define kHegiht60DPDistance 30
15 |
16 | #define kSlash30DPLineWidth 15
17 | #define kSlash40DPLineWidth 20
18 | #define kSlash50DPLineWidth 25
19 | #define kSlash70DPLineWidth 35
20 |
21 | #define kLabelHeight 25
22 | #define kTheLeftIndex 1
23 | #define kLineValue 1
24 |
25 | #define kWithePointWidth 6
26 |
27 | #define kBaseTag 2000
28 |
29 | #define ktagColor [UIColor whiteColor]
30 |
31 | @interface MaxShapeView () {
32 | UILongPressGestureRecognizer *_longPressGestureRecognizer;
33 | UITapGestureRecognizer *_tapGestureRecognizer;
34 | UITapGestureRecognizer *_label0TapGestureRecognizer;
35 | UITapGestureRecognizer *_label1TapGestureRecognizer;
36 | UITapGestureRecognizer *_label2TapGestureRecognizer;
37 | BOOL _isDragging;
38 |
39 | CAShapeLayer *_lineLayer0;
40 | CAShapeLayer *_linePoint0;
41 | CAShapeLayer *_lineLayer1;
42 | CAShapeLayer *_linePoint1;
43 | CAShapeLayer *_lineLayer2;
44 | CAShapeLayer *_linePoint2;
45 |
46 | UILabel *_lineLabel0;
47 | UILabel *_lineLabel1;
48 | UILabel *_lineLabel2;
49 |
50 | CGRect _superFrame;
51 | }
52 |
53 | @property(strong, nonatomic) MaxLightingView *lightingView;
54 | @property(assign, nonatomic) CGPoint beginpoint;
55 |
56 | @end
57 |
58 | @implementation MaxShapeView
59 |
60 | + (Class)layerClass {
61 | return [CAShapeLayer class];
62 | }
63 |
64 | - (CAShapeLayer *)shapeLayer {
65 | return (CAShapeLayer *)self.layer;
66 | }
67 |
68 | - (MaxLightingView *)lightingView {
69 |
70 | if (!_lightingView)
71 | {
72 | _lightingView =
73 | [[MaxLightingView alloc] initWithFrame:CGRectZero animationRepeats:YES];
74 |
75 | [self addSubview:_lightingView];
76 | }
77 | return _lightingView;
78 | }
79 |
80 | - (id)initWithFrame:(CGRect)frame
81 | point:(CGPoint)point
82 | tagGroup:(NSArray *)tagGroup
83 | tagType:(kMaxTagGroupType)type
84 | superFrame:(CGRect)superFrame {
85 | if (self = [super initWithFrame:frame]) {
86 | _superFrame = superFrame;
87 | self.type = type;
88 |
89 | if (type == kMaxTagGroupTypeDefault) {
90 |
91 | if (tagGroup.count == 1) {
92 | self.type = kMaxTagGroupOneTagTypeRight;
93 | } else if (tagGroup.count == 2) {
94 | self.type = kMaxTagGroupTwoTagTypeBrokenRight;
95 | } else if (tagGroup.count == 3) {
96 | self.type = kMaxTagGroupThreeTagTypeLeftBottom;
97 | }
98 | }
99 |
100 | self.opaque = NO;
101 | self.translatesAutoresizingMaskIntoConstraints = NO;
102 | self.reverse = NO;
103 | self.point = point;
104 | self.tagGroup = tagGroup;
105 | self.tagPointsArry = [NSMutableArray arrayWithCapacity:self.tagGroup.count];
106 | self.animationGroup =
107 | [NSMutableArray arrayWithCapacity:self.tagGroup.count];
108 |
109 | _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] init];
110 | [_longPressGestureRecognizer addTarget:self
111 | action:@selector(gestureRecognizerHandle:)];
112 | [_longPressGestureRecognizer setAllowableMovement:0];
113 | [self addGestureRecognizer:_longPressGestureRecognizer];
114 |
115 | _tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
116 | [_tapGestureRecognizer addTarget:self
117 | action:@selector(gestureRecognizerHandle:)];
118 | [self addGestureRecognizer:_tapGestureRecognizer];
119 |
120 | [self drawLine];
121 | }
122 |
123 | return self;
124 | }
125 |
126 | - (void)drawLine {
127 | if (self.tagGroup.count == 1) {
128 | [self drawLineOne];
129 | } else if (self.tagGroup.count == 2) {
130 | [self drawLineTwo];
131 | } else {
132 | [self drawLineThree];
133 | }
134 | }
135 |
136 | - (void)drawLineOne {
137 |
138 | CGPoint point = CGPointMake(0, kLabelHeight / 2);
139 | //添加 文字显示
140 | CGFloat lineWidth = [NSString widthWithAttributes:nil text:self.tagGroup[0]];
141 | NSMutableDictionary *tagPointsArry =
142 | [NSMutableDictionary dictionaryWithCapacity:self.tagGroup.count];
143 |
144 | if (self.type == kMaxTagGroupOneTagTypeRight) {
145 |
146 | point = CGPointMake(0, kLabelHeight / 2);
147 |
148 | self.frame = CGRectMake(self.point.x, self.point.y,
149 | lineWidth + kSlash50DPLineWidth, kLabelHeight);
150 |
151 | NSMutableArray *lineBranch = [NSMutableArray
152 | arrayWithObjects:[NSValue valueWithCGPoint:point],
153 | [NSValue
154 | valueWithCGPoint:CGPointMake(
155 | point.x + kSlash50DPLineWidth,
156 | point.y)],
157 | nil];
158 | [tagPointsArry setObject:lineBranch forKey:@(0)];
159 | } else if (self.type == kMaxTagGroupOneTagTypeLeft) {
160 |
161 | point = CGPointMake(lineWidth + kSlash50DPLineWidth, kLabelHeight / 2);
162 |
163 | self.frame = CGRectMake(self.point.x - lineWidth, self.point.y,
164 | lineWidth + kSlash50DPLineWidth, kLabelHeight);
165 | NSMutableArray *lineBranch = [NSMutableArray
166 | arrayWithObjects:[NSValue valueWithCGPoint:point],
167 | [NSValue
168 | valueWithCGPoint:CGPointMake(
169 | point.x - kSlash50DPLineWidth,
170 | point.y)],
171 | nil];
172 | [tagPointsArry setObject:lineBranch forKey:@(0)];
173 | } else if (self.type == kMaxTagGroupOneTagTypeLeftBottom) {
174 | self.frame = CGRectMake(
175 | self.point.x - (kSlash50DPLineWidth + lineWidth + kSlash30DPLineWidth),
176 | self.point.y, lineWidth + kSlash50DPLineWidth + kSlash30DPLineWidth,
177 | kHeight50DPDistance + kLabelHeight / 2);
178 |
179 | point = CGPointMake(CGRectGetWidth(self.frame), 0);
180 |
181 | NSMutableArray *lineBranch = [NSMutableArray
182 | arrayWithObjects:[NSValue valueWithCGPoint:point],
183 | [NSValue
184 | valueWithCGPoint:CGPointMake(
185 | point.x - kSlash50DPLineWidth,
186 | point.y +
187 | kHeight50DPDistance)],
188 | [NSValue
189 | valueWithCGPoint:CGPointMake(
190 | point.x -
191 | kSlash50DPLineWidth -
192 | kSlash30DPLineWidth,
193 | point.y +
194 | kHeight50DPDistance)],
195 | nil];
196 | [tagPointsArry setObject:lineBranch forKey:@(0)];
197 | } else if (self.type == kMaxTagGroupOneTagTypeRightBottom) {
198 | self.frame =
199 | CGRectMake(self.point.x, self.point.y,
200 | lineWidth + kSlash50DPLineWidth + kSlash30DPLineWidth,
201 | kHeight50DPDistance + kLabelHeight / 2);
202 | point = CGPointMake(0, 0);
203 | NSMutableArray *lineBranch = [NSMutableArray
204 | arrayWithObjects:[NSValue valueWithCGPoint:point],
205 | [NSValue
206 | valueWithCGPoint:CGPointMake(
207 | point.x + kSlash50DPLineWidth,
208 | point.y +
209 | kHeight50DPDistance)],
210 | [NSValue
211 | valueWithCGPoint:CGPointMake(
212 | point.x +
213 | kSlash50DPLineWidth +
214 | kSlash30DPLineWidth,
215 | point.y +
216 | kHeight50DPDistance)],
217 | nil];
218 | [tagPointsArry setObject:lineBranch forKey:@(0)];
219 | }
220 |
221 | self.lightingView.frame = CGRectMake(0, 0, 30.f, 30.f);
222 | self.lightingView.centerPoint = point;
223 |
224 | if (self.frame.origin.x < 0) {
225 | self.frame = CGRectMake(0, self.frame.origin.y, self.frame.size.width,
226 | self.frame.size.height);
227 | }
228 |
229 | if (self.frame.origin.y < 0) {
230 | self.frame = CGRectMake(self.frame.origin.x, 0, self.frame.size.width,
231 | self.frame.size.height);
232 | }
233 | if (CGRectGetMaxX(self.frame) > _superFrame.size.width) {
234 | self.frame = CGRectMake(_superFrame.size.width - self.frame.size.width,
235 | self.frame.origin.y, self.frame.size.width,
236 | self.frame.size.height);
237 | }
238 |
239 | if (CGRectGetMaxY(self.frame) > _superFrame.size.height) {
240 | self.frame = CGRectMake(self.frame.origin.x,
241 | _superFrame.size.height - self.frame.size.height,
242 | self.frame.size.width, self.frame.size.height);
243 | }
244 |
245 | [tagPointsArry enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key,
246 | NSArray *_Nonnull points,
247 | BOOL *_Nonnull stop) {
248 |
249 | NSInteger idx = [key integerValue];
250 | CGPoint lastPoint = [[points lastObject] CGPointValue];
251 |
252 | CAShapeLayer *lineLayer = nil;
253 | CAShapeLayer *linePoint = nil;
254 | UILabel *textlabel = nil;
255 |
256 | if (!_lineLayer0) {
257 | _lineLabel0 = [[UILabel alloc] init];
258 | _lineLayer0 = [CAShapeLayer layer];
259 | [self.layer addSublayer:_lineLayer0];
260 | [self addSubview:_lineLabel0];
261 |
262 | _label0TapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
263 | [_label0TapGestureRecognizer addTarget:self
264 | action:@selector(gestureRecognizerHandle:)];
265 | _lineLabel0.userInteractionEnabled = YES;
266 | [_lineLabel0 addGestureRecognizer:_label0TapGestureRecognizer];
267 | _linePoint0 = [self whiteLayer];
268 | [_lineLayer0 addSublayer:_linePoint0];
269 | }
270 | lineLayer = _lineLayer0;
271 | textlabel = _lineLabel0;
272 | linePoint = _linePoint0;
273 | {
274 | if (_lineLayer1) {
275 | [_lineLayer1 removeFromSuperlayer];
276 | _lineLayer1 = nil;
277 | [_linePoint1 removeFromSuperlayer];
278 | _linePoint1 = nil;
279 | [_lineLabel1 removeFromSuperview];
280 | _lineLabel1 = nil;
281 | }
282 | if (_lineLayer2) {
283 | [_lineLayer2 removeFromSuperlayer];
284 | _lineLayer2 = nil;
285 | [_linePoint2 removeFromSuperlayer];
286 | _linePoint2 = nil;
287 | [_lineLabel2 removeFromSuperview];
288 | _lineLabel2 = nil;
289 | }
290 | }
291 |
292 | //清空面板
293 | lineLayer.path = nil;
294 | textlabel.frame = CGRectZero;
295 | lineLayer.strokeColor = ktagColor.CGColor;
296 | textlabel.text = nil;
297 | textlabel.textColor = ktagColor;
298 | textlabel.textAlignment = NSTextAlignmentCenter;
299 | // 指定frame,只是为了设置宽度和高度
300 | // 设置居中显示
301 | // 设置填充颜色
302 | lineLayer.fillColor = [UIColor clearColor].CGColor;
303 | // 设置线宽
304 | lineLayer.lineWidth = kLineValue;
305 |
306 | // 使用UIBezierPath创建路径
307 | UIBezierPath *linePath = [UIBezierPath bezierPath];
308 |
309 | [points enumerateObjectsUsingBlock:^(NSValue *_Nonnull pointNumber,
310 | NSUInteger idx, BOOL *_Nonnull stop) {
311 |
312 | CGPoint point = pointNumber.CGPointValue;
313 | if (idx == 0) {
314 | [linePath moveToPoint:point];
315 | } else {
316 | [linePath addLineToPoint:point];
317 | }
318 |
319 | }];
320 |
321 | // 设置CAShapeLayer与UIBezierPath关联
322 | lineLayer.path = linePath.CGPath;
323 |
324 | //创建动画
325 | CABasicAnimation *animation = [CABasicAnimation
326 | animationWithKeyPath:NSStringFromSelector(@selector(strokeEnd))];
327 | animation.fromValue = @0.0;
328 | animation.toValue = @1.0;
329 | animation.delegate = self;
330 | animation.duration = 0.8;
331 |
332 | [lineLayer addAnimation:animation forKey:nil];
333 |
334 | linePoint.hidden = YES;
335 | linePoint.frame = CGRectMake(0, 0, 6.f, 6.f);
336 | NSValue *point = [points lastObject];
337 | linePoint.position = point.CGPointValue;
338 |
339 | //添加 文字显示
340 | switch (self.type) {
341 | case kMaxTagGroupOneTagTypeRight:
342 | case kMaxTagGroupOneTagTypeRightBottom: {
343 | [textlabel
344 | setFrame:CGRectMake(lastPoint.x + kWithePointWidth, lastPoint.y - kLabelHeight / 2,
345 | lineWidth - kWithePointWidth, kLabelHeight)];
346 | } break;
347 | case kMaxTagGroupOneTagTypeLeft:
348 | case kMaxTagGroupOneTagTypeLeftBottom: {
349 | [textlabel setFrame:CGRectMake(lastPoint.x - lineWidth,
350 | lastPoint.y - kLabelHeight / 2, lineWidth - kWithePointWidth,
351 | kLabelHeight)];
352 | } break;
353 | default:
354 | break;
355 | }
356 |
357 | textlabel.text = self.tagGroup[idx];
358 | textlabel.font = [UIFont systemFontOfSize:13];
359 | textlabel.hidden = YES;
360 | }];
361 | }
362 |
363 | - (void)drawLineTwo {
364 |
365 | CGPoint point = CGPointMake(0, 0);
366 | //添加 文字显示
367 | CGFloat maxLength = [NSString maxestWidthWithStringArray:self.tagGroup];
368 | NSMutableDictionary *tagPointsArry =
369 | [NSMutableDictionary dictionaryWithCapacity:self.tagGroup.count];
370 |
371 | if (self.type == kMaxTagGroupTwoTagTypeBrokenRight) {
372 | //这里需要考虑右侧是不是在父视图外侧,这个时候要整体往左侧移动,但是可能存在左侧移除父视图的外部(要定义规则)
373 |
374 | self.frame = CGRectMake(
375 | self.point.x, self.point.y - kHeight50DPDistance + kLabelHeight / 2,
376 | kSlash50DPLineWidth + kSlash30DPLineWidth + maxLength,
377 | 2 * kHeight50DPDistance + kLabelHeight);
378 |
379 | point = CGPointMake(0, CGRectGetHeight(self.frame) / 2);
380 | for (int idx = 0; idx < self.tagGroup.count; idx++) {
381 | // CGFloat lineWidth =
382 | // [NSString widthWithAttributes:nil text:self.tagGroup[idx]];
383 | NSMutableArray *lineBranch;
384 | switch (idx) {
385 | case 0: {
386 | lineBranch = [NSMutableArray
387 | arrayWithObjects:
388 | [NSValue valueWithCGPoint:point],
389 | [NSValue valueWithCGPoint:CGPointMake(
390 | point.x + kSlash50DPLineWidth,
391 | point.y - kHeight50DPDistance)],
392 | [NSValue valueWithCGPoint:CGPointMake(
393 | point.x + kSlash50DPLineWidth +
394 | kSlash30DPLineWidth,
395 | point.y - kHeight50DPDistance)],
396 | nil];
397 | [tagPointsArry setObject:lineBranch forKey:@(0)];
398 | } break;
399 | case 1: {
400 | lineBranch = [NSMutableArray
401 | arrayWithObjects:
402 | [NSValue valueWithCGPoint:point],
403 | [NSValue valueWithCGPoint:CGPointMake(
404 | point.x + kSlash50DPLineWidth,
405 | point.y + kHeight50DPDistance)],
406 | [NSValue valueWithCGPoint:CGPointMake(
407 | point.x + kSlash50DPLineWidth +
408 | kSlash30DPLineWidth,
409 | point.y + kHeight50DPDistance)],
410 | nil];
411 | [tagPointsArry setObject:lineBranch forKey:@(1)];
412 | } break;
413 | }
414 | }
415 | } else if (self.type == kMaxTagGroupTypeBrokenBrokenLeft) {
416 |
417 | //这里要考虑左侧是不是在父视图的外侧,这个时候要整体往右侧移动,但是这个时候可能存在右侧在父视图的外部
418 | self.frame = CGRectMake(
419 | self.point.x - maxLength - kSlash50DPLineWidth - kSlash30DPLineWidth,
420 | self.point.y - kHeight50DPDistance - kLabelHeight / 2,
421 | kSlash50DPLineWidth + kSlash30DPLineWidth + maxLength,
422 | 2 * kHeight50DPDistance + kLabelHeight);
423 |
424 | point = CGPointMake(CGRectGetWidth(self.frame),
425 | CGRectGetHeight(self.frame) / 2);
426 |
427 | for (int idx = 0; idx < self.tagGroup.count; idx++) {
428 | NSMutableArray *lineBranch;
429 | switch (idx) {
430 | case 0: {
431 | lineBranch = [NSMutableArray
432 | arrayWithObjects:
433 | [NSValue valueWithCGPoint:point],
434 | [NSValue valueWithCGPoint:CGPointMake(
435 | point.x - kSlash50DPLineWidth,
436 | point.y - kHeight50DPDistance)],
437 | [NSValue valueWithCGPoint:CGPointMake(
438 | point.x - kSlash50DPLineWidth -
439 | kSlash30DPLineWidth,
440 | point.y - kHeight50DPDistance)],
441 | nil];
442 | [tagPointsArry setObject:lineBranch forKey:@(0)];
443 | } break;
444 | case 1: {
445 | lineBranch = [NSMutableArray
446 | arrayWithObjects:
447 | [NSValue valueWithCGPoint:point],
448 | [NSValue valueWithCGPoint:CGPointMake(
449 | point.x - kSlash50DPLineWidth,
450 | point.y + kHeight50DPDistance)],
451 | [NSValue valueWithCGPoint:CGPointMake(
452 | point.x - kSlash50DPLineWidth -
453 | kSlash30DPLineWidth,
454 | point.y + kHeight50DPDistance)],
455 | nil];
456 | [tagPointsArry setObject:lineBranch forKey:@(1)];
457 | } break;
458 | }
459 | }
460 | } else if (self.type == kMaxTagGroupTwoTagTypeRight) {
461 | //这里需要考虑右侧是不是在父视图外侧,这个时候要整体往左侧移动,但是可能存在左侧移除父视图的外部(要定义规则)
462 |
463 | self.frame = CGRectMake(self.point.x, self.point.y - kSlash40DPLineWidth +
464 | kLabelHeight / 2,
465 | kSlash40DPLineWidth + maxLength,
466 | 2 * kHeight50DPDistance + kLabelHeight);
467 |
468 | point = CGPointMake(0, CGRectGetHeight(self.frame) / 2);
469 | for (int idx = 0; idx < self.tagGroup.count; idx++) {
470 | // CGFloat lineWidth =
471 | // [NSString widthWithAttributes:nil text:self.tagGroup[idx]];
472 | NSMutableArray *lineBranch;
473 | switch (idx) {
474 | case 0: {
475 | lineBranch = [NSMutableArray
476 | arrayWithObjects:[NSValue valueWithCGPoint:point],
477 | [NSValue
478 | valueWithCGPoint:CGPointMake(
479 | point.x,
480 | point.y -
481 | kHeight50DPDistance)],
482 | [NSValue
483 | valueWithCGPoint:CGPointMake(
484 | point.x +
485 | kSlash40DPLineWidth,
486 | point.y -
487 | kHeight50DPDistance)],
488 | nil];
489 | [tagPointsArry setObject:lineBranch forKey:@(0)];
490 | } break;
491 | case 1: {
492 | lineBranch = [NSMutableArray
493 | arrayWithObjects:[NSValue valueWithCGPoint:point],
494 | [NSValue
495 | valueWithCGPoint:CGPointMake(
496 | point.x,
497 | point.y +
498 | kHeight50DPDistance)],
499 | [NSValue
500 | valueWithCGPoint:CGPointMake(
501 | point.x +
502 | kSlash40DPLineWidth,
503 | point.y +
504 | kHeight50DPDistance)],
505 | nil];
506 | [tagPointsArry setObject:lineBranch forKey:@(1)];
507 | } break;
508 | }
509 | }
510 | } else if (self.type == kMaxTagGroupTwoTagTypeLeft) {
511 | //这里需要考虑右侧是不是在父视图外侧,这个时候要整体往左侧移动,但是可能存在左侧移除父视图的外部(要定义规则)
512 |
513 | self.frame =
514 | CGRectMake(self.point.x - (kSlash40DPLineWidth + maxLength),
515 | self.point.y - kHeight50DPDistance + kLabelHeight / 2,
516 | kSlash40DPLineWidth + maxLength,
517 | 2 * kHeight50DPDistance + kLabelHeight);
518 |
519 | point = CGPointMake(CGRectGetWidth(self.frame),
520 | CGRectGetHeight(self.frame) / 2);
521 | for (int idx = 0; idx < self.tagGroup.count; idx++) {
522 |
523 | NSMutableArray *lineBranch;
524 | switch (idx) {
525 | case 0: {
526 | lineBranch = [NSMutableArray
527 | arrayWithObjects:[NSValue valueWithCGPoint:point],
528 | [NSValue
529 | valueWithCGPoint:CGPointMake(
530 | point.x,
531 | point.y -
532 | kHeight50DPDistance)],
533 | [NSValue
534 | valueWithCGPoint:CGPointMake(
535 | point.x -
536 | kSlash40DPLineWidth,
537 | point.y -
538 | kHeight50DPDistance)],
539 | nil];
540 | [tagPointsArry setObject:lineBranch forKey:@(0)];
541 | } break;
542 | case 1: {
543 | lineBranch = [NSMutableArray
544 | arrayWithObjects:[NSValue valueWithCGPoint:point],
545 | [NSValue
546 | valueWithCGPoint:CGPointMake(
547 | point.x,
548 | point.y +
549 | kHeight50DPDistance)],
550 | [NSValue
551 | valueWithCGPoint:CGPointMake(
552 | point.x -
553 | kSlash40DPLineWidth,
554 | point.y +
555 | kHeight50DPDistance)],
556 | nil];
557 | [tagPointsArry setObject:lineBranch forKey:@(1)];
558 | } break;
559 | }
560 | }
561 | }
562 |
563 | self.lightingView.centerPoint = point;
564 |
565 | if (self.frame.origin.x < 0) {
566 | self.frame = CGRectMake(0, self.frame.origin.y, self.frame.size.width,
567 | self.frame.size.height);
568 | }
569 |
570 | if (self.frame.origin.y < 0) {
571 | self.frame = CGRectMake(self.frame.origin.x, 0, self.frame.size.width,
572 | self.frame.size.height);
573 | }
574 | if (CGRectGetMaxX(self.frame) > _superFrame.size.width) {
575 | self.frame = CGRectMake(_superFrame.size.width - self.frame.size.width,
576 | self.frame.origin.y, self.frame.size.width,
577 | self.frame.size.height);
578 | }
579 |
580 | if (CGRectGetMaxY(self.frame) > _superFrame.size.height) {
581 | self.frame = CGRectMake(self.frame.origin.x,
582 | _superFrame.size.height - self.frame.size.height,
583 | self.frame.size.width, self.frame.size.height);
584 | }
585 |
586 | [tagPointsArry enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key,
587 | NSArray *_Nonnull points,
588 | BOOL *_Nonnull stop) {
589 |
590 | NSInteger idx = [key integerValue];
591 | NSInteger currentTagIndex = 0;
592 | CGPoint lastPoint = [[points lastObject] CGPointValue];
593 |
594 | CAShapeLayer *lineLayer = nil;
595 | CAShapeLayer *linePoint = nil;
596 | UILabel *textlabel = nil;
597 | switch (idx) {
598 | case 0: {
599 | if (!_lineLayer0) {
600 | _lineLabel0 = [[UILabel alloc] init];
601 | _lineLayer0 = [CAShapeLayer layer];
602 | [self.layer addSublayer:_lineLayer0];
603 | [self addSubview:_lineLabel0];
604 |
605 | _label0TapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
606 | [_label0TapGestureRecognizer addTarget:self
607 | action:@selector(gestureRecognizerHandle:)];
608 | _lineLabel0.userInteractionEnabled = YES;
609 | [_lineLabel0 addGestureRecognizer:_label0TapGestureRecognizer];
610 | _linePoint0 = [self whiteLayer];
611 | [_lineLayer0 addSublayer:_linePoint0];
612 | }
613 | lineLayer = _lineLayer0;
614 | linePoint = _linePoint0;
615 | textlabel = _lineLabel0;
616 | currentTagIndex = 0;
617 | } break;
618 | case 1: {
619 | if (!_lineLayer1) {
620 | _lineLabel1 = [[UILabel alloc] init];
621 | _lineLayer1 = [CAShapeLayer layer];
622 | [self.layer addSublayer:_lineLayer1];
623 | [self addSubview:_lineLabel1];
624 |
625 | _label1TapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
626 | [_label1TapGestureRecognizer addTarget:self
627 | action:@selector(gestureRecognizerHandle:)];
628 | _lineLabel1.userInteractionEnabled = YES;
629 | [_lineLabel1 addGestureRecognizer:_label1TapGestureRecognizer];
630 |
631 | _linePoint1 = [self whiteLayer];
632 | [_lineLayer1 addSublayer:_linePoint1];
633 | }
634 | lineLayer = _lineLayer1;
635 | linePoint = _linePoint1;
636 | textlabel = _lineLabel1;
637 | currentTagIndex = 1;
638 | } break;
639 | default:
640 | lineLayer = [CAShapeLayer layer];
641 | break;
642 | }
643 |
644 | //清空面板
645 | lineLayer.path = nil;
646 | textlabel.frame = CGRectZero;
647 | lineLayer.strokeColor = ktagColor.CGColor;
648 | textlabel.text = nil;
649 | textlabel.textColor = ktagColor;
650 | textlabel.textAlignment = NSTextAlignmentCenter;
651 | // 指定frame,只是为了设置宽度和高度
652 | // 设置居中显示
653 | // 设置填充颜色
654 | lineLayer.fillColor = [UIColor clearColor].CGColor;
655 | // 设置线宽
656 | lineLayer.lineWidth = kLineValue;
657 |
658 | // 使用UIBezierPath创建路径
659 | UIBezierPath *linePath = [UIBezierPath bezierPath];
660 |
661 | [points enumerateObjectsUsingBlock:^(NSValue *_Nonnull pointNumber,
662 | NSUInteger idx, BOOL *_Nonnull stop) {
663 |
664 | CGPoint point = pointNumber.CGPointValue;
665 | if (idx == 0) {
666 | [linePath moveToPoint:point];
667 | } else {
668 | [linePath addLineToPoint:point];
669 | }
670 |
671 | }];
672 |
673 | // 设置CAShapeLayer与UIBezierPath关联
674 | lineLayer.path = linePath.CGPath;
675 |
676 | //创建动画
677 | CABasicAnimation *animation = [CABasicAnimation
678 | animationWithKeyPath:NSStringFromSelector(@selector(strokeEnd))];
679 | animation.fromValue = @0.0;
680 | animation.toValue = @1.0;
681 | animation.delegate = self;
682 | animation.duration = 0.8;
683 |
684 | [lineLayer addAnimation:animation forKey:nil];
685 |
686 | linePoint.hidden = YES;
687 | linePoint.frame = CGRectMake(0, 0, 6.f, 6.f);
688 | NSValue *point = [points lastObject];
689 | linePoint.position = point.CGPointValue;
690 |
691 | CGFloat lineWidth =
692 | [NSString widthWithAttributes:nil text:self.tagGroup[currentTagIndex]];
693 | //添加 文字显示
694 | //添加 文字显示
695 | switch (self.type) {
696 | case kMaxTagGroupTwoTagTypeBrokenRight:
697 | case kMaxTagGroupTwoTagTypeRight: {
698 | [textlabel
699 | setFrame:CGRectMake(lastPoint.x + kWithePointWidth, lastPoint.y - kLabelHeight / 2,
700 | lineWidth - kWithePointWidth, kLabelHeight)];
701 | } break;
702 | case kMaxTagGroupTypeBrokenBrokenLeft:
703 | case kMaxTagGroupTwoTagTypeLeft: {
704 | [textlabel setFrame:CGRectMake(lastPoint.x - lineWidth,
705 | lastPoint.y - kLabelHeight / 2, lineWidth - kWithePointWidth,
706 | kLabelHeight)];
707 | } break;
708 | default:
709 | break;
710 | }
711 |
712 | textlabel.text = self.tagGroup[currentTagIndex];
713 | textlabel.font = [UIFont systemFontOfSize:12];
714 | textlabel.hidden = YES;
715 | }];
716 | }
717 |
718 | - (void)drawLineThree {
719 | CGPoint point;
720 | //添加 文字显示
721 |
722 | CGFloat maxTotleMaxLength =
723 | [NSString maxestWidthWithStringArray:self.tagGroup];
724 | CGFloat maxSingleSideLength = [NSString
725 | maxestWidthWithStringArray:@[ self.tagGroup[0], self.tagGroup[1] ]];
726 |
727 | NSString *moneyString = [self.tagGroup lastObject];
728 | CGFloat moneyLength = [NSString maxestWidthWithStringArray:@[ moneyString ]];
729 | NSMutableDictionary *tagPointsArry =
730 | [NSMutableDictionary dictionaryWithCapacity:self.tagGroup.count];
731 |
732 | if (self.type == kMaxTagGroupThreeTagTypeLeftBottom) {
733 | //这里需要考虑右侧是不是在父视图外侧,这个时候要整体往左侧移动,但是可能存在左侧移除父视图的外部(要定义规则)
734 |
735 | self.frame =
736 | CGRectMake(self.point.x - (kSlash50DPLineWidth + kSlash30DPLineWidth +
737 | moneyLength),
738 | self.point.y - kHegiht60DPDistance - kLabelHeight / 2,
739 | 2 * (kSlash50DPLineWidth + kSlash30DPLineWidth) +
740 | moneyLength + maxSingleSideLength,
741 | 2 * kHegiht60DPDistance + kLabelHeight);
742 |
743 | point = CGPointMake(moneyLength + kSlash50DPLineWidth + kSlash30DPLineWidth,
744 | CGRectGetHeight(self.frame) / 2);
745 | for (int idx = 0; idx < self.tagGroup.count; idx++) {
746 |
747 | NSMutableArray *lineBranch;
748 | switch (idx) {
749 | case 0: {
750 | lineBranch = [NSMutableArray
751 | arrayWithObjects:
752 | [NSValue valueWithCGPoint:point],
753 | [NSValue valueWithCGPoint:CGPointMake(
754 | point.x + kSlash50DPLineWidth,
755 | point.y - kHegiht60DPDistance)],
756 | [NSValue valueWithCGPoint:CGPointMake(
757 | point.x + kSlash50DPLineWidth +
758 | kSlash30DPLineWidth,
759 | point.y - kHegiht60DPDistance)],
760 | nil];
761 | [tagPointsArry setObject:lineBranch forKey:@(0)];
762 | } break;
763 | case 1: {
764 | lineBranch = [NSMutableArray
765 | arrayWithObjects:
766 | [NSValue valueWithCGPoint:point],
767 | [NSValue valueWithCGPoint:CGPointMake(
768 | point.x + kSlash50DPLineWidth,
769 | point.y + kHegiht60DPDistance)],
770 | [NSValue valueWithCGPoint:CGPointMake(
771 | point.x + kSlash50DPLineWidth +
772 | kSlash30DPLineWidth,
773 | point.y + kHegiht60DPDistance)],
774 | nil];
775 | [tagPointsArry setObject:lineBranch forKey:@(1)];
776 | } break;
777 | case 2: {
778 | lineBranch = [NSMutableArray
779 | arrayWithObjects:
780 | [NSValue valueWithCGPoint:point],
781 | [NSValue valueWithCGPoint:CGPointMake(
782 | point.x - kSlash50DPLineWidth,
783 | point.y + kHegiht60DPDistance)],
784 | [NSValue valueWithCGPoint:CGPointMake(
785 | point.x - kSlash50DPLineWidth -
786 | kSlash30DPLineWidth,
787 | point.y + kHegiht60DPDistance)],
788 | nil];
789 | [tagPointsArry setObject:lineBranch forKey:@(2)];
790 | } break;
791 | }
792 | }
793 | } else if (self.type == kMaxTagGroupThreeTagTypeLeftTop) {
794 | //这里需要考虑右侧是不是在父视图外侧,这个时候要整体往左侧移动,但是可能存在左侧移除父视图的外部(要定义规则)
795 |
796 | self.frame =
797 | CGRectMake(self.point.x - (kSlash50DPLineWidth + kSlash30DPLineWidth +
798 | moneyLength),
799 | self.point.y - kHegiht60DPDistance - kLabelHeight / 2,
800 | 2 * (kSlash50DPLineWidth + kSlash30DPLineWidth) +
801 | moneyLength + maxSingleSideLength,
802 | 2 * kHegiht60DPDistance + kLabelHeight);
803 |
804 | point = CGPointMake(moneyLength + kSlash50DPLineWidth + kSlash30DPLineWidth,
805 | CGRectGetHeight(self.frame) / 2);
806 | for (int idx = 0; idx < self.tagGroup.count; idx++) {
807 |
808 | NSMutableArray *lineBranch;
809 | switch (idx) {
810 | case 0: {
811 | lineBranch = [NSMutableArray
812 | arrayWithObjects:
813 | [NSValue valueWithCGPoint:point],
814 | [NSValue valueWithCGPoint:CGPointMake(
815 | point.x + kSlash50DPLineWidth,
816 | point.y - kHegiht60DPDistance)],
817 | [NSValue valueWithCGPoint:CGPointMake(
818 | point.x + kSlash50DPLineWidth +
819 | kSlash30DPLineWidth,
820 | point.y - kHegiht60DPDistance)],
821 | nil];
822 | [tagPointsArry setObject:lineBranch forKey:@(0)];
823 | } break;
824 | case 1: {
825 | lineBranch = [NSMutableArray
826 | arrayWithObjects:
827 | [NSValue valueWithCGPoint:point],
828 | [NSValue valueWithCGPoint:CGPointMake(
829 | point.x + kSlash50DPLineWidth,
830 | point.y + kHegiht60DPDistance)],
831 | [NSValue valueWithCGPoint:CGPointMake(
832 | point.x + kSlash50DPLineWidth +
833 | kSlash30DPLineWidth,
834 | point.y + kHegiht60DPDistance)],
835 | nil];
836 | [tagPointsArry setObject:lineBranch forKey:@(1)];
837 | } break;
838 | case 2: {
839 | lineBranch = [NSMutableArray
840 | arrayWithObjects:
841 | [NSValue valueWithCGPoint:point],
842 | [NSValue valueWithCGPoint:CGPointMake(
843 | point.x - kSlash50DPLineWidth,
844 | point.y - kHegiht60DPDistance)],
845 | [NSValue valueWithCGPoint:CGPointMake(
846 | point.x - kSlash50DPLineWidth -
847 | kSlash30DPLineWidth,
848 | point.y - kHegiht60DPDistance)],
849 | nil];
850 | [tagPointsArry setObject:lineBranch forKey:@(2)];
851 | } break;
852 | }
853 | }
854 | } else if (self.type == kMaxTagGroupThreeTagTypeRightTop) {
855 | //这里需要考虑右侧是不是在父视图外侧,这个时候要整体往左侧移动,但是可能存在左侧移除父视图的外部(要定义规则)
856 | self.frame =
857 | CGRectMake(self.point.x - (kSlash50DPLineWidth + kSlash30DPLineWidth +
858 | maxSingleSideLength),
859 | self.point.y - kHegiht60DPDistance - kLabelHeight / 2,
860 | 2 * (kSlash50DPLineWidth + kSlash30DPLineWidth) +
861 | moneyLength + maxSingleSideLength,
862 | 2 * kHegiht60DPDistance + kLabelHeight);
863 |
864 | point = CGPointMake(maxSingleSideLength + kSlash50DPLineWidth +
865 | kSlash30DPLineWidth,
866 | CGRectGetHeight(self.frame) / 2);
867 | for (int idx = 0; idx < self.tagGroup.count; idx++) {
868 |
869 | NSMutableArray *lineBranch;
870 | switch (idx) {
871 | case 0: {
872 | lineBranch = [NSMutableArray
873 | arrayWithObjects:
874 | [NSValue valueWithCGPoint:point],
875 | [NSValue valueWithCGPoint:CGPointMake(
876 | point.x - kSlash50DPLineWidth,
877 | point.y - kHegiht60DPDistance)],
878 | [NSValue valueWithCGPoint:CGPointMake(
879 | point.x - kSlash50DPLineWidth -
880 | kSlash30DPLineWidth,
881 | point.y - kHegiht60DPDistance)],
882 | nil];
883 | [tagPointsArry setObject:lineBranch forKey:@(0)];
884 | } break;
885 | case 1: {
886 | lineBranch = [NSMutableArray
887 | arrayWithObjects:
888 | [NSValue valueWithCGPoint:point],
889 | [NSValue valueWithCGPoint:CGPointMake(
890 | point.x - kSlash50DPLineWidth,
891 | point.y + kHegiht60DPDistance)],
892 | [NSValue valueWithCGPoint:CGPointMake(
893 | point.x - kSlash50DPLineWidth -
894 | kSlash30DPLineWidth,
895 | point.y + kHegiht60DPDistance)],
896 | nil];
897 | [tagPointsArry setObject:lineBranch forKey:@(1)];
898 | } break;
899 | case 2: {
900 | lineBranch = [NSMutableArray
901 | arrayWithObjects:
902 | [NSValue valueWithCGPoint:point],
903 | [NSValue valueWithCGPoint:CGPointMake(
904 | point.x + kSlash50DPLineWidth,
905 | point.y - kHegiht60DPDistance)],
906 | [NSValue valueWithCGPoint:CGPointMake(
907 | point.x + kSlash50DPLineWidth +
908 | kSlash30DPLineWidth,
909 | point.y - kHegiht60DPDistance)],
910 | nil];
911 | [tagPointsArry setObject:lineBranch forKey:@(2)];
912 | } break;
913 | }
914 | }
915 | } else if (self.type == kMaxTagGroupThreeTagTypeRightBottom) {
916 | //这里需要考虑右侧是不是在父视图外侧,这个时候要整体往左侧移动,但是可能存在左侧移除父视图的外部(要定义规则)
917 |
918 | self.frame =
919 | CGRectMake(self.point.x - (kSlash50DPLineWidth + kSlash30DPLineWidth +
920 | maxSingleSideLength),
921 | self.point.y - kHegiht60DPDistance - kLabelHeight / 2,
922 | 2 * (kSlash50DPLineWidth + kSlash30DPLineWidth) +
923 | moneyLength + maxSingleSideLength,
924 | 2 * kHegiht60DPDistance + kLabelHeight);
925 |
926 | point = CGPointMake(maxSingleSideLength + kSlash50DPLineWidth +
927 | kSlash30DPLineWidth,
928 | CGRectGetHeight(self.frame) / 2);
929 | for (int idx = 0; idx < self.tagGroup.count; idx++) {
930 |
931 | NSMutableArray *lineBranch;
932 | switch (idx) {
933 | case 0: {
934 | lineBranch = [NSMutableArray
935 | arrayWithObjects:
936 | [NSValue valueWithCGPoint:point],
937 | [NSValue valueWithCGPoint:CGPointMake(
938 | point.x - kSlash50DPLineWidth,
939 | point.y - kHegiht60DPDistance)],
940 | [NSValue valueWithCGPoint:CGPointMake(
941 | point.x - kSlash50DPLineWidth -
942 | kSlash30DPLineWidth,
943 | point.y - kHegiht60DPDistance)],
944 | nil];
945 | [tagPointsArry setObject:lineBranch forKey:@(0)];
946 | } break;
947 | case 1: {
948 | lineBranch = [NSMutableArray
949 | arrayWithObjects:
950 | [NSValue valueWithCGPoint:point],
951 | [NSValue valueWithCGPoint:CGPointMake(
952 | point.x - kSlash50DPLineWidth,
953 | point.y + kHegiht60DPDistance)],
954 | [NSValue valueWithCGPoint:CGPointMake(
955 | point.x - kSlash50DPLineWidth -
956 | kSlash30DPLineWidth,
957 | point.y + kHegiht60DPDistance)],
958 | nil];
959 | [tagPointsArry setObject:lineBranch forKey:@(1)];
960 | } break;
961 | case 2: {
962 | lineBranch = [NSMutableArray
963 | arrayWithObjects:
964 | [NSValue valueWithCGPoint:point],
965 | [NSValue valueWithCGPoint:CGPointMake(
966 | point.x + kSlash50DPLineWidth,
967 | point.y + kHegiht60DPDistance)],
968 | [NSValue valueWithCGPoint:CGPointMake(
969 | point.x + kSlash50DPLineWidth +
970 | kSlash30DPLineWidth,
971 | point.y + kHegiht60DPDistance)],
972 | nil];
973 | [tagPointsArry setObject:lineBranch forKey:@(2)];
974 | } break;
975 | }
976 | }
977 | } else if (self.type == kMaxTagGroupThreeTagTypeBrokenRight) {
978 | //这里需要考虑右侧是不是在父视图外侧,这个时候要整体往左侧移动,但是可能存在左侧移除父视图的外部(要定义规则)
979 |
980 | self.frame = CGRectMake(
981 | self.point.x, self.point.y - kHegiht60DPDistance + kLabelHeight / 2,
982 | kSlash50DPLineWidth + kSlash30DPLineWidth + maxTotleMaxLength,
983 | 2 * kHegiht60DPDistance + kLabelHeight);
984 |
985 | point = CGPointMake(0, CGRectGetHeight(self.frame) / 2);
986 | for (int idx = 0; idx < self.tagGroup.count; idx++) {
987 |
988 | NSMutableArray *lineBranch;
989 | switch (idx) {
990 | case 0: {
991 | lineBranch = [NSMutableArray
992 | arrayWithObjects:
993 | [NSValue valueWithCGPoint:point],
994 | [NSValue valueWithCGPoint:CGPointMake(point.x + kSlash50DPLineWidth,
995 | point.y - kHegiht60DPDistance)],
996 | [NSValue valueWithCGPoint:CGPointMake(point.x + kSlash50DPLineWidth +
997 | kSlash30DPLineWidth,
998 | point.y - kHegiht60DPDistance)],
999 | nil];
1000 | [tagPointsArry setObject:lineBranch forKey:@(0)];
1001 | } break;
1002 | case 1: {
1003 | lineBranch = [NSMutableArray
1004 | arrayWithObjects:[NSValue valueWithCGPoint:point],
1005 | [NSValue
1006 | valueWithCGPoint:CGPointMake(point.x +
1007 | kSlash70DPLineWidth,
1008 | point.y)],
1009 | nil];
1010 | [tagPointsArry setObject:lineBranch forKey:@(1)];
1011 | } break;
1012 | case 2: {
1013 | lineBranch = [NSMutableArray
1014 | arrayWithObjects:
1015 | [NSValue valueWithCGPoint:point],
1016 | [NSValue valueWithCGPoint:CGPointMake(point.x + kSlash50DPLineWidth,
1017 | point.y + kHegiht60DPDistance)],
1018 | [NSValue valueWithCGPoint:CGPointMake(point.x + kSlash50DPLineWidth +
1019 | kSlash30DPLineWidth,
1020 | point.y + kHegiht60DPDistance)],
1021 | nil];
1022 | [tagPointsArry setObject:lineBranch forKey:@(2)];
1023 | } break;
1024 | }
1025 | }
1026 | }
1027 | else if (self.type == kMaxTagGroupThreeTagTypeBrokenLeft)
1028 | {
1029 | self.frame = CGRectMake(self.point.x -
1030 | (kSlash30DPLineWidth + maxTotleMaxLength + kSlash50DPLineWidth),
1031 | self.point.y - kHegiht60DPDistance - kLabelHeight / 2,
1032 | kSlash30DPLineWidth + maxTotleMaxLength + kSlash50DPLineWidth,
1033 | 2 * kHegiht60DPDistance + kLabelHeight);
1034 |
1035 | point = CGPointMake(CGRectGetWidth(self.frame),
1036 | CGRectGetHeight(self.frame) / 2);
1037 | for (int idx = 0; idx < self.tagGroup.count; idx++)
1038 | {
1039 | NSMutableArray *lineBranch;
1040 | switch (idx) {
1041 | case 0: {
1042 | lineBranch = [NSMutableArray
1043 | arrayWithObjects:
1044 | [NSValue valueWithCGPoint:point],
1045 | [NSValue valueWithCGPoint:CGPointMake(point.x - kSlash50DPLineWidth,
1046 | point.y - kHegiht60DPDistance)],
1047 | [NSValue valueWithCGPoint:CGPointMake(point.x - kSlash50DPLineWidth -
1048 | kSlash30DPLineWidth,
1049 | point.y - kHegiht60DPDistance)],
1050 | nil];
1051 | [tagPointsArry setObject:lineBranch forKey:@(0)];
1052 | } break;
1053 | case 1: {
1054 | lineBranch = [NSMutableArray
1055 | arrayWithObjects:[NSValue valueWithCGPoint:point],
1056 | [NSValue
1057 | valueWithCGPoint:CGPointMake(point.x -
1058 | kSlash70DPLineWidth,
1059 | point.y)],
1060 | nil];
1061 | [tagPointsArry setObject:lineBranch forKey:@(1)];
1062 | } break;
1063 | case 2: {
1064 | lineBranch = [NSMutableArray
1065 | arrayWithObjects:
1066 | [NSValue valueWithCGPoint:point],
1067 | [NSValue valueWithCGPoint:CGPointMake(point.x - kSlash50DPLineWidth,
1068 | point.y + kHegiht60DPDistance)],
1069 | [NSValue valueWithCGPoint:CGPointMake(point.x - kSlash50DPLineWidth -
1070 | kSlash30DPLineWidth,
1071 | point.y + kHegiht60DPDistance)],
1072 | nil];
1073 | [tagPointsArry setObject:lineBranch forKey:@(2)];
1074 | } break;
1075 | }
1076 | }
1077 | }
1078 | else if (self.type == kMaxTagGroupThreeTagTypeRight)
1079 | {
1080 | //这里需要考虑右侧是不是在父视图外侧,这个时候要整体往左侧移动,但是可能存在左侧移除父视图的外部(要定义规则)
1081 |
1082 | self.frame = CGRectMake(self.point.x, self.point.y - kHegiht60DPDistance +
1083 | kLabelHeight / 2,
1084 | kSlash40DPLineWidth + maxTotleMaxLength,
1085 | 2 * kHegiht60DPDistance + kLabelHeight);
1086 |
1087 | point = CGPointMake(0, CGRectGetHeight(self.frame) / 2);
1088 | for (int idx = 0; idx < self.tagGroup.count; idx++)
1089 | {
1090 | NSMutableArray *lineBranch;
1091 | switch (idx) {
1092 | case 0: {
1093 | lineBranch = [NSMutableArray
1094 | arrayWithObjects:[NSValue valueWithCGPoint:point],
1095 | [NSValue
1096 | valueWithCGPoint:CGPointMake(point.x,
1097 | point.y -
1098 | kHegiht60DPDistance)],
1099 | [NSValue
1100 | valueWithCGPoint:CGPointMake(point.x +
1101 | kSlash40DPLineWidth,
1102 | point.y -
1103 | kHegiht60DPDistance)],
1104 | nil];
1105 | [tagPointsArry setObject:lineBranch forKey:@(0)];
1106 | } break;
1107 | case 1: {
1108 | lineBranch = [NSMutableArray
1109 | arrayWithObjects:[NSValue valueWithCGPoint:point],
1110 | [NSValue
1111 | valueWithCGPoint:CGPointMake(point.x +
1112 | kSlash40DPLineWidth,
1113 | point.y)],
1114 | nil];
1115 | [tagPointsArry setObject:lineBranch forKey:@(1)];
1116 | } break;
1117 | case 2: {
1118 | lineBranch = [NSMutableArray
1119 | arrayWithObjects:[NSValue valueWithCGPoint:point],
1120 | [NSValue
1121 | valueWithCGPoint:CGPointMake(point.x,
1122 | point.y +
1123 | kHegiht60DPDistance)],
1124 | [NSValue
1125 | valueWithCGPoint:CGPointMake(point.x +
1126 | kSlash40DPLineWidth,
1127 | point.y +
1128 | kHegiht60DPDistance)],
1129 | nil];
1130 | [tagPointsArry setObject:lineBranch forKey:@(2)];
1131 | } break;
1132 | }
1133 | }
1134 | }
1135 | else if (self.type == kMaxTagGroupThreeTagTypeLeft)
1136 | {
1137 | self.frame =
1138 | CGRectMake(self.point.x - (kSlash40DPLineWidth + maxTotleMaxLength),
1139 | self.point.y - kHegiht60DPDistance - kLabelHeight / 2,
1140 | kSlash40DPLineWidth + maxTotleMaxLength,
1141 | 2 * kHegiht60DPDistance + kLabelHeight);
1142 |
1143 | point = CGPointMake(CGRectGetWidth(self.frame),
1144 | CGRectGetHeight(self.frame) / 2);
1145 | for (int idx = 0; idx < self.tagGroup.count; idx++)
1146 | {
1147 | NSMutableArray *lineBranch;
1148 | switch (idx) {
1149 | case 0: {
1150 | lineBranch = [NSMutableArray
1151 | arrayWithObjects:[NSValue valueWithCGPoint:point],
1152 | [NSValue
1153 | valueWithCGPoint:CGPointMake(point.x,
1154 | point.y -
1155 | kHegiht60DPDistance)],
1156 | [NSValue
1157 | valueWithCGPoint:CGPointMake(point.x -
1158 | kSlash40DPLineWidth,
1159 | point.y -
1160 | kHegiht60DPDistance)],
1161 | nil];
1162 | [tagPointsArry setObject:lineBranch forKey:@(0)];
1163 | } break;
1164 | case 1: {
1165 | lineBranch = [NSMutableArray
1166 | arrayWithObjects:[NSValue valueWithCGPoint:point],
1167 | [NSValue
1168 | valueWithCGPoint:CGPointMake(point.x -
1169 | kSlash40DPLineWidth,
1170 | point.y)],
1171 | nil];
1172 | [tagPointsArry setObject:lineBranch forKey:@(1)];
1173 | } break;
1174 | case 2: {
1175 | lineBranch = [NSMutableArray
1176 | arrayWithObjects:[NSValue valueWithCGPoint:point],
1177 | [NSValue
1178 | valueWithCGPoint:CGPointMake(point.x,
1179 | point.y +
1180 | kHegiht60DPDistance)],
1181 | [NSValue
1182 | valueWithCGPoint:CGPointMake(point.x -
1183 | kSlash40DPLineWidth,
1184 | point.y +
1185 | kHegiht60DPDistance)],
1186 | nil];
1187 | [tagPointsArry setObject:lineBranch forKey:@(2)];
1188 | } break;
1189 | }
1190 | }
1191 | }
1192 |
1193 | self.lightingView.centerPoint = point;
1194 |
1195 | if (self.frame.origin.x < 0)
1196 | {
1197 | self.frame = CGRectMake(0,
1198 | self.frame.origin.y,
1199 | self.frame.size.width,
1200 | self.frame.size.height);
1201 | }
1202 |
1203 | if (self.frame.origin.y < 0)
1204 | {
1205 | self.frame = CGRectMake(self.frame.origin.x,
1206 | 0,
1207 | self.frame.size.width,
1208 | self.frame.size.height);
1209 | }
1210 |
1211 | if (CGRectGetMaxX(self.frame) > _superFrame.size.width)
1212 | {
1213 | self.frame = CGRectMake(_superFrame.size.width - self.frame.size.width,
1214 | self.frame.origin.y,
1215 | self.frame.size.width,
1216 | self.frame.size.height);
1217 | }
1218 |
1219 | if (CGRectGetMaxY(self.frame) > _superFrame.size.height)
1220 | {
1221 | self.frame = CGRectMake(self.frame.origin.x,
1222 | _superFrame.size.height - self.frame.size.height,
1223 | self.frame.size.width,
1224 | self.frame.size.height);
1225 | }
1226 |
1227 | [tagPointsArry enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key,
1228 | NSArray *_Nonnull points,
1229 | BOOL *_Nonnull stop) {
1230 |
1231 | NSInteger idx = [key integerValue];
1232 | CGPoint lastPoint = [[points lastObject] CGPointValue];
1233 | NSInteger currentTagIndex = 0;
1234 |
1235 | CAShapeLayer *lineLayer = nil;
1236 | CAShapeLayer *linePoint = nil;
1237 | UILabel *textlabel = nil;
1238 | switch (idx) {
1239 | case 0: {
1240 | if (!_lineLayer0)
1241 | {
1242 | _lineLabel0 = [[UILabel alloc] init];
1243 | _lineLayer0 = [CAShapeLayer layer];
1244 | [self.layer addSublayer:_lineLayer0];
1245 | [self addSubview:_lineLabel0];
1246 |
1247 | _label0TapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
1248 | [_label0TapGestureRecognizer addTarget:self
1249 | action:@selector(gestureRecognizerHandle:)];
1250 | _lineLabel0.userInteractionEnabled = YES;
1251 | [_lineLabel0 addGestureRecognizer:_label0TapGestureRecognizer];
1252 |
1253 | _linePoint0 = [self whiteLayer];
1254 | [_lineLayer0 addSublayer:_linePoint0];
1255 | }
1256 | currentTagIndex = idx;
1257 | lineLayer = _lineLayer0;
1258 | linePoint = _linePoint0;
1259 | textlabel = _lineLabel0;
1260 | } break;
1261 | case 1: {
1262 | if (!_lineLayer1)
1263 | {
1264 | _lineLabel1 = [[UILabel alloc] init];
1265 | _lineLayer1 = [CAShapeLayer layer];
1266 | [self.layer addSublayer:_lineLayer1];
1267 | [self addSubview:_lineLabel1];
1268 |
1269 | _label1TapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
1270 | [_label1TapGestureRecognizer addTarget:self
1271 | action:@selector(gestureRecognizerHandle:)];
1272 | _lineLabel1.userInteractionEnabled = YES;
1273 | [_lineLabel1 addGestureRecognizer:_label1TapGestureRecognizer];
1274 |
1275 | _linePoint1 = [self whiteLayer];
1276 | [_lineLayer1 addSublayer:_linePoint1];
1277 | }
1278 | currentTagIndex = idx;
1279 | lineLayer = _lineLayer1;
1280 | linePoint = _linePoint1;
1281 | textlabel = _lineLabel1;
1282 | } break;
1283 | case 2: {
1284 | if (!_lineLayer2)
1285 | {
1286 | _lineLabel2 = [[UILabel alloc] init];
1287 | _lineLayer2 = [CAShapeLayer layer];
1288 | [self.layer addSublayer:_lineLayer2];
1289 | [self addSubview:_lineLabel2];
1290 |
1291 | _label2TapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
1292 | [_label2TapGestureRecognizer addTarget:self
1293 | action:@selector(gestureRecognizerHandle:)];
1294 | _lineLabel2.userInteractionEnabled = YES;
1295 | [_lineLabel2 addGestureRecognizer:_label2TapGestureRecognizer];
1296 |
1297 | _linePoint2 = [self whiteLayer];
1298 | [_lineLayer2 addSublayer:_linePoint2];
1299 | }
1300 | currentTagIndex = idx;
1301 | lineLayer = _lineLayer2;
1302 | linePoint = _linePoint2;
1303 | textlabel = _lineLabel2;
1304 | } break;
1305 | default:
1306 | lineLayer = [CAShapeLayer layer];
1307 | break;
1308 | }
1309 |
1310 | //清空面板
1311 | lineLayer.path = nil;
1312 | textlabel.frame = CGRectZero;
1313 | lineLayer.strokeColor = ktagColor.CGColor;
1314 | textlabel.text = nil;
1315 | textlabel.textColor = ktagColor;
1316 | textlabel.textAlignment = NSTextAlignmentCenter;
1317 | // 指定frame,只是为了设置宽度和高度
1318 | // 设置居中显示
1319 | // 设置填充颜色
1320 | lineLayer.fillColor = [UIColor clearColor].CGColor;
1321 | // 设置线宽
1322 | lineLayer.lineWidth = kLineValue;
1323 | // 使用UIBezierPath创建路径
1324 | UIBezierPath *linePath = [UIBezierPath bezierPath];
1325 |
1326 | [points enumerateObjectsUsingBlock:^(NSValue *_Nonnull pointNumber, NSUInteger idx, BOOL *_Nonnull stop) {
1327 |
1328 | CGPoint point = pointNumber.CGPointValue;
1329 | if (idx == 0)
1330 | {
1331 | [linePath moveToPoint:point];
1332 | }
1333 | else
1334 | {
1335 | [linePath addLineToPoint:point];
1336 | }
1337 |
1338 | }];
1339 |
1340 | // 设置CAShapeLayer与UIBezierPath关联
1341 | lineLayer.path = linePath.CGPath;
1342 | //创建动画
1343 | CABasicAnimation *animation = [CABasicAnimation
1344 | animationWithKeyPath:NSStringFromSelector(@selector(strokeEnd))];
1345 | animation.fromValue = @0.0;
1346 | animation.toValue = @1.0;
1347 | animation.delegate = self;
1348 | animation.duration = 0.8;
1349 |
1350 | [lineLayer addAnimation:animation forKey:nil];
1351 |
1352 | linePoint.hidden = YES;
1353 | linePoint.frame = CGRectMake(0, 0, 6.f, 6.f);
1354 | NSValue *point = [points lastObject];
1355 | linePoint.position = point.CGPointValue;
1356 |
1357 | CGFloat lineWidth = [NSString widthWithAttributes:nil text:self.tagGroup[currentTagIndex]];
1358 |
1359 | //添加 文字显示
1360 | switch (self.type) {
1361 | case kMaxTagGroupThreeTagTypeRight:
1362 | case kMaxTagGroupThreeTagTypeBrokenRight: {
1363 | [textlabel
1364 | setFrame:CGRectMake(lastPoint.x + kWithePointWidth,
1365 | lastPoint.y - kLabelHeight / 2,
1366 | lineWidth - kWithePointWidth,
1367 | kLabelHeight)];
1368 | } break;
1369 | case kMaxTagGroupThreeTagTypeLeft:
1370 | case kMaxTagGroupThreeTagTypeBrokenLeft: {
1371 | [textlabel setFrame:CGRectMake(lastPoint.x - lineWidth,
1372 | lastPoint.y - kLabelHeight / 2,
1373 | lineWidth - kWithePointWidth,
1374 | kLabelHeight)];
1375 | } break;
1376 | case kMaxTagGroupThreeTagTypeRightTop:
1377 | case kMaxTagGroupThreeTagTypeRightBottom: {
1378 | if (currentTagIndex == 2)
1379 | {
1380 | [textlabel setFrame:CGRectMake(lastPoint.x + kWithePointWidth,
1381 | lastPoint.y - kLabelHeight / 2,
1382 | lineWidth - kWithePointWidth,
1383 | kLabelHeight)];
1384 |
1385 | }
1386 | else
1387 | {
1388 | [textlabel setFrame:CGRectMake(lastPoint.x - lineWidth,
1389 | lastPoint.y - kLabelHeight / 2,
1390 | lineWidth - kWithePointWidth,
1391 | kLabelHeight)];
1392 | }
1393 |
1394 | } break;
1395 | case kMaxTagGroupThreeTagTypeLeftTop:
1396 | case kMaxTagGroupThreeTagTypeLeftBottom: {
1397 |
1398 | if (currentTagIndex != 2)
1399 | {
1400 | [textlabel setFrame:CGRectMake(lastPoint.x + kWithePointWidth,
1401 | lastPoint.y - kLabelHeight / 2,
1402 | lineWidth - kWithePointWidth,
1403 | kLabelHeight)];
1404 |
1405 | }
1406 | else
1407 | {
1408 | [textlabel setFrame:CGRectMake(lastPoint.x - lineWidth,
1409 | lastPoint.y - kLabelHeight / 2,
1410 | lineWidth - kWithePointWidth,
1411 | kLabelHeight)];
1412 | }
1413 |
1414 | } break;
1415 | default:{
1416 |
1417 | }break;
1418 | }
1419 |
1420 | textlabel.text = self.tagGroup[idx];
1421 | textlabel.font = [UIFont systemFontOfSize:12];
1422 | textlabel.hidden = YES;
1423 | }];
1424 | }
1425 |
1426 | #pragma mark - CABasicAnimation delegate
1427 | - (void)animationDidStart:(CAAnimation *)anim
1428 | {
1429 |
1430 | }
1431 |
1432 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
1433 | {
1434 | _lineLabel0.hidden = NO;
1435 | _lineLabel1.hidden = NO;
1436 | _lineLabel2.hidden = NO;
1437 |
1438 | _linePoint0.hidden = NO;
1439 | _linePoint1.hidden = NO;
1440 | _linePoint2.hidden = NO;
1441 | }
1442 |
1443 | #pragma mark - Ges
1444 |
1445 | - (void)gestureRecognizerHandle:(UIGestureRecognizer *)gestureRecognizer
1446 | {
1447 | if (gestureRecognizer == _longPressGestureRecognizer)
1448 | {
1449 | if ([gestureRecognizer state] == UIGestureRecognizerStateBegan)
1450 | {
1451 | if (_longPressBlock)
1452 | {
1453 | _longPressBlock(self);
1454 | }
1455 | }
1456 | }
1457 | else if (gestureRecognizer == _tapGestureRecognizer)
1458 | {
1459 | if ([gestureRecognizer state] == UIGestureRecognizerStateEnded)
1460 | {
1461 | [self changeDirection];
1462 | }
1463 | }
1464 | else if (gestureRecognizer == _label0TapGestureRecognizer)
1465 | {
1466 | if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
1467 | {
1468 | if (_tapGestureRecognizer)
1469 | {
1470 | if (_tapBlock)
1471 | {
1472 | _tapBlock(self, _lineLabel0);
1473 | }
1474 | }
1475 | }
1476 | }
1477 | else if (gestureRecognizer == _label1TapGestureRecognizer)
1478 | {
1479 | if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
1480 | {
1481 | if (_tapGestureRecognizer)
1482 | {
1483 | if (_tapBlock)
1484 | {
1485 | _tapBlock(self, _lineLabel1);
1486 | }
1487 | }
1488 | }
1489 | }
1490 | else if (gestureRecognizer == _label2TapGestureRecognizer)
1491 | {
1492 | if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
1493 | {
1494 | if (_tapGestureRecognizer)
1495 | {
1496 | if (_tapBlock)
1497 | {
1498 | _tapBlock(self, _lineLabel2);
1499 | }
1500 | }
1501 | }
1502 | }
1503 | }
1504 |
1505 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
1506 | {
1507 | _isDragging = NO;
1508 |
1509 | UITouch *touch = [touches anyObject];
1510 | self.beginpoint = [touch locationInView:self];
1511 | [super touchesBegan:touches withEvent:event];
1512 | }
1513 |
1514 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
1515 | {
1516 | _isDragging = YES;
1517 | UITouch *touch = [touches anyObject];
1518 | CGPoint currentLocation = [touch locationInView:self];
1519 | CGRect frame = self.frame;
1520 |
1521 | CGFloat offsetX = currentLocation.x - self.beginpoint.x;
1522 | CGFloat offsetY = currentLocation.y - self.beginpoint.y;
1523 | frame.origin.x += offsetX;
1524 | frame.origin.y += offsetY;
1525 |
1526 | self.point = CGPointMake(self.point.x + offsetX, self.point.y + offsetY);
1527 | self.frame = frame;
1528 |
1529 | if (self.frame.origin.x < 0)
1530 | {
1531 | self.frame = CGRectMake(0,
1532 | self.frame.origin.y,
1533 | self.frame.size.width,
1534 | self.frame.size.height);
1535 | }
1536 |
1537 | if (self.frame.origin.y < 0)
1538 | {
1539 | self.frame = CGRectMake(self.frame.origin.x,
1540 | 0,
1541 | self.frame.size.width,
1542 | self.frame.size.height);
1543 | }
1544 |
1545 | if (CGRectGetMaxX(self.frame) > _superFrame.size.width)
1546 | {
1547 | self.frame = CGRectMake(_superFrame.size.width - self.frame.size.width,
1548 | self.frame.origin.y,
1549 | self.frame.size.width,
1550 | self.frame.size.height);
1551 | }
1552 |
1553 | if (CGRectGetMaxY(self.frame) > _superFrame.size.height)
1554 | {
1555 | self.frame = CGRectMake(self.frame.origin.x,
1556 | _superFrame.size.height - self.frame.size.height,
1557 | self.frame.size.width,
1558 | self.frame.size.height);
1559 | }
1560 | }
1561 |
1562 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
1563 | {
1564 | [super touchesEnded:touches withEvent:event];
1565 | if (_isDragging && _dragDoneBlock)
1566 | {
1567 | _dragDoneBlock(self);
1568 | }
1569 | _isDragging = NO;
1570 | }
1571 |
1572 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
1573 | {
1574 | [super touchesCancelled:touches withEvent:event];
1575 |
1576 | if (_dragCancelBlock)
1577 | {
1578 | _dragCancelBlock(self);
1579 | }
1580 | }
1581 |
1582 | - (CAShapeLayer *)whiteLayer
1583 | {
1584 | UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 6.f, 6.f) cornerRadius:3.f];
1585 | CAShapeLayer *layer = [CAShapeLayer layer];
1586 | layer.path = path.CGPath;
1587 | layer.fillColor = [UIColor whiteColor].CGColor;
1588 | return layer;
1589 | }
1590 |
1591 | - (void)changeDirection
1592 | {
1593 | kMaxTagGroupType value;
1594 | if (self.tagGroup.count == 1)
1595 | {
1596 | value = self.type;
1597 | if (value == kMaxTagGroupTypeDefault)
1598 | {
1599 | value = kMaxTagGroupOneTagTypeRight;
1600 | }
1601 | value++;
1602 | if (value == kMaxTagGroupOneTagTypeLeftBottom+1)
1603 | {
1604 | value = kMaxTagGroupOneTagTypeRight;
1605 | }
1606 | self.type = value;
1607 | }
1608 | else if (self.tagGroup.count == 2)
1609 | {
1610 | value = self.type;
1611 | if (value == kMaxTagGroupTypeDefault)
1612 | {
1613 | value = kMaxTagGroupTwoTagTypeBrokenRight;
1614 | }
1615 | value++;
1616 | if (value == kMaxTagGroupTwoTagTypeLeft+1)
1617 | {
1618 | value = kMaxTagGroupTwoTagTypeBrokenRight;
1619 | }
1620 | self.type = value;
1621 | }
1622 | else if (self.tagGroup.count == 3)
1623 | {
1624 | value = self.type;
1625 | if (value == kMaxTagGroupTypeDefault)
1626 | {
1627 | value = kMaxTagGroupThreeTagTypeLeftBottom;
1628 | }
1629 | value++;
1630 | if (value == kMaxTagGroupThreeTagTypeLeft+1)
1631 | {
1632 | value = kMaxTagGroupThreeTagTypeLeftBottom;
1633 | }
1634 | self.type = value;
1635 | }
1636 | [self drawLine];
1637 | }
1638 | @end
1639 |
--------------------------------------------------------------------------------