├── 录屏1.gif ├── 20161213.png ├── QQRed ├── Assets.xcassets │ ├── Contents.json │ ├── AppIcon.appiconset │ │ ├── AppIcon-1024.png │ │ ├── AppIcon-129x29@2x.png │ │ ├── AppIcon-129x29@3x.png │ │ ├── AppIcon-140x40@2x.png │ │ ├── AppIcon-140x40@3x.png │ │ ├── AppIcon-160x60@2x.png │ │ ├── AppIcon-160x60@3x.png │ │ ├── AppIcon-140x40~ipad.png │ │ └── Contents.json │ ├── launchImage.imageset │ │ ├── launchImage@3x.png │ │ └── Contents.json │ ├── LaunchImage.launchimage │ │ ├── LaunchImage640x1136@2x.png │ │ ├── LaunchImage640x960@2x.png │ │ ├── LaunchImage750x1334@2x.png │ │ ├── LaunchImage-2208x1242@3x.png │ │ ├── LaunchImage1242x2208@3x.png │ │ ├── LaunchImage640x1136@2x-1.png │ │ ├── LaunchImage640x960@2x-1.png │ │ └── Contents.json │ └── boss_unipay_bank_card_button.imageset │ │ ├── boss_unipay_bank_card_button@2x.png │ │ └── Contents.json ├── DragBlast │ ├── imageSoure │ │ ├── unreadBomb_1@2x.png │ │ ├── unreadBomb_2@2x.png │ │ ├── unreadBomb_3@2x.png │ │ ├── unreadBomb_4@2x.png │ │ └── unreadBomb_5@2x.png │ ├── UIView+DragBlast.h │ └── UIView+DragBlast.m ├── ViewController.h ├── DetailViewController.h ├── TableViewController.h ├── AppDelegate.h ├── TableViewCell.h ├── main.m ├── Search │ ├── SearchResurltView.h │ ├── JATagView.h │ ├── JATagView.m │ └── SearchResurltView.m ├── Info.plist ├── AppDelegate.m ├── TableViewCell.m ├── DetailViewController.m ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── TableViewController.m ├── TableViewCell.xib └── ViewController.m ├── QQRed.xcodeproj ├── xcuserdata │ └── jion.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── QQRed.xcscheme ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── jion.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── project.pbxproj ├── QQRedTests ├── Info.plist └── QQRedTests.m ├── QQRedUITests ├── Info.plist └── QQRedUITests.m └── README.md /录屏1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/录屏1.gif -------------------------------------------------------------------------------- /20161213.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/20161213.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /QQRed/DragBlast/imageSoure/unreadBomb_1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/DragBlast/imageSoure/unreadBomb_1@2x.png -------------------------------------------------------------------------------- /QQRed/DragBlast/imageSoure/unreadBomb_2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/DragBlast/imageSoure/unreadBomb_2@2x.png -------------------------------------------------------------------------------- /QQRed/DragBlast/imageSoure/unreadBomb_3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/DragBlast/imageSoure/unreadBomb_3@2x.png -------------------------------------------------------------------------------- /QQRed/DragBlast/imageSoure/unreadBomb_4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/DragBlast/imageSoure/unreadBomb_4@2x.png -------------------------------------------------------------------------------- /QQRed/DragBlast/imageSoure/unreadBomb_5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/DragBlast/imageSoure/unreadBomb_5@2x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@2x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-129x29@3x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@2x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40@3x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@2x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-160x60@3x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/launchImage.imageset/launchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/launchImage.imageset/launchImage@3x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/AppIcon.appiconset/AppIcon-140x40~ipad.png -------------------------------------------------------------------------------- /QQRed.xcodeproj/xcuserdata/jion.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage640x1136@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage640x1136@2x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage640x960@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage640x960@2x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage750x1334@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage750x1334@2x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage-2208x1242@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage-2208x1242@3x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage1242x2208@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage1242x2208@3x.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage640x1136@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage640x1136@2x-1.png -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage640x960@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/LaunchImage.launchimage/LaunchImage640x960@2x-1.png -------------------------------------------------------------------------------- /QQRed.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /QQRed.xcodeproj/project.xcworkspace/xcuserdata/jion.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed.xcodeproj/project.xcworkspace/xcuserdata/jion.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/boss_unipay_bank_card_button.imageset/boss_unipay_bank_card_button@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuzhuxingtianxia/QQRed/HEAD/QQRed/Assets.xcassets/boss_unipay_bank_card_button.imageset/boss_unipay_bank_card_button@2x.png -------------------------------------------------------------------------------- /QQRed/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/12. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /QQRed/DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.h 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/21. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /QQRed/TableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.h 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/15. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /QQRed.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /QQRed/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/12. 6 | // Copyright © 2016年 Youjuke. 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 | -------------------------------------------------------------------------------- /QQRed/TableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewCell.h 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/15. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TableViewCell : UITableViewCell 12 | @property (weak, nonatomic) IBOutlet UILabel *messageLable; 13 | @property (weak, nonatomic) IBOutlet UIButton *messageBtn; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /QQRed/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/12. 6 | // Copyright © 2016年 Youjuke. 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 | -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/launchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "launchImage@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/boss_unipay_bank_card_button.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "boss_unipay_bank_card_button@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /QQRed/DragBlast/UIView+DragBlast.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+DragBlast.h 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/13. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (DragBlast) 12 | //是否使用粒子动画 13 | @property(nonatomic,assign)BOOL isFragment; 14 | //点击爆炸 默认为NO 15 | @property(nonatomic,assign)BOOL tapBlast; 16 | //拖拽爆炸 默认为NO 17 | @property(nonatomic,assign)BOOL dragBlast; 18 | 19 | //拖动爆炸或点击爆炸后的回调 20 | -(void)blastCompletion:(void (^)(BOOL finished))completion; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /QQRed/Search/SearchResurltView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SearchResurltView.h 3 | // AutomobileAccessories 4 | // 5 | // Created by z on 2016/12/15. 6 | // Copyright © 2016年 sensu_nikun. All rights reserved. 7 | /* 8 | #import "SearchResurltView.h" 9 | 10 | SearchResurltView *search = [[SearchResurltView alloc] initWithFrame:CGRectMake(0, 364, 375, 300)]; 11 | [self.view addSubview:search]; 12 | 13 | */ 14 | 15 | #import 16 | typedef void(^dimissSelf)(void); 17 | @interface SearchResurltView : UIView 18 | @property (nonatomic,copy)dimissSelf dimiss; 19 | - (void)dimiss:(dimissSelf)dimiss; 20 | @end 21 | -------------------------------------------------------------------------------- /QQRed/Search/JATagView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JATagView.h 3 | // StudyDemo 4 | // 5 | // Created by z on 2016/12/14. 6 | // Copyright © 2016年 ja. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | enum { 12 | JATagViewDefault =0,//默认是不带有删除按钮 13 | JATagViewDelete,//有删除按钮 14 | //...以后再补充 15 | }; 16 | typedef NSUInteger JATagViewType; 17 | typedef void(^deleteTagBlock)(void); 18 | @interface JATagView : UIView 19 | @property (nonatomic,strong)NSString *tagString; 20 | @property (nonatomic,strong)deleteTagBlock deleteTag; 21 | - (instancetype)initWithFrame:(CGRect)frame withTagType:(JATagViewType)type; 22 | - (void)deleteTagBlock:(deleteTagBlock)deleteTag; 23 | @end 24 | -------------------------------------------------------------------------------- /QQRedTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /QQRedUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QQRed 2 | demo环境Xcode10.0以上 3 | 4 | ## demo讲解地址 5 | 6 | 简书:ios仿QQ消息拖拽效果 7 | 8 | ## demo效果展示 9 | 10 | ![image](https://github.com/873391579/QQRed/blob/master/%E5%BD%95%E5%B1%8F1.gif) 11 | 12 | ## 使用: 13 | 14 | 在文件里找到DragBlast文件夹,然后把该文件夹拖到你的工程中 15 | 16 | 导入 `< import "UIView+DragBlast.h" >` 给对应View设置定义的属性或方法就可以了! 17 | ``` 18 | //设置点击就能爆炸,如果不需要可以不设置,这个点击事件没有设置回调方法 19 | view.tapBlast = YES; 20 | //设置使用绘制的爆炸效果,但是这个效果并不理想,建议不要设置这个属性 21 | // view.isFragment = YES; 22 | /* 23 | 设置拖拽爆炸,如果爆炸后不需要做操作 24 | 则可使用view.dragBlast = YES; 25 | 若爆炸后需要做一些处理,则可使用下面的block方法。 26 | */ 27 | [view blastCompletion:^(BOOL finished) { 28 | //do something 29 | }]; 30 | ``` 31 | 32 | 33 | -------------------------------------------------------------------------------- /QQRed.xcodeproj/xcuserdata/jion.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | QQRed.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | B6356D371DFE952E000365B8 16 | 17 | primary 18 | 19 | 20 | B6356D501DFE952E000365B8 21 | 22 | primary 23 | 24 | 25 | B6356D5B1DFE952E000365B8 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /QQRedTests/QQRedTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // QQRedTests.m 3 | // QQRedTests 4 | // 5 | // Created by Jion on 2016/12/12. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QQRedTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation QQRedTests 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 | -------------------------------------------------------------------------------- /QQRed/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | QQ 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 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 | -------------------------------------------------------------------------------- /QQRedUITests/QQRedUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // QQRedUITests.m 3 | // QQRedUITests 4 | // 5 | // Created by Jion on 2016/12/12. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QQRedUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation QQRedUITests 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 | -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "AppIcon-140x40~ipad.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "idiom" : "iphone", 11 | "size" : "20x20", 12 | "scale" : "3x" 13 | }, 14 | { 15 | "size" : "29x29", 16 | "idiom" : "iphone", 17 | "filename" : "AppIcon-129x29@2x.png", 18 | "scale" : "2x" 19 | }, 20 | { 21 | "size" : "29x29", 22 | "idiom" : "iphone", 23 | "filename" : "AppIcon-129x29@3x.png", 24 | "scale" : "3x" 25 | }, 26 | { 27 | "size" : "40x40", 28 | "idiom" : "iphone", 29 | "filename" : "AppIcon-140x40@2x.png", 30 | "scale" : "2x" 31 | }, 32 | { 33 | "size" : "40x40", 34 | "idiom" : "iphone", 35 | "filename" : "AppIcon-140x40@3x.png", 36 | "scale" : "3x" 37 | }, 38 | { 39 | "size" : "60x60", 40 | "idiom" : "iphone", 41 | "filename" : "AppIcon-160x60@2x.png", 42 | "scale" : "2x" 43 | }, 44 | { 45 | "size" : "60x60", 46 | "idiom" : "iphone", 47 | "filename" : "AppIcon-160x60@3x.png", 48 | "scale" : "3x" 49 | }, 50 | { 51 | "size" : "1024x1024", 52 | "idiom" : "ios-marketing", 53 | "filename" : "AppIcon-1024.png", 54 | "scale" : "1x" 55 | } 56 | ], 57 | "info" : { 58 | "version" : 1, 59 | "author" : "xcode" 60 | } 61 | } -------------------------------------------------------------------------------- /QQRed/Assets.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "orientation" : "portrait", 11 | "idiom" : "iphone", 12 | "filename" : "LaunchImage640x960@2x.png", 13 | "extent" : "full-screen", 14 | "scale" : "2x" 15 | }, 16 | { 17 | "orientation" : "portrait", 18 | "idiom" : "iphone", 19 | "filename" : "LaunchImage640x1136@2x.png", 20 | "extent" : "full-screen", 21 | "subtype" : "retina4", 22 | "scale" : "2x" 23 | }, 24 | { 25 | "extent" : "full-screen", 26 | "idiom" : "iphone", 27 | "subtype" : "736h", 28 | "filename" : "LaunchImage1242x2208@3x.png", 29 | "minimum-system-version" : "8.0", 30 | "orientation" : "portrait", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "extent" : "full-screen", 35 | "idiom" : "iphone", 36 | "subtype" : "736h", 37 | "filename" : "LaunchImage-2208x1242@3x.png", 38 | "minimum-system-version" : "8.0", 39 | "orientation" : "landscape", 40 | "scale" : "3x" 41 | }, 42 | { 43 | "extent" : "full-screen", 44 | "idiom" : "iphone", 45 | "subtype" : "667h", 46 | "filename" : "LaunchImage750x1334@2x.png", 47 | "minimum-system-version" : "8.0", 48 | "orientation" : "portrait", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "orientation" : "portrait", 53 | "idiom" : "iphone", 54 | "filename" : "LaunchImage640x960@2x-1.png", 55 | "extent" : "full-screen", 56 | "minimum-system-version" : "7.0", 57 | "scale" : "2x" 58 | }, 59 | { 60 | "extent" : "full-screen", 61 | "idiom" : "iphone", 62 | "subtype" : "retina4", 63 | "filename" : "LaunchImage640x1136@2x-1.png", 64 | "minimum-system-version" : "7.0", 65 | "orientation" : "portrait", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /QQRed/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/12. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /QQRed/TableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewCell.m 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/15. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import "TableViewCell.h" 10 | #import "UIView+DragBlast.h" 11 | 12 | @implementation TableViewCell 13 | 14 | - (void)awakeFromNib { 15 | [super awakeFromNib]; 16 | // Initialization code 17 | self.selectionStyle = UITableViewCellSelectionStyleNone; 18 | self.messageBtn.layer.cornerRadius = self.messageBtn.bounds.size.height/2; 19 | self.messageBtn.layer.masksToBounds = YES; 20 | self.messageBtn.tapBlast = YES; 21 | self.messageBtn.dragBlast = YES; 22 | 23 | [self.messageBtn addTarget:self action:@selector(transformScal:) forControlEvents:UIControlEventTouchDown]; 24 | 25 | self.messageLable.layer.cornerRadius = self.messageLable.bounds.size.height/2; 26 | self.messageLable.layer.masksToBounds = YES; 27 | self.messageLable.tapBlast = YES; 28 | self.messageLable.dragBlast = YES; 29 | } 30 | 31 | -(void)layoutSubviews{ 32 | [super layoutSubviews]; 33 | 34 | } 35 | 36 | -(void)transformScal:(UIButton*)sender{ 37 | sender.transform = CGAffineTransformMakeScale(1.2, 1.2); 38 | //做阻尼震动 39 | [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{ 40 | sender.transform = CGAffineTransformMakeScale(1.0, 1.0); 41 | } completion:^(BOOL finished) { 42 | 43 | }]; 44 | 45 | } 46 | 47 | -(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated{ 48 | [super setHighlighted:highlighted animated:animated]; 49 | if (highlighted) { 50 | self.contentView.backgroundColor = [UIColor colorWithRed:204/255.0 green:204/255.0 blue:204/255.0 alpha:1.0]; 51 | } else { 52 | // 增加延迟消失动画效果,提升用户体验 53 | [UIView animateWithDuration:0.1 delay:0.1 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 54 | self.contentView.backgroundColor = [UIColor clearColor]; 55 | } completion:nil]; 56 | } 57 | 58 | } 59 | 60 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 61 | [super setSelected:selected animated:animated]; 62 | 63 | // Configure the view for the selected state 64 | } 65 | 66 | - (void)drawRect:(CGRect)rect 67 | { 68 | CGContextRef context = UIGraphicsGetCurrentContext(); 69 | 70 | CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); 71 | CGContextFillRect(context, rect); 72 | 73 | CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0xE2/255.0f green:0xE2/255.0f blue:0xE2/255.0f alpha:1].CGColor); 74 | CGContextStrokeRect(context, CGRectMake(62, rect.size.height - 0.5, rect.size.width, 0.5)); 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /QQRed/DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.m 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/21. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import "DetailViewController.h" 10 | #import "UIView+DragBlast.h" 11 | 12 | @interface DetailViewController () 13 | 14 | @end 15 | 16 | @implementation DetailViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view. 21 | self.view.backgroundColor = [UIColor whiteColor]; 22 | self.title = @"猪猪行天下"; 23 | 24 | [self buildView]; 25 | } 26 | 27 | -(void)buildView { 28 | NSString *title = @"20"; 29 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 30 | btn.center = self.view.center; 31 | btn.titleLabel.font = [UIFont systemFontOfSize:14]; 32 | [btn setBackgroundColor:[UIColor redColor]]; 33 | [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 34 | [btn setTitle:title forState:UIControlStateNormal]; 35 | 36 | CGFloat aWidth = [title boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading|NSStringDrawingTruncatesLastVisibleLine attributes:@{NSFontAttributeName:btn.titleLabel.font} context:nil].size.width; 37 | btn.bounds = CGRectMake(0, 0, title.length>1?aWidth+10:20, 20); 38 | [btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside]; 39 | btn.layer.cornerRadius = 10; 40 | btn.layer.masksToBounds = YES; 41 | btn.tapBlast = YES; 42 | [btn blastCompletion:^(BOOL finished) { 43 | NSLog(@"拖拽事件"); 44 | }]; 45 | [self.view addSubview:btn]; 46 | 47 | 48 | UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom]; 49 | btn1.center = CGPointMake(btn.center.x, btn.center.y+100); 50 | btn1.titleLabel.font = [UIFont systemFontOfSize:14]; 51 | [btn1 setBackgroundColor:[UIColor redColor]]; 52 | 53 | btn1.bounds = CGRectMake(0, 0, 20, 25); 54 | [btn1 addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside]; 55 | btn1.layer.cornerRadius = 10; 56 | btn1.layer.masksToBounds = YES; 57 | btn1.tapBlast = YES; 58 | [btn1 blastCompletion:^(BOOL finished) { 59 | NSLog(@"拖拽事件"); 60 | }]; 61 | [self.view addSubview:btn1]; 62 | } 63 | 64 | -(void)btnAction:(id)sender{ 65 | NSLog(@"点击事件"); 66 | } 67 | 68 | - (void)didReceiveMemoryWarning { 69 | [super didReceiveMemoryWarning]; 70 | // Dispose of any resources that can be recreated. 71 | } 72 | 73 | /* 74 | #pragma mark - Navigation 75 | 76 | // In a storyboard-based application, you will often want to do a little preparation before navigation 77 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 78 | // Get the new view controller using [segue destinationViewController]. 79 | // Pass the selected object to the new view controller. 80 | } 81 | */ 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /QQRed/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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /QQRed/Search/JATagView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JATagView.m 3 | // StudyDemo 4 | // 5 | // Created by z on 2016/12/14. 6 | // Copyright © 2016年 ja. All rights reserved. 7 | // 8 | 9 | #import "JATagView.h" 10 | @interface JATagView() 11 | { 12 | 13 | } 14 | @property (nonatomic,strong)UILabel *label; 15 | @property (nonatomic,strong)UIButton *deleteBtn; 16 | @property (nonatomic,assign)JATagViewType currentType; 17 | @end 18 | @implementation JATagView 19 | 20 | 21 | 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame 24 | { 25 | self = [super initWithFrame:frame]; 26 | if (self) { 27 | [self createBaseView:JATagViewDefault]; 28 | } 29 | return self; 30 | } 31 | - (instancetype)initWithFrame:(CGRect)frame withTagType:(JATagViewType)type 32 | { 33 | self = [super initWithFrame:frame]; 34 | if (self) { 35 | [self createBaseView:type]; 36 | } 37 | return self; 38 | } 39 | - (void)createBaseView:(JATagViewType)type 40 | { 41 | self.currentType = type; 42 | [self addSubview:self.label]; 43 | if (type == JATagViewDefault) { 44 | 45 | }else if (type == JATagViewDelete){ 46 | [self addSubview:self.deleteBtn]; 47 | } 48 | 49 | 50 | 51 | [self reinstallFrme]; 52 | 53 | } 54 | - (void)setTagString:(NSString *)tagString 55 | { 56 | _tagString = tagString; 57 | self.label.text = tagString; 58 | [self reinstallFrme]; 59 | 60 | } 61 | - (void)reinstallFrme 62 | { 63 | 64 | /*设置圆角*/ 65 | CGRect rect = self.frame; 66 | CGFloat cornerRadius = rect.size.height / 2.0; 67 | self.layer.cornerRadius = cornerRadius; 68 | self.layer.borderColor = [UIColor clearColor].CGColor; 69 | self.layer.masksToBounds = YES; 70 | 71 | 72 | CGFloat lableW = rect.size.width - 2*cornerRadius; 73 | CGFloat deleteW = 15; 74 | self.deleteBtn.frame = CGRectMake(rect.size.width - deleteW - cornerRadius, (rect.size.height - deleteW)/2, deleteW, deleteW); 75 | 76 | if (self.currentType == JATagViewDelete) { 77 | lableW -= deleteW; 78 | } 79 | self.label.frame = CGRectMake(cornerRadius, 0, lableW, rect.size.height); 80 | } 81 | #pragma mark - 创建视图 82 | - (UILabel *)label 83 | { 84 | if (!_label) { 85 | CGRect rect = self.frame; 86 | _label = [[UILabel alloc] initWithFrame:CGRectMake(rect.size.height/2, 0, rect.size.width - (rect.size.height/2)*2, rect.size.height)]; 87 | _label.numberOfLines = 1; 88 | _label.textAlignment = 1; 89 | _label.textColor = [UIColor blackColor]; 90 | _label.font = [UIFont systemFontOfSize:14.f]; 91 | 92 | } 93 | return _label; 94 | } 95 | - (UIButton *)deleteBtn 96 | { 97 | if (!_deleteBtn) { 98 | 99 | _deleteBtn = [UIButton buttonWithType:UIButtonTypeCustom]; 100 | _deleteBtn.backgroundColor = [UIColor redColor]; 101 | [_deleteBtn addTarget:self action:@selector(deleteBtnAction) forControlEvents:UIControlEventTouchUpInside]; 102 | } 103 | return _deleteBtn; 104 | } 105 | //删除 106 | - (void)deleteBtnAction 107 | { 108 | self.deleteTag(); 109 | [self removeFromSuperview]; 110 | 111 | } 112 | - (void)deleteTagBlock:(deleteTagBlock)deleteTag 113 | { 114 | _deleteTag = deleteTag; 115 | } 116 | //- (CGFloat)getLabelHeight:(NSString *)content labelWidth:(CGFloat)contentW font:(UIFont *)fnt 117 | //{ 118 | // // 宽度W 119 | // // label的字体 HelveticaNeue Courier 120 | // 121 | // // iOS7中用以下方法替代过时的iOS6中的sizeWithFont:constrainedToSize:lineBreakMode:方法 122 | // if (!content) { 123 | // content = @""; 124 | // } 125 | // CGRect tmpRect = [content boundingRectWithSize:CGSizeMake(contentW, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:fnt,NSFontAttributeName, nil] context:nil]; 126 | // 127 | // // 高度H 128 | // CGFloat contentH = tmpRect.size.height; 129 | // return contentH; 130 | //} 131 | @end 132 | -------------------------------------------------------------------------------- /QQRed/TableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.m 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/15. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import "TableViewController.h" 10 | #import "DetailViewController.h" 11 | static NSString * const reuseIdentifier = @"TableViewCell"; 12 | @interface TableViewController () 13 | 14 | @end 15 | 16 | @implementation TableViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | self.title = @"消息列表"; 21 | self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 22 | [self.tableView registerNib:[UINib nibWithNibName:reuseIdentifier bundle:nil] forCellReuseIdentifier:reuseIdentifier]; 23 | } 24 | 25 | - (void)didReceiveMemoryWarning { 26 | [super didReceiveMemoryWarning]; 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | #pragma mark - Table view data source 31 | 32 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 33 | 34 | return 1; 35 | } 36 | 37 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 38 | 39 | return 20; 40 | } 41 | -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 42 | return 60; 43 | } 44 | 45 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 46 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; 47 | 48 | // Configure the cell... 49 | 50 | return cell; 51 | } 52 | 53 | 54 | /* 55 | // Override to support conditional editing of the table view. 56 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 57 | // Return NO if you do not want the specified item to be editable. 58 | return YES; 59 | } 60 | */ 61 | 62 | /* 63 | // Override to support editing the table view. 64 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 65 | if (editingStyle == UITableViewCellEditingStyleDelete) { 66 | // Delete the row from the data source 67 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 68 | } else if (editingStyle == UITableViewCellEditingStyleInsert) { 69 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view 70 | } 71 | } 72 | */ 73 | 74 | /* 75 | // Override to support rearranging the table view. 76 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { 77 | } 78 | */ 79 | 80 | /* 81 | // Override to support conditional rearranging of the table view. 82 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 83 | // Return NO if you do not want the item to be re-orderable. 84 | return YES; 85 | } 86 | */ 87 | 88 | 89 | #pragma mark - Table view delegate 90 | 91 | // In a xib-based application, navigation from a table can be handled in -tableView:didSelectRowAtIndexPath: 92 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 93 | // Navigation logic may go here, for example: 94 | // Create the next view controller. 95 | DetailViewController *detailViewController = [[DetailViewController alloc] init]; 96 | 97 | [self.navigationController pushViewController:detailViewController animated:YES]; 98 | } 99 | 100 | 101 | /* 102 | #pragma mark - Navigation 103 | 104 | // In a storyboard-based application, you will often want to do a little preparation before navigation 105 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 106 | // Get the new view controller using [segue destinationViewController]. 107 | // Pass the selected object to the new view controller. 108 | } 109 | */ 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /QQRed.xcodeproj/xcuserdata/jion.xcuserdatad/xcschemes/QQRed.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 | -------------------------------------------------------------------------------- /QQRed/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 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /QQRed/TableViewCell.xib: -------------------------------------------------------------------------------- 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 | 32 | 40 | 47 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /QQRed/Search/SearchResurltView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SearchResurltView.m 3 | // AutomobileAccessories 4 | // 5 | // Created by JA on 2016/12/15. 6 | // Copyright © 2016年 sensu_nikun. All rights reserved. 7 | // 8 | 9 | #import "SearchResurltView.h" 10 | #import "JATagView.h" 11 | #define tagViewHeight 50.f 12 | 13 | @interface SearchResurltView () 14 | { 15 | } 16 | @property (nonatomic,strong)UITableView *tableView; 17 | @property (nonatomic,strong)UIView *bottomView; 18 | @property (nonatomic,strong)UIButton *sureBtn;//确定按钮 19 | @property (nonatomic,strong)UIScrollView *tagScrollView;//选择的标签所在的scroll 20 | @property (nonatomic,strong)NSMutableArray *dataArry;//数据源 21 | //@property (nonatomic,strong)NSMutableDictionary *selectTagDic;//选择的标签 22 | @property (nonatomic,assign)CGSize curentContentSize; 23 | @end 24 | @implementation SearchResurltView 25 | 26 | - (instancetype)initWithFrame:(CGRect)frame 27 | { 28 | self = [super initWithFrame:frame]; 29 | if (self) { 30 | [self createArryAndDic]; 31 | [self createBaseView]; 32 | } 33 | return self; 34 | } 35 | //创建view 36 | - (void)createBaseView 37 | { 38 | self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; 39 | 40 | [self addSubview:self.tableView]; 41 | [self addSubview:self.bottomView]; 42 | [self.bottomView addSubview:self.sureBtn]; 43 | [self.bottomView addSubview:self.tagScrollView]; 44 | 45 | } 46 | 47 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 48 | { 49 | /* 50 | [self removeFromSuperview]; 51 | self.dimiss(); 52 | */ 53 | } 54 | #pragma mark - 55 | #pragma mark - tableViewDelegate 56 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 57 | { 58 | return self.dataArry.count; 59 | } 60 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 61 | { 62 | return 1; 63 | } 64 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 65 | { 66 | return 44.f; 67 | } 68 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 69 | { 70 | static NSString * iden = @"cell"; 71 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:iden]; 72 | if (!cell) { 73 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:iden]; 74 | } 75 | cell.textLabel.text =self.dataArry[indexPath.row]; 76 | return cell; 77 | } 78 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 79 | { 80 | NSString *selectTagStr = self.dataArry[indexPath.row]; 81 | [self showTagOnScrollView:selectTagStr]; 82 | } 83 | #pragma mark -标签的显示与删除 84 | //显示标签在scroll上 85 | - (void)showTagOnScrollView:(NSString *)tagStr 86 | { 87 | //底部确定按钮向下移动,显示出选择的标签 88 | __block CGRect botomRect = self.bottomView.frame; 89 | __block CGRect sureBtnRect = self.sureBtn.frame; 90 | if (botomRect.size.height == 50) { 91 | [UIView animateWithDuration:0.3 animations:^{ 92 | botomRect.size.height = botomRect.size.height + tagViewHeight; 93 | sureBtnRect.origin.y = sureBtnRect.origin.y + tagViewHeight; 94 | self.bottomView.frame = botomRect; 95 | self.sureBtn.frame = sureBtnRect; 96 | } completion:^(BOOL finished) { 97 | self.tagScrollView.hidden = NO; 98 | 99 | 100 | }]; 101 | } 102 | 103 | //显示/删除 标签 104 | [self showAndDeleteTagWithTagstr:tagStr]; 105 | 106 | } 107 | - (void)showAndDeleteTagWithTagstr:(NSString *)tagStr 108 | { 109 | //创建要显示的标签 110 | CGRect scrollRect = self.tagScrollView.frame; 111 | CGFloat space = 8; 112 | CGFloat tagViewH = 30; 113 | CGFloat tagViewW = 130; 114 | //找出scroll上面最后一个tagview 115 | JATagView *afterView = nil; 116 | for (UIView *view in self.tagScrollView.subviews) { 117 | if ([view isKindOfClass:[JATagView class]]) { 118 | afterView = (JATagView *)view; 119 | } 120 | } 121 | CGFloat leftSpace = 12; 122 | CGFloat x = leftSpace; 123 | if (afterView) { 124 | x = CGRectGetMaxX(afterView.frame) + space; 125 | } 126 | JATagView *tagView = [[JATagView alloc] initWithFrame:CGRectMake(x, (scrollRect.size.height - tagViewH)/2.f, tagViewW, tagViewH) withTagType:JATagViewDelete]; 127 | tagView.backgroundColor = [UIColor whiteColor]; 128 | tagView.tagString = tagStr; 129 | 130 | 131 | //设置tagScrollView 的相关属性 132 | [self.tagScrollView addSubview:tagView]; 133 | CGSize contentSize = self.tagScrollView.contentSize; 134 | CGFloat maxX = CGRectGetMaxX(tagView.frame) + leftSpace;//多加12(距离右边的距离) 135 | if (maxX > contentSize.width) { 136 | contentSize.width = maxX; 137 | self.tagScrollView.contentSize = contentSize; 138 | [self.tagScrollView setContentOffset:CGPointMake(contentSize.width-self.tagScrollView.frame.size.width, 0) animated:YES]; 139 | } 140 | //删除标签 141 | 142 | [tagView deleteTagBlock:^{ 143 | NSMutableArray *moveLefts = [[NSMutableArray alloc] init]; 144 | JATagView *lastTagView = nil; 145 | for (int i = 0; i < self.tagScrollView.subviews.count; i ++) { 146 | UIView *view = self.tagScrollView.subviews[i]; 147 | if (![view isKindOfClass:[JATagView class]]) { 148 | continue; 149 | } 150 | if ([view isEqual:tagView]) {//找到当前要删除的tagView,并把后面的viewX坐标向前移动 151 | tagView.hidden = YES;//此时tagView还没有被移除,所以先隐藏掉 152 | 153 | } 154 | if (tagView.isHidden) { 155 | [moveLefts addObject:view]; 156 | } 157 | lastTagView = (JATagView *)view; 158 | } 159 | 160 | 161 | 162 | //把所有需要移动的view,整体向左边移动 163 | [UIView animateWithDuration:.3 animations:^{ 164 | for (JATagView *view in moveLefts) { 165 | CGRect rect = view.frame; 166 | rect.origin.x -= (tagView.frame.size.width + space); 167 | view.frame = rect; 168 | } 169 | if (lastTagView) { 170 | CGSize contentSize = self.tagScrollView.contentSize; 171 | CGFloat maxX = CGRectGetMaxX(lastTagView.frame) + leftSpace;//多加12(距离右边的距离) 172 | if (maxX>375) { 173 | contentSize.width = maxX; 174 | }else{ 175 | contentSize.width = 375; 176 | } 177 | 178 | self.curentContentSize = contentSize; 179 | self.tagScrollView.contentSize = self.curentContentSize; 180 | } 181 | 182 | } completion:^(BOOL finished) { 183 | 184 | }]; 185 | 186 | 187 | }]; 188 | 189 | } 190 | //延迟设置contentSize 使动画更加自然 191 | - (void)afterSetContentSize{ 192 | 193 | self.tagScrollView.contentSize = _curentContentSize; 194 | 195 | 196 | 197 | } 198 | #pragma mark - 199 | #pragma mark - scrollViewDelegate 200 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 201 | { 202 | NSLog(@"scrollViewOff =%f",scrollView.contentOffset.x); 203 | } 204 | 205 | #pragma mark - 206 | #pragma mark - 按钮action 207 | - (void)sureBtnAction 208 | { 209 | 210 | 211 | 212 | } 213 | #pragma mark - 214 | #pragma mark - 懒加载 215 | - (UITableView *)tableView 216 | { 217 | if (!_tableView) { 218 | CGRect rect = self.frame; 219 | _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, rect.size.width, 200) style:UITableViewStylePlain]; 220 | _tableView.backgroundColor = [UIColor whiteColor]; 221 | _tableView.delegate = self; 222 | _tableView.dataSource = self; 223 | [self addSubview:_tableView]; 224 | } 225 | return _tableView; 226 | } 227 | - (UIView *)bottomView 228 | { 229 | if (!_bottomView) { 230 | CGRect rect = self.frame; 231 | _bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.tableView.frame), rect.size.width, 50)]; 232 | _bottomView.backgroundColor = [UIColor blueColor]; 233 | } 234 | return _bottomView; 235 | } 236 | - (UIButton *)sureBtn 237 | { 238 | if (!_sureBtn) { 239 | CGFloat height = 42; 240 | CGRect bottomRect = self.bottomView.frame; 241 | _sureBtn = [UIButton buttonWithType:UIButtonTypeCustom]; 242 | _sureBtn.frame = CGRectMake(20, (bottomRect.size.height - height)/2.f, bottomRect.size.width - 20*2, height); 243 | [_sureBtn setTitle:@"确定" forState:0]; 244 | [_sureBtn setTitleColor:[UIColor redColor] forState:0]; 245 | _sureBtn.backgroundColor = [UIColor groupTableViewBackgroundColor]; 246 | _sureBtn.titleLabel.font = [UIFont systemFontOfSize:13.f]; 247 | _sureBtn.layer.cornerRadius = 2.5f; 248 | _sureBtn.layer.borderColor = [UIColor clearColor].CGColor; 249 | _sureBtn.layer.masksToBounds = YES; 250 | [_sureBtn addTarget:self action:@selector(sureBtnAction) forControlEvents:UIControlEventTouchUpInside]; 251 | } 252 | return _sureBtn; 253 | } 254 | - (UIScrollView *)tagScrollView 255 | { 256 | if (!_tagScrollView) { 257 | _tagScrollView = [[UIScrollView alloc] init]; 258 | _tagScrollView.showsVerticalScrollIndicator = NO; 259 | _tagScrollView.showsHorizontalScrollIndicator = NO; 260 | _tagScrollView.frame = CGRectMake(0, 0, self.bottomView.frame.size.width, tagViewHeight); 261 | _tagScrollView.backgroundColor = [UIColor clearColor]; 262 | _tagScrollView.hidden = YES; 263 | _tagScrollView.contentSize = CGSizeMake(_tagScrollView.frame.size.width, tagViewHeight); 264 | _tagScrollView.delegate = self; 265 | } 266 | return _tagScrollView; 267 | } 268 | 269 | - (void)createArryAndDic 270 | { 271 | 272 | self.dataArry = [[NSMutableArray alloc] init]; 273 | //做些假数据 274 | for (int i = 0; i < 10; i ++) { 275 | [_dataArry addObject:[NSString stringWithFormat:@"标签🏷%d",i]]; 276 | } 277 | /*创建选择的标签字典*/ 278 | // self.selectTagDic = [[NSMutableDictionary alloc] init]; 279 | 280 | } 281 | - (void)dimiss:(dimissSelf)dimiss 282 | { 283 | _dimiss = dimiss; 284 | } 285 | @end 286 | -------------------------------------------------------------------------------- /QQRed/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/12. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "UIView+DragBlast.h" 11 | #import "TableViewController.h" 12 | 13 | //设置最大偏移距离为当前空间的倍数 14 | #define MAXDistance 4 15 | 16 | @interface ViewController () 17 | { 18 | UIView *circle2; 19 | } 20 | @property (weak, nonatomic) IBOutlet UIButton *testbtn; 21 | @property(nonatomic,assign)CGPoint remindPoint; 22 | @property(nonatomic,strong)UIView *circle1; 23 | @property(nonatomic,strong)CAShapeLayer *shapeLayer; 24 | @end 25 | 26 | @implementation ViewController 27 | 28 | 29 | - (void)viewDidLoad { 30 | [super viewDidLoad]; 31 | //self.edgesForExtendedLayout = UIRectEdgeNone; 32 | // Do any additional setup after loading the view, typically from a nib. 33 | self.title = @"点击或拖拽1爆炸,并跳转到下个界面。"; 34 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; 35 | btn.frame = CGRectMake(0, 100, 300, 50); 36 | btn.titleLabel.numberOfLines = 0; 37 | btn.titleLabel.textAlignment = NSTextAlignmentCenter; 38 | [btn setTitle:@"点击这里重新开始" forState:UIControlStateNormal]; 39 | [btn addTarget:self action:@selector(resetSetting:) forControlEvents:UIControlEventTouchUpInside]; 40 | [self.view addSubview:btn]; 41 | 42 | __block UILabel *redView = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 20, 20)]; 43 | redView.backgroundColor = [UIColor redColor]; 44 | redView.layer.cornerRadius = redView.bounds.size.height/2; 45 | redView.layer.masksToBounds = YES; 46 | redView.textAlignment = NSTextAlignmentCenter; 47 | redView.font = [UIFont systemFontOfSize:12]; 48 | redView.textColor = [UIColor whiteColor]; 49 | redView.text = @"1"; 50 | redView.tag = 110; 51 | redView.tapBlast = YES; 52 | redView.isFragment = YES; 53 | [redView blastCompletion:^(BOOL finished) { 54 | TableViewController *table = [[TableViewController alloc] init]; 55 | 56 | [self.navigationController pushViewController:table animated:YES]; 57 | 58 | }]; 59 | [self.view addSubview:redView]; 60 | 61 | self.testbtn.layer.cornerRadius = 20; 62 | self.testbtn.dragBlast = YES; 63 | 64 | [self testDrag]; 65 | } 66 | 67 | -(void)testDrag{ 68 | 69 | circle2 = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 20, 20)]; 70 | circle2.backgroundColor = [UIColor redColor]; 71 | circle2.layer.cornerRadius = 10; 72 | [self.view addSubview:circle2]; 73 | 74 | self.circle1 = [[UIView alloc] init]; 75 | self.circle1.backgroundColor = circle2.backgroundColor; 76 | self.circle1.center = circle2.center; 77 | self.circle1.bounds = circle2.bounds; 78 | self.circle1.layer.cornerRadius = circle2.layer.cornerRadius; 79 | self.circle1.layer.masksToBounds = circle2.layer.masksToBounds; 80 | self.circle1.hidden = YES; 81 | [self.view insertSubview:self.circle1 belowSubview:circle2]; 82 | 83 | UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragPanAction:)]; 84 | [circle2 addGestureRecognizer:panGR]; 85 | 86 | UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(blastAction:)]; 87 | [circle2 addGestureRecognizer:tapGR]; 88 | 89 | _remindPoint = CGPointMake(0, 0); 90 | } 91 | 92 | -(void)resetSetting:(UIButton*)sender{ 93 | UIView *redView = [self.view viewWithTag:110]; 94 | redView.hidden = NO; 95 | 96 | self.testbtn.hidden = NO; 97 | } 98 | 99 | -(void)blastAction:(UITapGestureRecognizer*)tap{ 100 | tap.view.hidden = YES; 101 | self.circle1.hidden = YES; 102 | //爆炸效果 103 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:tap.view.frame]; 104 | imageView.contentMode = UIViewContentModeCenter; 105 | NSMutableArray *imageArr = [NSMutableArray array]; 106 | for (int i = 1 ; i < 5; i++) { 107 | UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"unreadBomb_%d",i]]; 108 | [imageArr addObject:image]; 109 | } 110 | imageView.animationImages = imageArr; 111 | imageView.animationDuration = 0.5; 112 | imageView.animationRepeatCount = 1; 113 | [imageView startAnimating]; 114 | [self.view addSubview:imageView]; 115 | 116 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 117 | [imageView removeFromSuperview]; 118 | }); 119 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 120 | tap.view.hidden = NO; 121 | }); 122 | } 123 | 124 | -(void)dragPanAction:(UIPanGestureRecognizer*)pan{ 125 | 126 | if (_remindPoint.x == 0 && _remindPoint.y == 0) { 127 | _remindPoint = pan.view.center; 128 | } 129 | 130 | self.circle1.hidden = NO; 131 | 132 | //拖动 133 | CGPoint translation = [pan translationInView:self.view]; 134 | CGPoint newCenter = CGPointMake(pan.view.center.x+ translation.x, 135 | pan.view.center.y + translation.y); 136 | newCenter.y = MAX(pan.view.frame.size.height/2, newCenter.y); 137 | newCenter.y = MIN(self.view.frame.size.height - pan.view.frame.size.height/2, newCenter.y); 138 | newCenter.x = MAX(pan.view.frame.size.width/2, newCenter.x); 139 | newCenter.x = MIN(self.view.frame.size.width - pan.view.frame.size.width/2,newCenter.x); 140 | pan.view.center = newCenter; 141 | [pan setTranslation:CGPointZero inView:self.view]; 142 | 143 | /* 144 | //拖动和上面的代码一样 145 | CGPoint newCenter = [pan locationInView:self.view]; 146 | newCenter = [pan.view convertPoint:p toView:self.view]; 147 | pan.view.center= newCenter; 148 | */ 149 | 150 | // 设置circle1变化的值 151 | CGFloat cirDistance = [self distanceWithPointA:self.circle1.center andPointB:circle2.center]; 152 | CGFloat scale = 1- cirDistance/(MAXDistance*circle2.bounds.size.height); 153 | if (scale < 0.2) { 154 | scale = 0.2; 155 | } 156 | self.circle1.transform = CGAffineTransformMakeScale(scale, scale); 157 | 158 | CGFloat fx = fabs(_remindPoint.x- newCenter.x); 159 | CGFloat fy = fabs(_remindPoint.y- newCenter.y); 160 | if (fx>MAXDistance*circle2.bounds.size.height || fy>MAXDistance*circle2.bounds.size.height) { 161 | self.shapeLayer.path = nil; 162 | self.circle1.hidden = YES; 163 | }else{ 164 | self.circle1.hidden = NO; 165 | [self reloadBeziePath]; 166 | } 167 | 168 | if (pan.state == UIGestureRecognizerStateRecognized) { 169 | CGFloat fx = fabs(_remindPoint.x- newCenter.x); 170 | CGFloat fy = fabs(_remindPoint.y- newCenter.y); 171 | if (fx>MAXDistance*circle2.bounds.size.height || fy>MAXDistance*circle2.bounds.size.height) { 172 | [self boomCells:pan.view.center]; 173 | /* 174 | NSInteger k = arc4random()%2; 175 | if (k==1) { 176 | //位图移动 177 | [self boomCells:pan.view.center]; 178 | }else{ 179 | //粒子束运动 180 | [self boom:pan.view]; 181 | } 182 | */ 183 | }else{ 184 | [self.shapeLayer removeFromSuperlayer]; 185 | self.shapeLayer = nil; 186 | [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{ 187 | self->circle2.center = self.circle1.center; 188 | } completion:^(BOOL finished) { 189 | self.circle1.hidden = NO; 190 | }]; 191 | 192 | } 193 | 194 | } 195 | 196 | } 197 | #pragma mark - 获取圆心距离 198 | - (CGFloat)distanceWithPointA:(CGPoint)pointA andPointB:(CGPoint)pointB{ 199 | CGFloat offSetX = pointA.x - pointB.x; 200 | CGFloat offSetY = pointA.y - pointB.y; 201 | return sqrt(offSetX*offSetX + offSetY*offSetY); 202 | } 203 | 204 | #pragma mark - 绘制贝塞尔图形 205 | - (void) reloadBeziePath { 206 | CGFloat r1 = self.circle1.frame.size.width / 2.0f; 207 | CGFloat r2 = circle2.frame.size.width / 2.0f; 208 | 209 | CGFloat x1 = self.circle1.center.x; 210 | CGFloat y1 = self.circle1.center.y; 211 | CGFloat x2 = circle2.center.x; 212 | CGFloat y2 = circle2.center.y; 213 | 214 | CGFloat distance = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); 215 | 216 | CGFloat sinDegree = (x2 - x1) / distance; 217 | CGFloat cosDegree = (y2 - y1) / distance; 218 | 219 | CGPoint pointA = CGPointMake(x1 - r1 * cosDegree, y1 + r1 * sinDegree); 220 | CGPoint pointB = CGPointMake(x1 + r1 * cosDegree, y1 - r1 * sinDegree); 221 | CGPoint pointC = CGPointMake(x2 + r2 * cosDegree, y2 - r2 * sinDegree); 222 | CGPoint pointD = CGPointMake(x2 - r2 * cosDegree, y2 + r2 * sinDegree); 223 | CGPoint pointP = CGPointMake(pointB.x + (distance / 2) * sinDegree, pointB.y + (distance / 2) * cosDegree); 224 | CGPoint pointO = CGPointMake(pointA.x + (distance / 2) * sinDegree, pointA.y + (distance / 2) * cosDegree); 225 | 226 | UIBezierPath *path = [UIBezierPath bezierPath]; 227 | [path moveToPoint: pointA]; 228 | [path addLineToPoint: pointB]; 229 | [path addQuadCurveToPoint: pointC controlPoint: pointP]; 230 | [path addLineToPoint: pointD]; 231 | [path addQuadCurveToPoint: pointA controlPoint: pointO]; 232 | 233 | self.shapeLayer.path = path.CGPath; 234 | } 235 | 236 | - (CAShapeLayer *)shapeLayer{ 237 | if (!_shapeLayer) { 238 | CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 239 | shapeLayer.fillColor = circle2.backgroundColor.CGColor; 240 | [self.view.layer insertSublayer:shapeLayer below:self.circle1.layer]; 241 | _shapeLayer = shapeLayer; 242 | } 243 | return _shapeLayer; 244 | } 245 | 246 | #pragma mark - 粒子添加及动画 247 | -(void)boomCells:(CGPoint)point{ 248 | NSInteger rowClocn = 3; 249 | NSMutableArray *boomCells = [NSMutableArray array]; 250 | for (int i = 0; i < rowClocn*rowClocn; ++ i) { 251 | CGFloat pw = MIN(circle2.frame.size.width, circle2.frame.size.height); 252 | CALayer *shape = [CALayer layer]; 253 | shape.backgroundColor = [UIColor colorWithRed:231/255.0 green:231/255.0 blue:231/255.0 alpha:1.0].CGColor; 254 | shape.cornerRadius = pw / 2; 255 | //shape.frame = CGRectMake((i/rowClocn) * pw, (i%rowClocn) * pw, pw, pw); 256 | shape.frame = CGRectMake(0, 0, pw, pw); 257 | [circle2.layer.superlayer addSublayer: shape]; 258 | [boomCells addObject: shape]; 259 | } 260 | circle2.hidden = YES; 261 | [self cellAnimation:boomCells]; 262 | } 263 | - (void) cellAnimation:(NSArray*)cells { 264 | 265 | for (NSInteger j=0; jcircle2.hidden = NO; 289 | }); 290 | 291 | } 292 | -(void)removeLayer:(CALayer*)layer{ 293 | [layer removeFromSuperlayer]; 294 | } 295 | #pragma mark - 设置碎片路径 296 | - (UIBezierPath *) makeRandomPath: (CALayer *) alayer AngleTransformation:(CGFloat)index{ 297 | UIBezierPath *path = [UIBezierPath bezierPath]; 298 | [path moveToPoint:circle2.center]; 299 | CGFloat dia = circle2.frame.size.width; 300 | if (index>0) { 301 | CGFloat angle = index*45*M_PI*2/360; 302 | CGFloat x = dia*cosf(angle); 303 | CGFloat y = dia*sinf(angle); 304 | [path addLineToPoint:CGPointMake(circle2.center.x + x, circle2.center.y+y)]; 305 | }else{ 306 | [path addLineToPoint:CGPointMake(circle2.center.x, circle2.center.y)]; 307 | } 308 | 309 | return path; 310 | } 311 | 312 | #pragma mark -- 粒子发射 313 | -(void)boom:(UIView*)view{ 314 | //生成粒子发射器 315 | CAEmitterLayer *emitter = [CAEmitterLayer layer]; 316 | emitter.frame = view.bounds; 317 | [view.layer addSublayer:emitter]; 318 | 319 | //配置发射器 320 | emitter.renderMode = kCAEmitterLayerAdditive; 321 | emitter.emitterMode = kCAEmitterLayerSurface; 322 | //发射位置 323 | emitter.emitterPosition = CGPointMake(emitter.frame.size.width / 2.0, emitter.frame.size.height / 2.0); 324 | 325 | 326 | CALayer *shape = [CALayer layer]; 327 | shape.bounds = view.bounds; 328 | shape.backgroundColor = [UIColor colorWithRed:231/255.0 green:231/255.0 blue:231/255.0 alpha:1.0].CGColor; 329 | shape.cornerRadius = view.bounds.size.height / 2; 330 | //生成粒子资源 331 | CGSize size = CGSizeMake(view.bounds.size.width, view.bounds.size.height); 332 | UIGraphicsBeginImageContext(size); 333 | CGContextRef context = UIGraphicsGetCurrentContext(); 334 | [shape renderInContext:context]; 335 | UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); 336 | UIGraphicsEndImageContext(); 337 | 338 | //创建粒子 339 | CAEmitterCell *cell = [[CAEmitterCell alloc] init]; 340 | //设置粒子资源内容是CGImageRef格式 341 | cell.contents = (__bridge id)img.CGImage; 342 | //每秒生产的离子数 343 | cell.birthRate = 150; 344 | //离子的生命周期 345 | cell.lifetime = 0.3; 346 | cell.color = [UIColor colorWithRed:231/255.0 green:231/255.0 blue:231/255.0 alpha:1.0].CGColor; 347 | cell.alphaSpeed = -0.4; 348 | //速度和范围 349 | cell.velocity = 50; 350 | cell.velocityRange = img.size.height*2; 351 | //粒子的辐射范围 352 | cell.emissionRange = M_PI * 2.0; 353 | 354 | //添加粒子 355 | emitter.emitterCells = @[cell]; 356 | [self performSelector:@selector(removeLayer:) withObject:emitter afterDelay:cell.lifetime]; 357 | } 358 | 359 | - (void)didReceiveMemoryWarning { 360 | [super didReceiveMemoryWarning]; 361 | // Dispose of any resources that can be recreated. 362 | } 363 | 364 | 365 | @end 366 | -------------------------------------------------------------------------------- /QQRed/DragBlast/UIView+DragBlast.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+DragBlast.m 3 | // QQRed 4 | // 5 | // Created by Jion on 2016/12/13. 6 | // Copyright © 2016年 Youjuke. All rights reserved. 7 | // 8 | /* 9 | 设置拖动时改变大小的圆为circle1 10 | 被拖动的圆则为当前的视图 11 | */ 12 | //设置最大偏移距离为当前控件的倍数 13 | #define MAXMultiple 3 14 | 15 | #import "UIView+DragBlast.h" 16 | #import 17 | 18 | NSString const *kTapBlastKey = @"kTapBlastKey"; 19 | NSString const *kDragBlastKey = @"kDragBlastKey"; 20 | static const void *kCompletionKey = @"kCompletionKey"; 21 | 22 | /*仿照AFNetworking的写法*/ 23 | 24 | @interface UIView (_DragBlast) 25 | @property (readwrite, nonatomic, strong, setter = setCircle1:) UIView* circle1; 26 | @property(readwrite,nonatomic,strong)CAShapeLayer *shapeLayer; 27 | //保存self的父视图,用于复位 28 | @property(readwrite,nonatomic,strong)UIView *restSuperView; 29 | 30 | @property (readwrite, nonatomic, copy, setter = setCompletion:) void (^completion)(BOOL finished); 31 | //保留初始值 32 | @property (readwrite, nonatomic, assign, setter = setOriginalPoint:) CGPoint originalPoint; 33 | @end 34 | 35 | @implementation UIView (_DragBlast) 36 | 37 | -(void)setRestSuperView:(UIView *)restSuperView{ 38 | objc_setAssociatedObject(self, @selector(restSuperView), restSuperView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 39 | } 40 | 41 | -(UIView*)restSuperView{ 42 | return objc_getAssociatedObject(self, @selector(restSuperView)); 43 | } 44 | 45 | -(void)setCircle1:(UIView*)circle1{ 46 | 47 | objc_setAssociatedObject(self, @selector(circle1), circle1, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 48 | 49 | } 50 | 51 | -(UIView*)circle1{ 52 | 53 | return objc_getAssociatedObject(self, @selector(circle1)); 54 | } 55 | 56 | -(void)setShapeLayer:(CAShapeLayer *)shapeLayer{ 57 | objc_setAssociatedObject(self, @selector(shapeLayer), shapeLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 58 | } 59 | 60 | -(CAShapeLayer*)shapeLayer{ 61 | return objc_getAssociatedObject(self, @selector(shapeLayer)); 62 | } 63 | 64 | -(void)setOriginalPoint:(CGPoint)originalPoint{ 65 | objc_setAssociatedObject(self, @selector(originalPoint), NSStringFromCGPoint(originalPoint), OBJC_ASSOCIATION_COPY_NONATOMIC); 66 | } 67 | 68 | -(CGPoint)originalPoint{ 69 | 70 | return CGPointFromString(objc_getAssociatedObject(self, @selector(originalPoint))); 71 | } 72 | 73 | -(void)setCompletion:(void (^)(BOOL))completion{ 74 | objc_setAssociatedObject(self, kCompletionKey, completion, OBJC_ASSOCIATION_COPY_NONATOMIC); 75 | } 76 | 77 | -(void (^)(BOOL))completion{ 78 | return objc_getAssociatedObject(self, kCompletionKey); 79 | } 80 | 81 | @end 82 | 83 | @implementation UIView (DragBlast) 84 | 85 | #pragma mark - setters 86 | 87 | -(void)setTapBlast:(BOOL)tapBlast{ 88 | objc_setAssociatedObject(self, (__bridge const void *)(kTapBlastKey), [NSNumber numberWithBool:tapBlast], OBJC_ASSOCIATION_COPY_NONATOMIC); 89 | self.userInteractionEnabled = YES; 90 | //self.translatesAutoresizingMaskIntoConstraints = NO; 91 | if (tapBlast) { 92 | UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapBlastAction:)]; 93 | [self addGestureRecognizer:tapGR]; 94 | }else{ 95 | for (UIGestureRecognizer *gesture in self.gestureRecognizers) { 96 | if ([gesture isMemberOfClass:[UITapGestureRecognizer class]]) { 97 | [gesture removeTarget:self action:@selector(tapBlastAction:)]; 98 | } 99 | } 100 | } 101 | 102 | } 103 | -(void)setDragBlast:(BOOL)dragBlast{ 104 | objc_setAssociatedObject(self, (__bridge const void *)(kDragBlastKey), [NSNumber numberWithBool:dragBlast], OBJC_ASSOCIATION_COPY_NONATOMIC); 105 | self.userInteractionEnabled = YES; 106 | 107 | if (!self.circle1) { 108 | self.circle1 = [[UIView alloc] init]; 109 | self.circle1.hidden = YES; 110 | } 111 | 112 | self.originalPoint = CGPointZero; 113 | 114 | if (dragBlast) { 115 | UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragPanAction:)]; 116 | [self addGestureRecognizer:panGR]; 117 | }else{ 118 | for (UIGestureRecognizer *gesture in self.gestureRecognizers) { 119 | if ([gesture isMemberOfClass:[UIPanGestureRecognizer class]]) { 120 | [gesture removeTarget:self action:@selector(dragPanAction:)]; 121 | } 122 | } 123 | } 124 | 125 | } 126 | 127 | -(void)setIsFragment:(BOOL)isFragment{ 128 | objc_setAssociatedObject(self, @selector(isFragment), [NSNumber numberWithBool:isFragment], OBJC_ASSOCIATION_COPY_NONATOMIC); 129 | } 130 | 131 | #pragma mark - getters 132 | -(BOOL)tapBlast{ 133 | return [objc_getAssociatedObject(self, (__bridge const void *)(kTapBlastKey)) boolValue]; 134 | } 135 | 136 | -(BOOL)dragBlast{ 137 | return [objc_getAssociatedObject(self, (__bridge const void *)(kDragBlastKey)) boolValue]; 138 | } 139 | 140 | -(BOOL)isFragment{ 141 | return [objc_getAssociatedObject(self, @selector(isFragment)) boolValue]; 142 | } 143 | 144 | -(CAShapeLayer*)getShapeLayer{ 145 | if (!self.shapeLayer) { 146 | self.shapeLayer = [CAShapeLayer layer]; 147 | self.shapeLayer.fillColor = self.backgroundColor.CGColor; 148 | } 149 | return self.shapeLayer; 150 | } 151 | 152 | #pragma mark - Method 153 | -(void)blastCompletion:(void (^)(BOOL finished))completion{ 154 | self.completion = completion; 155 | self.dragBlast = YES; 156 | } 157 | 158 | -(void)tapBlastAction:(UITapGestureRecognizer*)tap{ 159 | if (self.tapBlast) { 160 | tap.view.hidden = YES; 161 | self.circle1.hidden = YES; 162 | self.originalPoint = tap.view.center; 163 | if (self.isFragment) { 164 | [self boomCellsInGesture:tap]; 165 | }else{ 166 | [self aViewBlastEffect:tap]; 167 | } 168 | 169 | }else{ 170 | self.transform = CGAffineTransformMakeScale(1.1, 1.1); 171 | [UIView animateWithDuration:0.3 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{ 172 | self.transform = CGAffineTransformMakeScale(1.0, 1.0); 173 | } completion:^(BOOL finished) { 174 | self.circle1.hidden = NO; 175 | }]; 176 | 177 | } 178 | 179 | } 180 | 181 | -(void)dragPanAction:(UIPanGestureRecognizer*)pan{ 182 | 183 | UIWindow *window = [[UIApplication sharedApplication] keyWindow]; 184 | 185 | CGPoint translation = [pan translationInView:window]; 186 | CGPoint topFloorPoint = [pan.view.superview convertPoint:pan.view.center toView:window]; 187 | 188 | if (CGPointEqualToPoint(self.originalPoint, CGPointZero)){ 189 | 190 | self.originalPoint = topFloorPoint;//pan.view.center; 191 | } 192 | 193 | CGPoint panPoint = CGPointMake(topFloorPoint.x+ translation.x, 194 | topFloorPoint.y + translation.y); 195 | 196 | pan.view.center= panPoint; 197 | [pan setTranslation:CGPointZero inView:window]; 198 | 199 | switch (pan.state) { 200 | case UIGestureRecognizerStateBegan: 201 | { 202 | CGFloat HW = MIN(pan.view.bounds.size.height, pan.view.bounds.size.width); 203 | self.circle1.bounds = CGRectMake(0, 0, HW, HW); 204 | self.circle1.layer.cornerRadius = pan.view.layer.cornerRadius; 205 | self.circle1.layer.masksToBounds = pan.view.layer.masksToBounds; 206 | self.circle1.backgroundColor = pan.view.backgroundColor; 207 | self.circle1.center = self.originalPoint; 208 | self.circle1.hidden = NO; 209 | self.restSuperView = pan.view.superview; 210 | 211 | [window addSubview:self]; 212 | [window insertSubview:self.circle1 belowSubview:self]; 213 | [window.layer insertSublayer:[self getShapeLayer] below:self.circle1.layer]; 214 | 215 | } 216 | break; 217 | case UIGestureRecognizerStateChanged: 218 | { 219 | // 设置circle1变化的值 220 | CGFloat centerDistance = [self distanceWithPoint1:self.circle1.center andPoint2:pan.view.center]; 221 | CGFloat scale = 1- centerDistance/(MAXMultiple*pan.view.bounds.size.height); 222 | if (centerDistance >MAXMultiple*pan.view.bounds.size.height) { 223 | self.shapeLayer.path = nil; 224 | //[self.shapeLayer removeFromSuperlayer]; 225 | //self.shapeLayer = nil; 226 | self.circle1.hidden = YES; 227 | 228 | }else{ 229 | self.circle1.hidden = NO; 230 | [self reloadBeziePath:1-scale]; 231 | } 232 | 233 | if (scale < 0.4) { 234 | scale = 0.4; 235 | } 236 | self.circle1.transform = CGAffineTransformMakeScale(scale, scale); 237 | 238 | } 239 | break; 240 | case UIGestureRecognizerStateEnded: 241 | { 242 | //求圆心距离 243 | CGFloat distance = sqrtf(pow(self.originalPoint.x- panPoint.x, 2)+pow(self.originalPoint.y- panPoint.y, 2)); 244 | 245 | if (distance>MAXMultiple*pan.view.bounds.size.height) { 246 | pan.view.hidden = YES; 247 | 248 | if (self.isFragment) { 249 | [self boomCellsInGesture:pan]; 250 | }else{ 251 | [self aViewBlastEffect:pan]; 252 | } 253 | 254 | }else{ 255 | self.circle1.hidden = YES; 256 | self.shapeLayer.path = nil; 257 | //设置动画时间,阻尼系数,初始速度,动画方式 258 | [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{ 259 | 260 | pan.view.center = self.circle1.center; 261 | 262 | } completion:^(BOOL finished) { 263 | 264 | [self.circle1 removeFromSuperview]; 265 | [self.shapeLayer removeFromSuperlayer]; 266 | //复位 267 | [self.restSuperView addSubview:self]; 268 | CGPoint belowFloorPoint = [window convertPoint:pan.view.center toView:self.restSuperView]; 269 | //判定该视图有没有添加约束 270 | if (self.translatesAutoresizingMaskIntoConstraints) { 271 | self.center = belowFloorPoint; 272 | }else{ 273 | CGFloat R = self.bounds.size.height/2.0; 274 | //创建左边约束 275 | NSLayoutConstraint *leftLc = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.restSuperView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:belowFloorPoint.x-R]; 276 | [self.restSuperView addConstraint:leftLc]; 277 | //创建顶部约束 278 | NSLayoutConstraint *topLc = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.restSuperView attribute:NSLayoutAttributeTop multiplier:1.0 constant:belowFloorPoint.y-R]; 279 | [self.restSuperView addConstraint:topLc]; 280 | } 281 | 282 | }]; 283 | 284 | } 285 | 286 | } 287 | break; 288 | 289 | default: 290 | break; 291 | } 292 | 293 | } 294 | 295 | -(void)aViewBlastEffect:(UIGestureRecognizer*)gesture{ 296 | 297 | UIWindow *window = [[UIApplication sharedApplication] keyWindow]; 298 | //获取在顶层视图的位置 299 | CGRect topFloorRect = [gesture.view.superview convertRect:gesture.view.frame toView:window]; 300 | 301 | //爆炸效果 302 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:topFloorRect]; 303 | imageView.contentMode = UIViewContentModeCenter; 304 | NSMutableArray *imageArr = [NSMutableArray array]; 305 | for (int i = 1 ; i < 5; i++) { 306 | UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"unreadBomb_%d",i]]; 307 | [imageArr addObject:image]; 308 | } 309 | imageView.animationImages = imageArr; 310 | imageView.animationDuration = 0.5; 311 | imageView.animationRepeatCount = 1; 312 | [imageView startAnimating]; 313 | [window addSubview:imageView]; 314 | 315 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 316 | 317 | [imageView removeFromSuperview]; 318 | [self.circle1 removeFromSuperview]; 319 | [self.shapeLayer removeFromSuperlayer]; 320 | //复位 321 | [self.restSuperView addSubview:gesture.view]; 322 | CGPoint belowFloorPoint = [window convertPoint:self.originalPoint toView:self.restSuperView]; 323 | //判断有没有约束和是那种手势 324 | if (self.translatesAutoresizingMaskIntoConstraints) { 325 | gesture.view.center = belowFloorPoint; 326 | }else if([gesture isMemberOfClass:[UIPanGestureRecognizer class]] && !self.translatesAutoresizingMaskIntoConstraints){ 327 | CGFloat R = self.bounds.size.height/2.0; 328 | //创建左边约束 329 | NSLayoutConstraint *leftLc = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.restSuperView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:belowFloorPoint.x-R]; 330 | [self.restSuperView addConstraint:leftLc]; 331 | //创建顶部约束 332 | NSLayoutConstraint *topLc = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.restSuperView attribute:NSLayoutAttributeTop multiplier:1.0 constant:belowFloorPoint.y-R]; 333 | [self.restSuperView addConstraint:topLc]; 334 | } 335 | 336 | //self.hidden = NO; 337 | 338 | if (self.completion) { 339 | self.completion(self.hidden); 340 | } 341 | }); 342 | 343 | } 344 | 345 | #pragma mark - 获取圆心距离 346 | - (CGFloat)distanceWithPoint1:(CGPoint)point1 andPoint2:(CGPoint)point2{ 347 | CGFloat offSetX = point1.x - point2.x; 348 | CGFloat offSetY = point1.y - point2.y; 349 | //平方根sqrt(9) = 3 N次方pow(x,N)表示x的N次方 350 | return sqrt(pow(offSetX, 2) + pow(offSetY, 2)); 351 | } 352 | #pragma mark - 绘制贝塞尔图形 353 | - (void) reloadBeziePath:(CGFloat)scale { 354 | CGFloat r1 = MAX(self.circle1.frame.size.width, self.circle1.frame.size.height) / 2.0f; 355 | CGFloat r2 = MAX(self.frame.size.width, self.frame.size.height) / 2.0f; 356 | 357 | //宽高不同时,半径的差值 358 | CGFloat diffR1 = fabs(self.circle1.frame.size.width - self.circle1.frame.size.height)/2.0; 359 | CGFloat diffR2 = fabs(self.frame.size.width - self.frame.size.height)/2.0; 360 | 361 | 362 | CGFloat x1 = self.circle1.center.x; 363 | CGFloat y1 = self.circle1.center.y; 364 | CGFloat x2 = self.center.x; 365 | CGFloat y2 = self.center.y; 366 | 367 | CGFloat distance = sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2)); 368 | 369 | CGFloat sinDegree = (x2 - x1) / distance; 370 | CGFloat cosDegree = (y2 - y1) / distance; 371 | 372 | CGPoint pointA = CGPointMake(x1 - (r1 - diffR1) * cosDegree, y1 + (r1 - diffR1) * sinDegree); 373 | CGPoint pointB = CGPointMake(x1 + (r1 - diffR1) * cosDegree, y1 - (r1 - diffR1) * sinDegree); 374 | CGPoint pointC = CGPointMake(x2 + (r2 - diffR2) * cosDegree, y2 - (r2 - diffR2) * sinDegree); 375 | CGPoint pointD = CGPointMake(x2 - (r2 - diffR2) * cosDegree, y2 + (r2 - diffR2) * sinDegree); 376 | 377 | CGPoint pointP = CGPointMake(pointB.x + (distance / 2) * sinDegree, pointB.y + (distance / 2) * cosDegree); 378 | CGPoint pointO = CGPointMake(pointA.x + (distance / 2) * sinDegree, pointA.y + (distance / 2) * cosDegree); 379 | 380 | UIBezierPath *path = [UIBezierPath bezierPath]; 381 | [path moveToPoint: pointA]; 382 | [path addLineToPoint: pointB]; 383 | 384 | [path addQuadCurveToPoint: pointC controlPoint: CGPointMake(pointP.x-r1*cosDegree*scale, pointP.y+r1*sinDegree*scale)]; 385 | /* 386 | if (distance>r1+r2) { 387 | [path addQuadCurveToPoint: pointC controlPoint: CGPointMake(pointP.x-r1*cosDegree*scale, pointP.y+r1*sinDegree*scale)]; 388 | }else{ 389 | [path addQuadCurveToPoint: pointC controlPoint: pointP]; 390 | } 391 | */ 392 | [path addLineToPoint: pointD]; 393 | 394 | [path addQuadCurveToPoint: pointA controlPoint: CGPointMake(pointO.x+r1*cosDegree*scale, pointO.y-r1*sinDegree*scale)]; 395 | /* 396 | if (distance >r1+r2) { 397 | [path addQuadCurveToPoint: pointA controlPoint: CGPointMake(pointO.x+r1*cosDegree*scale, pointO.y-r1*sinDegree*scale)]; 398 | }else{ 399 | [path addQuadCurveToPoint: pointA controlPoint: pointO]; 400 | } 401 | */ 402 | [self getShapeLayer].path = path.CGPath; 403 | } 404 | 405 | #pragma mark ============= CALayer实现粒子爆炸动画 406 | 407 | -(void)boomCellsInGesture:(UIGestureRecognizer*)gesture{ 408 | NSInteger rowClocn = 3; 409 | NSMutableArray *boomCells = [NSMutableArray array]; 410 | for (int i = 0; i < rowClocn*rowClocn; ++ i) { 411 | CGFloat pw = MIN(self.frame.size.width, self.frame.size.height); 412 | CALayer *shape = [CALayer layer]; 413 | shape.backgroundColor = [UIColor colorWithRed:231/255.0 green:231/255.0 blue:231/255.0 alpha:1.0].CGColor; 414 | shape.cornerRadius = pw / 2; 415 | //shape.frame = CGRectMake((i/rowClocn) * pw, (i%rowClocn) * pw, pw, pw); 416 | shape.frame = CGRectMake(0, 0, pw, pw); 417 | [self.layer.superlayer addSublayer: shape]; 418 | [boomCells addObject: shape]; 419 | } 420 | [self cellAnimations:boomCells withGesture:gesture]; 421 | } 422 | - (void) cellAnimations:(NSArray*)cells withGesture:(UIGestureRecognizer*)gesture{ 423 | 424 | for (NSInteger j=0; j0) { 483 | CGFloat angle = index*45*M_PI*2/360; 484 | CGFloat x = dia*cosf(angle); 485 | CGFloat y = dia*sinf(angle); 486 | [path addLineToPoint:CGPointMake(self.center.x + x, self.center.y+y)]; 487 | }else{ 488 | [path addLineToPoint:CGPointMake(self.center.x, self.center.y)]; 489 | } 490 | 491 | return path; 492 | } 493 | 494 | 495 | @end 496 | -------------------------------------------------------------------------------- /QQRed.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B6356D3D1DFE952E000365B8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B6356D3C1DFE952E000365B8 /* main.m */; }; 11 | B6356D401DFE952E000365B8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B6356D3F1DFE952E000365B8 /* AppDelegate.m */; }; 12 | B6356D431DFE952E000365B8 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B6356D421DFE952E000365B8 /* ViewController.m */; }; 13 | B6356D461DFE952E000365B8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B6356D441DFE952E000365B8 /* Main.storyboard */; }; 14 | B6356D481DFE952E000365B8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B6356D471DFE952E000365B8 /* Assets.xcassets */; }; 15 | B6356D4B1DFE952E000365B8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B6356D491DFE952E000365B8 /* LaunchScreen.storyboard */; }; 16 | B6356D561DFE952E000365B8 /* QQRedTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B6356D551DFE952E000365B8 /* QQRedTests.m */; }; 17 | B6356D611DFE952E000365B8 /* QQRedUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = B6356D601DFE952E000365B8 /* QQRedUITests.m */; }; 18 | B6B408901E0A382000534AFD /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B4088F1E0A382000534AFD /* DetailViewController.m */; }; 19 | B6FB90901E022E5E005AFDC3 /* unreadBomb_1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6FB90891E022E5E005AFDC3 /* unreadBomb_1@2x.png */; }; 20 | B6FB90911E022E5E005AFDC3 /* unreadBomb_2@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6FB908A1E022E5E005AFDC3 /* unreadBomb_2@2x.png */; }; 21 | B6FB90921E022E5E005AFDC3 /* unreadBomb_3@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6FB908B1E022E5E005AFDC3 /* unreadBomb_3@2x.png */; }; 22 | B6FB90931E022E5E005AFDC3 /* unreadBomb_4@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6FB908C1E022E5E005AFDC3 /* unreadBomb_4@2x.png */; }; 23 | B6FB90941E022E5E005AFDC3 /* unreadBomb_5@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B6FB908D1E022E5E005AFDC3 /* unreadBomb_5@2x.png */; }; 24 | B6FB90951E022E5E005AFDC3 /* UIView+DragBlast.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FB908F1E022E5E005AFDC3 /* UIView+DragBlast.m */; }; 25 | B6FB90991E023241005AFDC3 /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FB90971E023241005AFDC3 /* TableViewController.m */; }; 26 | B6FB909E1E024151005AFDC3 /* TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FB909C1E024151005AFDC3 /* TableViewCell.m */; }; 27 | B6FB909F1E024151005AFDC3 /* TableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B6FB909D1E024151005AFDC3 /* TableViewCell.xib */; }; 28 | B6FB90AC1E03D41C005AFDC3 /* JATagView.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FB90A91E03D41C005AFDC3 /* JATagView.m */; }; 29 | B6FB90AD1E03D41C005AFDC3 /* SearchResurltView.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FB90AB1E03D41C005AFDC3 /* SearchResurltView.m */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXContainerItemProxy section */ 33 | B6356D521DFE952E000365B8 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = B6356D301DFE952E000365B8 /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = B6356D371DFE952E000365B8; 38 | remoteInfo = QQRed; 39 | }; 40 | B6356D5D1DFE952E000365B8 /* PBXContainerItemProxy */ = { 41 | isa = PBXContainerItemProxy; 42 | containerPortal = B6356D301DFE952E000365B8 /* Project object */; 43 | proxyType = 1; 44 | remoteGlobalIDString = B6356D371DFE952E000365B8; 45 | remoteInfo = QQRed; 46 | }; 47 | /* End PBXContainerItemProxy section */ 48 | 49 | /* Begin PBXFileReference section */ 50 | B6356D381DFE952E000365B8 /* QQRed.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QQRed.app; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | B6356D3C1DFE952E000365B8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 52 | B6356D3E1DFE952E000365B8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 53 | B6356D3F1DFE952E000365B8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 54 | B6356D411DFE952E000365B8 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 55 | B6356D421DFE952E000365B8 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 56 | B6356D451DFE952E000365B8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 57 | B6356D471DFE952E000365B8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 58 | B6356D4A1DFE952E000365B8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 59 | B6356D4C1DFE952E000365B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | B6356D511DFE952E000365B8 /* QQRedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QQRedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | B6356D551DFE952E000365B8 /* QQRedTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QQRedTests.m; sourceTree = ""; }; 62 | B6356D571DFE952E000365B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63 | B6356D5C1DFE952E000365B8 /* QQRedUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QQRedUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | B6356D601DFE952E000365B8 /* QQRedUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QQRedUITests.m; sourceTree = ""; }; 65 | B6356D621DFE952E000365B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 66 | B6B4088E1E0A382000534AFD /* DetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; 67 | B6B4088F1E0A382000534AFD /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; 68 | B6FB90891E022E5E005AFDC3 /* unreadBomb_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "unreadBomb_1@2x.png"; sourceTree = ""; }; 69 | B6FB908A1E022E5E005AFDC3 /* unreadBomb_2@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "unreadBomb_2@2x.png"; sourceTree = ""; }; 70 | B6FB908B1E022E5E005AFDC3 /* unreadBomb_3@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "unreadBomb_3@2x.png"; sourceTree = ""; }; 71 | B6FB908C1E022E5E005AFDC3 /* unreadBomb_4@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "unreadBomb_4@2x.png"; sourceTree = ""; }; 72 | B6FB908D1E022E5E005AFDC3 /* unreadBomb_5@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "unreadBomb_5@2x.png"; sourceTree = ""; }; 73 | B6FB908E1E022E5E005AFDC3 /* UIView+DragBlast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+DragBlast.h"; sourceTree = ""; }; 74 | B6FB908F1E022E5E005AFDC3 /* UIView+DragBlast.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+DragBlast.m"; sourceTree = ""; }; 75 | B6FB90961E023241005AFDC3 /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = ""; }; 76 | B6FB90971E023241005AFDC3 /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = ""; }; 77 | B6FB909B1E024151005AFDC3 /* TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewCell.h; sourceTree = ""; }; 78 | B6FB909C1E024151005AFDC3 /* TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewCell.m; sourceTree = ""; }; 79 | B6FB909D1E024151005AFDC3 /* TableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TableViewCell.xib; sourceTree = ""; }; 80 | B6FB90A81E03D41C005AFDC3 /* JATagView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JATagView.h; sourceTree = ""; }; 81 | B6FB90A91E03D41C005AFDC3 /* JATagView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JATagView.m; sourceTree = ""; }; 82 | B6FB90AA1E03D41C005AFDC3 /* SearchResurltView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SearchResurltView.h; sourceTree = ""; }; 83 | B6FB90AB1E03D41C005AFDC3 /* SearchResurltView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SearchResurltView.m; sourceTree = ""; }; 84 | /* End PBXFileReference section */ 85 | 86 | /* Begin PBXFrameworksBuildPhase section */ 87 | B6356D351DFE952E000365B8 /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | B6356D4E1DFE952E000365B8 /* Frameworks */ = { 95 | isa = PBXFrameworksBuildPhase; 96 | buildActionMask = 2147483647; 97 | files = ( 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | B6356D591DFE952E000365B8 /* Frameworks */ = { 102 | isa = PBXFrameworksBuildPhase; 103 | buildActionMask = 2147483647; 104 | files = ( 105 | ); 106 | runOnlyForDeploymentPostprocessing = 0; 107 | }; 108 | /* End PBXFrameworksBuildPhase section */ 109 | 110 | /* Begin PBXGroup section */ 111 | B6356D2F1DFE952E000365B8 = { 112 | isa = PBXGroup; 113 | children = ( 114 | B6356D3A1DFE952E000365B8 /* QQRed */, 115 | B6356D541DFE952E000365B8 /* QQRedTests */, 116 | B6356D5F1DFE952E000365B8 /* QQRedUITests */, 117 | B6356D391DFE952E000365B8 /* Products */, 118 | ); 119 | sourceTree = ""; 120 | }; 121 | B6356D391DFE952E000365B8 /* Products */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | B6356D381DFE952E000365B8 /* QQRed.app */, 125 | B6356D511DFE952E000365B8 /* QQRedTests.xctest */, 126 | B6356D5C1DFE952E000365B8 /* QQRedUITests.xctest */, 127 | ); 128 | name = Products; 129 | sourceTree = ""; 130 | }; 131 | B6356D3A1DFE952E000365B8 /* QQRed */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | B6356D3E1DFE952E000365B8 /* AppDelegate.h */, 135 | B6356D3F1DFE952E000365B8 /* AppDelegate.m */, 136 | B6356D411DFE952E000365B8 /* ViewController.h */, 137 | B6356D421DFE952E000365B8 /* ViewController.m */, 138 | B6FB90961E023241005AFDC3 /* TableViewController.h */, 139 | B6FB90971E023241005AFDC3 /* TableViewController.m */, 140 | B6B4088E1E0A382000534AFD /* DetailViewController.h */, 141 | B6B4088F1E0A382000534AFD /* DetailViewController.m */, 142 | B6FB909B1E024151005AFDC3 /* TableViewCell.h */, 143 | B6FB909C1E024151005AFDC3 /* TableViewCell.m */, 144 | B6FB909D1E024151005AFDC3 /* TableViewCell.xib */, 145 | B6FB90871E022E5E005AFDC3 /* DragBlast */, 146 | B6356D441DFE952E000365B8 /* Main.storyboard */, 147 | B6356D471DFE952E000365B8 /* Assets.xcassets */, 148 | B6356D491DFE952E000365B8 /* LaunchScreen.storyboard */, 149 | B6356D4C1DFE952E000365B8 /* Info.plist */, 150 | B6FB90A71E03D41C005AFDC3 /* Search */, 151 | B6356D3B1DFE952E000365B8 /* Supporting Files */, 152 | ); 153 | path = QQRed; 154 | sourceTree = ""; 155 | }; 156 | B6356D3B1DFE952E000365B8 /* Supporting Files */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | B6356D3C1DFE952E000365B8 /* main.m */, 160 | ); 161 | name = "Supporting Files"; 162 | sourceTree = ""; 163 | }; 164 | B6356D541DFE952E000365B8 /* QQRedTests */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | B6356D551DFE952E000365B8 /* QQRedTests.m */, 168 | B6356D571DFE952E000365B8 /* Info.plist */, 169 | ); 170 | path = QQRedTests; 171 | sourceTree = ""; 172 | }; 173 | B6356D5F1DFE952E000365B8 /* QQRedUITests */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | B6356D601DFE952E000365B8 /* QQRedUITests.m */, 177 | B6356D621DFE952E000365B8 /* Info.plist */, 178 | ); 179 | path = QQRedUITests; 180 | sourceTree = ""; 181 | }; 182 | B6FB90871E022E5E005AFDC3 /* DragBlast */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | B6FB90881E022E5E005AFDC3 /* imageSoure */, 186 | B6FB908E1E022E5E005AFDC3 /* UIView+DragBlast.h */, 187 | B6FB908F1E022E5E005AFDC3 /* UIView+DragBlast.m */, 188 | ); 189 | path = DragBlast; 190 | sourceTree = ""; 191 | }; 192 | B6FB90881E022E5E005AFDC3 /* imageSoure */ = { 193 | isa = PBXGroup; 194 | children = ( 195 | B6FB90891E022E5E005AFDC3 /* unreadBomb_1@2x.png */, 196 | B6FB908A1E022E5E005AFDC3 /* unreadBomb_2@2x.png */, 197 | B6FB908B1E022E5E005AFDC3 /* unreadBomb_3@2x.png */, 198 | B6FB908C1E022E5E005AFDC3 /* unreadBomb_4@2x.png */, 199 | B6FB908D1E022E5E005AFDC3 /* unreadBomb_5@2x.png */, 200 | ); 201 | path = imageSoure; 202 | sourceTree = ""; 203 | }; 204 | B6FB90A71E03D41C005AFDC3 /* Search */ = { 205 | isa = PBXGroup; 206 | children = ( 207 | B6FB90A81E03D41C005AFDC3 /* JATagView.h */, 208 | B6FB90A91E03D41C005AFDC3 /* JATagView.m */, 209 | B6FB90AA1E03D41C005AFDC3 /* SearchResurltView.h */, 210 | B6FB90AB1E03D41C005AFDC3 /* SearchResurltView.m */, 211 | ); 212 | path = Search; 213 | sourceTree = ""; 214 | }; 215 | /* End PBXGroup section */ 216 | 217 | /* Begin PBXNativeTarget section */ 218 | B6356D371DFE952E000365B8 /* QQRed */ = { 219 | isa = PBXNativeTarget; 220 | buildConfigurationList = B6356D651DFE952E000365B8 /* Build configuration list for PBXNativeTarget "QQRed" */; 221 | buildPhases = ( 222 | B6356D341DFE952E000365B8 /* Sources */, 223 | B6356D351DFE952E000365B8 /* Frameworks */, 224 | B6356D361DFE952E000365B8 /* Resources */, 225 | ); 226 | buildRules = ( 227 | ); 228 | dependencies = ( 229 | ); 230 | name = QQRed; 231 | productName = QQRed; 232 | productReference = B6356D381DFE952E000365B8 /* QQRed.app */; 233 | productType = "com.apple.product-type.application"; 234 | }; 235 | B6356D501DFE952E000365B8 /* QQRedTests */ = { 236 | isa = PBXNativeTarget; 237 | buildConfigurationList = B6356D681DFE952E000365B8 /* Build configuration list for PBXNativeTarget "QQRedTests" */; 238 | buildPhases = ( 239 | B6356D4D1DFE952E000365B8 /* Sources */, 240 | B6356D4E1DFE952E000365B8 /* Frameworks */, 241 | B6356D4F1DFE952E000365B8 /* Resources */, 242 | ); 243 | buildRules = ( 244 | ); 245 | dependencies = ( 246 | B6356D531DFE952E000365B8 /* PBXTargetDependency */, 247 | ); 248 | name = QQRedTests; 249 | productName = QQRedTests; 250 | productReference = B6356D511DFE952E000365B8 /* QQRedTests.xctest */; 251 | productType = "com.apple.product-type.bundle.unit-test"; 252 | }; 253 | B6356D5B1DFE952E000365B8 /* QQRedUITests */ = { 254 | isa = PBXNativeTarget; 255 | buildConfigurationList = B6356D6B1DFE952E000365B8 /* Build configuration list for PBXNativeTarget "QQRedUITests" */; 256 | buildPhases = ( 257 | B6356D581DFE952E000365B8 /* Sources */, 258 | B6356D591DFE952E000365B8 /* Frameworks */, 259 | B6356D5A1DFE952E000365B8 /* Resources */, 260 | ); 261 | buildRules = ( 262 | ); 263 | dependencies = ( 264 | B6356D5E1DFE952E000365B8 /* PBXTargetDependency */, 265 | ); 266 | name = QQRedUITests; 267 | productName = QQRedUITests; 268 | productReference = B6356D5C1DFE952E000365B8 /* QQRedUITests.xctest */; 269 | productType = "com.apple.product-type.bundle.ui-testing"; 270 | }; 271 | /* End PBXNativeTarget section */ 272 | 273 | /* Begin PBXProject section */ 274 | B6356D301DFE952E000365B8 /* Project object */ = { 275 | isa = PBXProject; 276 | attributes = { 277 | LastUpgradeCheck = 1010; 278 | ORGANIZATIONNAME = Youjuke; 279 | TargetAttributes = { 280 | B6356D371DFE952E000365B8 = { 281 | CreatedOnToolsVersion = 8.1; 282 | DevelopmentTeam = N3379XTAJ9; 283 | ProvisioningStyle = Automatic; 284 | }; 285 | B6356D501DFE952E000365B8 = { 286 | CreatedOnToolsVersion = 8.1; 287 | ProvisioningStyle = Automatic; 288 | TestTargetID = B6356D371DFE952E000365B8; 289 | }; 290 | B6356D5B1DFE952E000365B8 = { 291 | CreatedOnToolsVersion = 8.1; 292 | ProvisioningStyle = Automatic; 293 | TestTargetID = B6356D371DFE952E000365B8; 294 | }; 295 | }; 296 | }; 297 | buildConfigurationList = B6356D331DFE952E000365B8 /* Build configuration list for PBXProject "QQRed" */; 298 | compatibilityVersion = "Xcode 3.2"; 299 | developmentRegion = English; 300 | hasScannedForEncodings = 0; 301 | knownRegions = ( 302 | en, 303 | Base, 304 | ); 305 | mainGroup = B6356D2F1DFE952E000365B8; 306 | productRefGroup = B6356D391DFE952E000365B8 /* Products */; 307 | projectDirPath = ""; 308 | projectRoot = ""; 309 | targets = ( 310 | B6356D371DFE952E000365B8 /* QQRed */, 311 | B6356D501DFE952E000365B8 /* QQRedTests */, 312 | B6356D5B1DFE952E000365B8 /* QQRedUITests */, 313 | ); 314 | }; 315 | /* End PBXProject section */ 316 | 317 | /* Begin PBXResourcesBuildPhase section */ 318 | B6356D361DFE952E000365B8 /* Resources */ = { 319 | isa = PBXResourcesBuildPhase; 320 | buildActionMask = 2147483647; 321 | files = ( 322 | B6FB90921E022E5E005AFDC3 /* unreadBomb_3@2x.png in Resources */, 323 | B6FB90911E022E5E005AFDC3 /* unreadBomb_2@2x.png in Resources */, 324 | B6356D4B1DFE952E000365B8 /* LaunchScreen.storyboard in Resources */, 325 | B6FB90941E022E5E005AFDC3 /* unreadBomb_5@2x.png in Resources */, 326 | B6FB909F1E024151005AFDC3 /* TableViewCell.xib in Resources */, 327 | B6356D481DFE952E000365B8 /* Assets.xcassets in Resources */, 328 | B6356D461DFE952E000365B8 /* Main.storyboard in Resources */, 329 | B6FB90931E022E5E005AFDC3 /* unreadBomb_4@2x.png in Resources */, 330 | B6FB90901E022E5E005AFDC3 /* unreadBomb_1@2x.png in Resources */, 331 | ); 332 | runOnlyForDeploymentPostprocessing = 0; 333 | }; 334 | B6356D4F1DFE952E000365B8 /* Resources */ = { 335 | isa = PBXResourcesBuildPhase; 336 | buildActionMask = 2147483647; 337 | files = ( 338 | ); 339 | runOnlyForDeploymentPostprocessing = 0; 340 | }; 341 | B6356D5A1DFE952E000365B8 /* Resources */ = { 342 | isa = PBXResourcesBuildPhase; 343 | buildActionMask = 2147483647; 344 | files = ( 345 | ); 346 | runOnlyForDeploymentPostprocessing = 0; 347 | }; 348 | /* End PBXResourcesBuildPhase section */ 349 | 350 | /* Begin PBXSourcesBuildPhase section */ 351 | B6356D341DFE952E000365B8 /* Sources */ = { 352 | isa = PBXSourcesBuildPhase; 353 | buildActionMask = 2147483647; 354 | files = ( 355 | B6FB90AD1E03D41C005AFDC3 /* SearchResurltView.m in Sources */, 356 | B6FB90AC1E03D41C005AFDC3 /* JATagView.m in Sources */, 357 | B6B408901E0A382000534AFD /* DetailViewController.m in Sources */, 358 | B6356D431DFE952E000365B8 /* ViewController.m in Sources */, 359 | B6FB909E1E024151005AFDC3 /* TableViewCell.m in Sources */, 360 | B6356D401DFE952E000365B8 /* AppDelegate.m in Sources */, 361 | B6FB90951E022E5E005AFDC3 /* UIView+DragBlast.m in Sources */, 362 | B6FB90991E023241005AFDC3 /* TableViewController.m in Sources */, 363 | B6356D3D1DFE952E000365B8 /* main.m in Sources */, 364 | ); 365 | runOnlyForDeploymentPostprocessing = 0; 366 | }; 367 | B6356D4D1DFE952E000365B8 /* Sources */ = { 368 | isa = PBXSourcesBuildPhase; 369 | buildActionMask = 2147483647; 370 | files = ( 371 | B6356D561DFE952E000365B8 /* QQRedTests.m in Sources */, 372 | ); 373 | runOnlyForDeploymentPostprocessing = 0; 374 | }; 375 | B6356D581DFE952E000365B8 /* Sources */ = { 376 | isa = PBXSourcesBuildPhase; 377 | buildActionMask = 2147483647; 378 | files = ( 379 | B6356D611DFE952E000365B8 /* QQRedUITests.m in Sources */, 380 | ); 381 | runOnlyForDeploymentPostprocessing = 0; 382 | }; 383 | /* End PBXSourcesBuildPhase section */ 384 | 385 | /* Begin PBXTargetDependency section */ 386 | B6356D531DFE952E000365B8 /* PBXTargetDependency */ = { 387 | isa = PBXTargetDependency; 388 | target = B6356D371DFE952E000365B8 /* QQRed */; 389 | targetProxy = B6356D521DFE952E000365B8 /* PBXContainerItemProxy */; 390 | }; 391 | B6356D5E1DFE952E000365B8 /* PBXTargetDependency */ = { 392 | isa = PBXTargetDependency; 393 | target = B6356D371DFE952E000365B8 /* QQRed */; 394 | targetProxy = B6356D5D1DFE952E000365B8 /* PBXContainerItemProxy */; 395 | }; 396 | /* End PBXTargetDependency section */ 397 | 398 | /* Begin PBXVariantGroup section */ 399 | B6356D441DFE952E000365B8 /* Main.storyboard */ = { 400 | isa = PBXVariantGroup; 401 | children = ( 402 | B6356D451DFE952E000365B8 /* Base */, 403 | ); 404 | name = Main.storyboard; 405 | sourceTree = ""; 406 | }; 407 | B6356D491DFE952E000365B8 /* LaunchScreen.storyboard */ = { 408 | isa = PBXVariantGroup; 409 | children = ( 410 | B6356D4A1DFE952E000365B8 /* Base */, 411 | ); 412 | name = LaunchScreen.storyboard; 413 | sourceTree = ""; 414 | }; 415 | /* End PBXVariantGroup section */ 416 | 417 | /* Begin XCBuildConfiguration section */ 418 | B6356D631DFE952E000365B8 /* Debug */ = { 419 | isa = XCBuildConfiguration; 420 | buildSettings = { 421 | ALWAYS_SEARCH_USER_PATHS = NO; 422 | CLANG_ANALYZER_NONNULL = YES; 423 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 424 | CLANG_CXX_LIBRARY = "libc++"; 425 | CLANG_ENABLE_MODULES = YES; 426 | CLANG_ENABLE_OBJC_ARC = YES; 427 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 428 | CLANG_WARN_BOOL_CONVERSION = YES; 429 | CLANG_WARN_COMMA = YES; 430 | CLANG_WARN_CONSTANT_CONVERSION = YES; 431 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 432 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 433 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 434 | CLANG_WARN_EMPTY_BODY = YES; 435 | CLANG_WARN_ENUM_CONVERSION = YES; 436 | CLANG_WARN_INFINITE_RECURSION = YES; 437 | CLANG_WARN_INT_CONVERSION = YES; 438 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 439 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 440 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 441 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 442 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 443 | CLANG_WARN_STRICT_PROTOTYPES = YES; 444 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 445 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 446 | CLANG_WARN_UNREACHABLE_CODE = YES; 447 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 448 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 449 | COPY_PHASE_STRIP = NO; 450 | DEBUG_INFORMATION_FORMAT = dwarf; 451 | ENABLE_STRICT_OBJC_MSGSEND = YES; 452 | ENABLE_TESTABILITY = YES; 453 | GCC_C_LANGUAGE_STANDARD = gnu99; 454 | GCC_DYNAMIC_NO_PIC = NO; 455 | GCC_NO_COMMON_BLOCKS = YES; 456 | GCC_OPTIMIZATION_LEVEL = 0; 457 | GCC_PREPROCESSOR_DEFINITIONS = ( 458 | "DEBUG=1", 459 | "$(inherited)", 460 | ); 461 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 462 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 463 | GCC_WARN_UNDECLARED_SELECTOR = YES; 464 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 465 | GCC_WARN_UNUSED_FUNCTION = YES; 466 | GCC_WARN_UNUSED_VARIABLE = YES; 467 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 468 | MTL_ENABLE_DEBUG_INFO = YES; 469 | ONLY_ACTIVE_ARCH = YES; 470 | SDKROOT = iphoneos; 471 | }; 472 | name = Debug; 473 | }; 474 | B6356D641DFE952E000365B8 /* Release */ = { 475 | isa = XCBuildConfiguration; 476 | buildSettings = { 477 | ALWAYS_SEARCH_USER_PATHS = NO; 478 | CLANG_ANALYZER_NONNULL = YES; 479 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 480 | CLANG_CXX_LIBRARY = "libc++"; 481 | CLANG_ENABLE_MODULES = YES; 482 | CLANG_ENABLE_OBJC_ARC = YES; 483 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 484 | CLANG_WARN_BOOL_CONVERSION = YES; 485 | CLANG_WARN_COMMA = YES; 486 | CLANG_WARN_CONSTANT_CONVERSION = YES; 487 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 488 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 489 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 490 | CLANG_WARN_EMPTY_BODY = YES; 491 | CLANG_WARN_ENUM_CONVERSION = YES; 492 | CLANG_WARN_INFINITE_RECURSION = YES; 493 | CLANG_WARN_INT_CONVERSION = YES; 494 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 495 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 496 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 497 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 498 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 499 | CLANG_WARN_STRICT_PROTOTYPES = YES; 500 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 501 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 502 | CLANG_WARN_UNREACHABLE_CODE = YES; 503 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 504 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 505 | COPY_PHASE_STRIP = NO; 506 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 507 | ENABLE_NS_ASSERTIONS = NO; 508 | ENABLE_STRICT_OBJC_MSGSEND = YES; 509 | GCC_C_LANGUAGE_STANDARD = gnu99; 510 | GCC_NO_COMMON_BLOCKS = YES; 511 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 512 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 513 | GCC_WARN_UNDECLARED_SELECTOR = YES; 514 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 515 | GCC_WARN_UNUSED_FUNCTION = YES; 516 | GCC_WARN_UNUSED_VARIABLE = YES; 517 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 518 | MTL_ENABLE_DEBUG_INFO = NO; 519 | SDKROOT = iphoneos; 520 | VALIDATE_PRODUCT = YES; 521 | }; 522 | name = Release; 523 | }; 524 | B6356D661DFE952E000365B8 /* Debug */ = { 525 | isa = XCBuildConfiguration; 526 | buildSettings = { 527 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 528 | DEVELOPMENT_TEAM = N3379XTAJ9; 529 | INFOPLIST_FILE = QQRed/Info.plist; 530 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 531 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 532 | PRODUCT_BUNDLE_IDENTIFIER = com.youjuke.QQRed; 533 | PRODUCT_NAME = "$(TARGET_NAME)"; 534 | }; 535 | name = Debug; 536 | }; 537 | B6356D671DFE952E000365B8 /* Release */ = { 538 | isa = XCBuildConfiguration; 539 | buildSettings = { 540 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 541 | DEVELOPMENT_TEAM = N3379XTAJ9; 542 | INFOPLIST_FILE = QQRed/Info.plist; 543 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 544 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 545 | PRODUCT_BUNDLE_IDENTIFIER = com.youjuke.QQRed; 546 | PRODUCT_NAME = "$(TARGET_NAME)"; 547 | }; 548 | name = Release; 549 | }; 550 | B6356D691DFE952E000365B8 /* Debug */ = { 551 | isa = XCBuildConfiguration; 552 | buildSettings = { 553 | BUNDLE_LOADER = "$(TEST_HOST)"; 554 | INFOPLIST_FILE = QQRedTests/Info.plist; 555 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 556 | PRODUCT_BUNDLE_IDENTIFIER = com.youjuke.QQRedTests; 557 | PRODUCT_NAME = "$(TARGET_NAME)"; 558 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/QQRed.app/QQRed"; 559 | }; 560 | name = Debug; 561 | }; 562 | B6356D6A1DFE952E000365B8 /* Release */ = { 563 | isa = XCBuildConfiguration; 564 | buildSettings = { 565 | BUNDLE_LOADER = "$(TEST_HOST)"; 566 | INFOPLIST_FILE = QQRedTests/Info.plist; 567 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 568 | PRODUCT_BUNDLE_IDENTIFIER = com.youjuke.QQRedTests; 569 | PRODUCT_NAME = "$(TARGET_NAME)"; 570 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/QQRed.app/QQRed"; 571 | }; 572 | name = Release; 573 | }; 574 | B6356D6C1DFE952E000365B8 /* Debug */ = { 575 | isa = XCBuildConfiguration; 576 | buildSettings = { 577 | INFOPLIST_FILE = QQRedUITests/Info.plist; 578 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 579 | PRODUCT_BUNDLE_IDENTIFIER = com.youjuke.QQRedUITests; 580 | PRODUCT_NAME = "$(TARGET_NAME)"; 581 | TEST_TARGET_NAME = QQRed; 582 | }; 583 | name = Debug; 584 | }; 585 | B6356D6D1DFE952E000365B8 /* Release */ = { 586 | isa = XCBuildConfiguration; 587 | buildSettings = { 588 | INFOPLIST_FILE = QQRedUITests/Info.plist; 589 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 590 | PRODUCT_BUNDLE_IDENTIFIER = com.youjuke.QQRedUITests; 591 | PRODUCT_NAME = "$(TARGET_NAME)"; 592 | TEST_TARGET_NAME = QQRed; 593 | }; 594 | name = Release; 595 | }; 596 | /* End XCBuildConfiguration section */ 597 | 598 | /* Begin XCConfigurationList section */ 599 | B6356D331DFE952E000365B8 /* Build configuration list for PBXProject "QQRed" */ = { 600 | isa = XCConfigurationList; 601 | buildConfigurations = ( 602 | B6356D631DFE952E000365B8 /* Debug */, 603 | B6356D641DFE952E000365B8 /* Release */, 604 | ); 605 | defaultConfigurationIsVisible = 0; 606 | defaultConfigurationName = Release; 607 | }; 608 | B6356D651DFE952E000365B8 /* Build configuration list for PBXNativeTarget "QQRed" */ = { 609 | isa = XCConfigurationList; 610 | buildConfigurations = ( 611 | B6356D661DFE952E000365B8 /* Debug */, 612 | B6356D671DFE952E000365B8 /* Release */, 613 | ); 614 | defaultConfigurationIsVisible = 0; 615 | defaultConfigurationName = Release; 616 | }; 617 | B6356D681DFE952E000365B8 /* Build configuration list for PBXNativeTarget "QQRedTests" */ = { 618 | isa = XCConfigurationList; 619 | buildConfigurations = ( 620 | B6356D691DFE952E000365B8 /* Debug */, 621 | B6356D6A1DFE952E000365B8 /* Release */, 622 | ); 623 | defaultConfigurationIsVisible = 0; 624 | defaultConfigurationName = Release; 625 | }; 626 | B6356D6B1DFE952E000365B8 /* Build configuration list for PBXNativeTarget "QQRedUITests" */ = { 627 | isa = XCConfigurationList; 628 | buildConfigurations = ( 629 | B6356D6C1DFE952E000365B8 /* Debug */, 630 | B6356D6D1DFE952E000365B8 /* Release */, 631 | ); 632 | defaultConfigurationIsVisible = 0; 633 | defaultConfigurationName = Release; 634 | }; 635 | /* End XCConfigurationList section */ 636 | }; 637 | rootObject = B6356D301DFE952E000365B8 /* Project object */; 638 | } 639 | --------------------------------------------------------------------------------