├── images ├── g614799921.jpg └── AssistiveTouchViewPreview.gif ├── Basic Files ├── Images │ ├── atv_hide_left@2x.png │ ├── atv_item_cafe@2x.png │ ├── atv_item_cs@2x.png │ ├── atv_item_user@2x.png │ ├── atv_hide_right@2x.png │ ├── atv_normal_left@2x.png │ ├── atv_unit1_left@2x.png │ ├── atv_unit1_right@2x.png │ ├── atv_unit2_left@2x.png │ ├── atv_unit2_right@2x.png │ └── atv_normal_right@2x.png ├── ViewController.h ├── AppDelegate.h ├── Supporting Files │ ├── main.m │ └── Info.plist ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── AppDelegate.m └── ViewController.m ├── DYFAssistiveTouchView.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ └── DYFAssistiveTouchView.xcscheme └── project.pbxproj ├── LICENSE ├── DYFAssistiveTouchView.podspec ├── .gitignore ├── Classes ├── DYFAssistiveTouchView.h └── DYFAssistiveTouchView.m └── README.md /images/g614799921.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/images/g614799921.jpg -------------------------------------------------------------------------------- /images/AssistiveTouchViewPreview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/images/AssistiveTouchViewPreview.gif -------------------------------------------------------------------------------- /Basic Files/Images/atv_hide_left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_hide_left@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_item_cafe@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_item_cafe@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_item_cs@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_item_cs@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_item_user@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_item_user@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_hide_right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_hide_right@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_normal_left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_normal_left@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_unit1_left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_unit1_left@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_unit1_right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_unit1_right@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_unit2_left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_unit2_left@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_unit2_right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_unit2_right@2x.png -------------------------------------------------------------------------------- /Basic Files/Images/atv_normal_right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itenfay/DYFAssistiveTouchView/HEAD/Basic Files/Images/atv_normal_right@2x.png -------------------------------------------------------------------------------- /Basic Files/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // 4 | // Created by Tenfay on 14/10/31. 5 | // Copyright © 2014年 Tenfay. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface ViewController : UIViewController 11 | 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /DYFAssistiveTouchView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Basic Files/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // 4 | // Created by Tenfay on 14/10/31. 5 | // Copyright © 2014年 Tenfay. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface AppDelegate : UIResponder 11 | 12 | @property (strong, nonatomic) UIWindow *window; 13 | 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /DYFAssistiveTouchView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Basic Files/Supporting Files/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // 4 | // Created by Tenfay on 14/10/31. 5 | // Copyright © 2014年 Tenfay. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "AppDelegate.h" 10 | 11 | int main(int argc, char * argv[]) { 12 | @autoreleasepool { 13 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Created by Tenfay on 2014/10/31. 4 | Copyright © 2014 Tenfay. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /DYFAssistiveTouchView.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | s.name = "DYFAssistiveTouchView" 4 | s.version = "4.3.1" 5 | s.summary = "应用内悬浮按钮和工具条,可以增加/修改 Item 项,通过事件索引实现各种场景页面的跳转。" 6 | 7 | s.homepage = "https://github.com/itenfay/DYFAssistiveTouchView" 8 | 9 | s.license = { :type => "MIT", :file => "LICENSE" } 10 | 11 | s.author = { "Tenfay" => "itenfay@163.com" } 12 | # s.social_media_url = "http://twitter.com/Tenfay" 13 | 14 | s.platform = :ios 15 | s.ios.deployment_target = "8.0" 16 | # s.osx.deployment_target = "10.7" 17 | # s.watchos.deployment_target = "2.0" 18 | # s.tvos.deployment_target = "9.0" 19 | 20 | s.source = { :git => "https://github.com/itenfay/DYFAssistiveTouchView.git", :tag => s.version.to_s } 21 | 22 | s.source_files = "Classes/**/*.{h,m}" 23 | s.public_header_files = "Classes/**/*.h" 24 | 25 | # s.resource = "icon.png" 26 | # s.resources = "Resources/*.png" 27 | 28 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 29 | 30 | s.frameworks = "QuartzCore" 31 | 32 | # s.library = "iconv" 33 | # s.libraries = "iconv", "xml2" 34 | 35 | s.requires_arc = true 36 | 37 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 38 | # s.dependency "JSONKit", "~> 1.4" 39 | end 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## MacOS 26 | .DS_Store 27 | 28 | ## Obj-C/Swift specific 29 | *.hmap 30 | *.ipa 31 | *.dSYM.zip 32 | *.dSYM 33 | 34 | # CocoaPods 35 | # 36 | # We recommend against adding the Pods directory to your .gitignore. However 37 | # you should judge for yourself, the pros and cons are mentioned at: 38 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 39 | # 40 | # Pods/ 41 | 42 | # Carthage 43 | # 44 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 45 | # Carthage/Checkouts 46 | 47 | Carthage/Build 48 | 49 | # fastlane 50 | # 51 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 52 | # screenshots whenever they are needed. 53 | # For more information about the recommended setup visit: 54 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 55 | 56 | fastlane/report.xml 57 | fastlane/Preview.html 58 | fastlane/screenshots/**/*.png 59 | fastlane/test_output 60 | 61 | # Code Injection 62 | # 63 | # After new code Injection tools there's a generated folder /iOSInjectionProject 64 | # https://github.com/johnno1962/injectionforxcode 65 | 66 | iOSInjectionProject/ 67 | -------------------------------------------------------------------------------- /Basic Files/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | FloatTouchView 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 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Basic Files/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 | -------------------------------------------------------------------------------- /Basic Files/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Basic Files/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // 4 | // Created by Tenfay on 14/10/31. 5 | // Copyright © 2014年 Tenfay. All rights reserved. 6 | // 7 | 8 | #import "AppDelegate.h" 9 | 10 | @interface AppDelegate () 11 | 12 | @end 13 | 14 | @implementation AppDelegate 15 | 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 18 | // Override point for customization after application launch. 19 | return YES; 20 | } 21 | 22 | - (void)applicationWillResignActive:(UIApplication *)application { 23 | // 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. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | - (void)applicationDidEnterBackground:(UIApplication *)application { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | - (void)applicationWillEnterForeground:(UIApplication *)application { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application { 37 | // 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. 38 | } 39 | 40 | - (void)applicationWillTerminate:(UIApplication *)application { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /DYFAssistiveTouchView.xcodeproj/xcshareddata/xcschemes/DYFAssistiveTouchView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Basic Files/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // 4 | // Created by Tenfay on 14/10/31. 5 | // Copyright © 2014年 Tenfay. All rights reserved. 6 | // 7 | 8 | #import "ViewController.h" 9 | #import "DYFAssistiveTouchView.h" 10 | #import 11 | 12 | @interface ViewController () 13 | @property(nonatomic, strong) DYFAssistiveTouchView *touchView; 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | } 21 | 22 | - (IBAction)configureAction:(id)sender { 23 | if (!_touchView) { 24 | [self configTouchViewDotImages]; 25 | [self configTouchViewUnits]; 26 | [self configTouchViewItems]; 27 | 28 | [self.touchView setShouldShowHalf:YES]; 29 | [self.touchView setTouchViewPlace:DYFTouchViewAtMiddleRight]; 30 | 31 | __weak typeof(self) weakSelf = self; 32 | [self.touchView touchViewItemDidClickedAtIndex:^(DYFAssistiveTouchView *touchView) { 33 | NSInteger index = touchView.indexOfItem; 34 | NSLog(@"Index of item: %zi", index); 35 | [weakSelf presentAtIndex:index]; 36 | }]; 37 | } 38 | } 39 | 40 | - (IBAction)showAndHideAction:(id)sender { 41 | if (_touchView) { 42 | if ([self.touchView isShowing]) { 43 | [self.touchView hide]; 44 | } else { 45 | [self.touchView show]; 46 | } 47 | } 48 | } 49 | 50 | - (void)presentAtIndex:(NSInteger)index { 51 | NSString *url = @"https://support.apple.com/zh-cn"; 52 | if (index == 0) { 53 | url = @"https://github.com/itenfay"; 54 | } else if (index == 1) { 55 | url = @"https://github.com/itenfay/Awesome"; 56 | } else { 57 | url = @"https://www.jianshu.com/u/7fc76f1179cc"; 58 | } 59 | 60 | SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:url]]; 61 | [self presentViewController:safariVC animated:YES completion:NULL]; 62 | } 63 | 64 | - (void)configTouchViewDotImages { 65 | UIImage *leftHidenImage = [UIImage imageNamed:@"atv_hide_left"]; 66 | UIImage *rightHidenImage = leftHidenImage; 67 | UIImage *leftNormalImage = [UIImage imageNamed:@"atv_normal_left"]; 68 | UIImage *rightNormalImage = leftNormalImage; 69 | UIImage *leftHighlightedImage = [UIImage imageNamed:@"atv_normal_left"]; 70 | UIImage *rightHighlightedImage = leftHighlightedImage; 71 | 72 | self.touchView.touchObject.leftNormalImage = leftNormalImage; 73 | self.touchView.touchObject.rightNormalImage = rightNormalImage; 74 | self.touchView.touchObject.leftHighlightedImage = leftHighlightedImage; 75 | self.touchView.touchObject.rightHighlightedImage = rightHighlightedImage; 76 | self.touchView.touchObject.leftTranslucentImage = leftHidenImage; 77 | self.touchView.touchObject.rightTranslucentImage = rightHidenImage; 78 | } 79 | 80 | - (void)configTouchViewUnits { 81 | UIImage *leftUint1Image = [UIImage imageNamed:@"atv_unit1_left"]; 82 | UIImage *rightUint1Image = [UIImage imageNamed:@"atv_unit1_right"]; 83 | UIImage *leftUint2Image = [UIImage imageNamed:@"atv_unit2_left"]; 84 | UIImage *rightUint2Image = [UIImage imageNamed:@"atv_unit2_right"]; 85 | 86 | self.touchView.unitObject.leftTouchImage = leftUint1Image; 87 | self.touchView.unitObject.rightTouchImage = rightUint1Image; 88 | self.touchView.unitObject.leftItemBackgroundImage = leftUint2Image; 89 | self.touchView.unitObject.rightItemBackgroundImage = rightUint2Image; 90 | } 91 | 92 | - (void)configTouchViewItems { 93 | UIImage *userImage = [UIImage imageNamed:@"atv_item_user"]; 94 | UIImage *cafeImage = [UIImage imageNamed:@"atv_item_cafe"]; 95 | UIImage *csImage = [UIImage imageNamed:@"atv_item_cs"]; 96 | 97 | DYFAssistiveTouchItem *item = [[DYFAssistiveTouchItem alloc] init]; 98 | item.image = userImage; 99 | DYFAssistiveTouchItem *item1 = [[DYFAssistiveTouchItem alloc] init]; 100 | item1.image = cafeImage; 101 | DYFAssistiveTouchItem *item2 = [[DYFAssistiveTouchItem alloc] init]; 102 | item2.image = csImage; 103 | 104 | self.touchView.items = @[item, item1, item2]; 105 | } 106 | 107 | #pragma mark - Lazy load 108 | 109 | - (DYFAssistiveTouchView *)touchView { 110 | if (!_touchView) { 111 | _touchView = [[DYFAssistiveTouchView alloc] init]; 112 | _touchView.frame = CGRectMake(0, 0, 50, 50); 113 | } 114 | return _touchView; 115 | } 116 | 117 | - (void)didReceiveMemoryWarning { 118 | [super didReceiveMemoryWarning]; 119 | } 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /Classes/DYFAssistiveTouchView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DYFAssistiveTouchView.h 3 | // 4 | // Created by Tenfay on 14/10/31. 5 | // Copyright (c) 2014 Tenfay. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import 27 | #import 28 | 29 | @class DYFAssistiveTouchView; 30 | 31 | typedef NS_ENUM(NSInteger, DYFTouchViewPlace) { 32 | DYFTouchViewAtTopLeft = 1 << 0, // At top and left. 33 | DYFTouchViewAtTopRight = 1 << 1, // At top and right. 34 | DYFTouchViewAtMiddleLeft = 1 << 2, // At middle and left. 35 | DYFTouchViewAtMiddleRight = 1 << 3, // At middle and right. 36 | DYFTouchViewAtBottomLeft = 1 << 4, // At bottom and left. 37 | DYFTouchViewAtBottomRight = 1 << 5, // At bottom and right. 38 | }; 39 | 40 | @protocol DYFAssistiveTouchViewDelegate 41 | 42 | @optional 43 | /** 44 | * TouchView item did clicked. 45 | * 46 | * @param touchView An `DYFAssistiveTouchView` object. 47 | */ 48 | - (void)touchViewItemDidClickedAtIndex:(nullable DYFAssistiveTouchView *)touchView; 49 | 50 | @end 51 | 52 | /** 53 | * TouchView item did clicked with block. 54 | * 55 | * @param touchView An `DYFAssistiveTouchView` object. 56 | */ 57 | typedef void (^DYFTouchViewItemDidClickedBlock)(DYFAssistiveTouchView *_Nullable touchView); 58 | 59 | @interface DYFAssistiveTouchObject : NSObject 60 | // TouchView normal image at left. 61 | @property (nonatomic, strong, nullable) UIImage *leftNormalImage; 62 | // TouchView normal image at right. 63 | @property (nonatomic, strong, nullable) UIImage *rightNormalImage; 64 | // TouchView highlighted image at left. 65 | @property (nonatomic, strong, nullable) UIImage *leftHighlightedImage; 66 | // TouchView highlighted image at right. 67 | @property (nonatomic, strong, nullable) UIImage *rightHighlightedImage; 68 | // TouchView translucent image at left. 69 | @property (nonatomic, strong, nullable) UIImage *leftTranslucentImage; 70 | // TouchView translucent image at right. 71 | @property (nonatomic, strong, nullable) UIImage *rightTranslucentImage; 72 | @end 73 | 74 | @interface DYFAssistiveTouchUnit : NSObject 75 | // Left touch image. 76 | @property (nonatomic, strong, nullable) UIImage *leftTouchImage; 77 | // Right touch image. 78 | @property (nonatomic, strong, nullable) UIImage *rightTouchImage; 79 | // Left item background image. 80 | @property (nonatomic, strong, nullable) UIImage *leftItemBackgroundImage; 81 | // Right item background image. 82 | @property (nonatomic, strong, nullable) UIImage *rightItemBackgroundImage; 83 | @end 84 | 85 | @interface DYFAssistiveTouchItem: NSObject 86 | // Normal image. 87 | @property (nonatomic, strong, nullable) UIImage *image; 88 | // Highlighted image. 89 | @property (nonatomic, strong, nullable) UIImage *highlightedImage; 90 | @end 91 | 92 | @interface DYFAssistiveTouchView : UIView 93 | // The delegate for touchView item which did clicked. 94 | @property (nonatomic, weak, nullable) id delegate; 95 | 96 | // TouchView is displaying or not displaying. 97 | @property (nonatomic, assign, readonly, getter=isShowing) BOOL showing; 98 | // TouchView is moving or not moving. 99 | @property (nonatomic, assign, readonly, getter=isMoving) BOOL moving; 100 | // TouchView is unfolded or not folded. 101 | @property (nonatomic, assign, readonly, getter=isUnfolded) BOOL unfolded; 102 | 103 | // TouchView images. 104 | @property (nonatomic, strong, nullable) DYFAssistiveTouchObject *touchObject; 105 | // TouchView unit. 106 | @property (nonatomic, strong, nullable) DYFAssistiveTouchUnit *unitObject; 107 | // TouchView items. 108 | @property (nonatomic, strong, nullable) NSArray *items; 109 | 110 | // TouchView item distance, default is 10.0. 111 | @property (nonatomic, assign) CGFloat distanceOfItem; 112 | // TouchView should show half or not. 113 | @property (nonatomic, assign) BOOL shouldShowHalf; 114 | // TouchView item index. 115 | @property (nonatomic, assign, readonly) NSInteger indexOfItem; 116 | 117 | /** 118 | * Set touchView begin location. 119 | * 120 | * @param place Begin location enum for touchView. 121 | */ 122 | - (void)setTouchViewPlace:(DYFTouchViewPlace)place; 123 | 124 | /** 125 | * TouchView has displayed. 126 | */ 127 | - (void)show; 128 | 129 | /** 130 | * TouchView has hidden. 131 | */ 132 | - (void)hide; 133 | 134 | /** 135 | * Set an block for touchView item which did clicked. 136 | * 137 | * @param block Executing after touchView item which did clicked. 138 | */ 139 | - (void)touchViewItemDidClickedAtIndex:(nullable DYFTouchViewItemDidClickedBlock)block; 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 如果能帮助到你,请你给[一颗星](https://github.com/itenfay/DYFAssistiveTouchView),谢谢!(If this can help you, please give it a [star](https://github.com/itenfay/DYFAssistiveTouchView), Thanks!) 2 | 3 | ## DYFAssistiveTouchView 4 | 5 | 实现应用内悬浮按钮和辅助工具条,可以增加/修改 Item 项,通过事件索引完成各种场景页面的跳转。 6 | 7 | [![License MIT](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](LICENSE)  8 | [![CocoaPods](http://img.shields.io/cocoapods/v/DYFAssistiveTouchView.svg?style=flat)](http://cocoapods.org/pods/DYFAssistiveTouchView)  9 | ![CocoaPods](http://img.shields.io/cocoapods/p/DYFAssistiveTouchView.svg?style=flat)  10 | 11 | ## Installation 12 | 13 | Using [CocoaPods](https://cocoapods.org): 14 | 15 | ``` 16 | pod 'DYFAssistiveTouchView' 17 | ``` 18 | 19 | Or 20 | 21 | ``` 22 | pod 'DYFAssistiveTouchView', '~> 4.3.1' 23 | ``` 24 | 25 | ## Group (ID:614799921) 26 | 27 |
28 |   29 |
30 | 31 | ## Priview 32 | 33 |
34 |   35 |
36 | 37 | ## Usage 38 | 39 | 1. 实例化 40 | 41 | ```ObjC 42 | // Lazy load 43 | - (DYFAssistiveTouchView *)touchView { 44 | if (!_touchView) { 45 | _touchView = [[DYFAssistiveTouchView alloc] init]; 46 | _touchView.frame = CGRectMake(0, 0, 50, 50); 47 | } 48 | return _touchView; 49 | } 50 | ``` 51 | 52 | 2. 设置属性 53 | 54 | - 设置悬浮按钮的各种状态的图片 55 | 56 | ```ObjC 57 | UIImage *leftHidenImage = [UIImage imageNamed:@"atv_hide_left"]; 58 | UIImage *rightHidenImage = leftHidenImage; 59 | UIImage *leftNormalImage = [UIImage imageNamed:@"atv_normal_left"]; 60 | UIImage *rightNormalImage = leftNormalImage; 61 | UIImage *leftHighlightedImage = [UIImage imageNamed:@"atv_normal_left"]; 62 | UIImage *rightHighlightedImage = leftHighlightedImage; 63 | 64 | self.touchView.touchObject.leftNormalImage = leftNormalImage; 65 | self.touchView.touchObject.rightNormalImage = rightNormalImage; 66 | self.touchView.touchObject.leftHighlightedImage = leftHighlightedImage; 67 | self.touchView.touchObject.rightHighlightedImage = rightHighlightedImage; 68 | self.touchView.touchObject.leftTranslucentImage = leftHidenImage; 69 | self.touchView.touchObject.rightTranslucentImage = rightHidenImage; 70 | ``` 71 | 72 | - 设置Unit对象 73 | 74 | ```ObjC 75 | UIImage *leftUint1Image = [UIImage imageNamed:@"atv_unit1_left"]; 76 | UIImage *rightUint1Image = [UIImage imageNamed:@"atv_unit1_right"]; 77 | UIImage *leftUint2Image = [UIImage imageNamed:@"atv_unit2_left"]; 78 | UIImage *rightUint2Image = [UIImage imageNamed:@"atv_unit2_right"]; 79 | 80 | self.touchView.unitObject.leftTouchImage = leftUint1Image; 81 | self.touchView.unitObject.rightTouchImage = rightUint1Image; 82 | self.touchView.unitObject.leftItemBackgroundImage = leftUint2Image; 83 | self.touchView.unitObject.rightItemBackgroundImage = rightUint2Image; 84 | ``` 85 | 86 | - 设置Item对象 87 | 88 | ```ObjC 89 | UIImage *userImage = [UIImage imageNamed:@"atv_item_user"]; 90 | UIImage *cafeImage = [UIImage imageNamed:@"atv_item_cafe"]; 91 | UIImage *csImage = [UIImage imageNamed:@"atv_item_cs"]; 92 | 93 | DYFAssistiveTouchItem *item = [[DYFAssistiveTouchItem alloc] init]; 94 | item.image = userImage; 95 | DYFAssistiveTouchItem *item1 = [[DYFAssistiveTouchItem alloc] init]; 96 | item1.image = cafeImage; 97 | DYFAssistiveTouchItem *item2 = [[DYFAssistiveTouchItem alloc] init]; 98 | item2.image = csImage; 99 | 100 | self.touchView.items = @[item, item1, item2]; 101 | ``` 102 | 103 | 3. 是否显示 104 | 105 | ```ObjC 106 | [self.touchView isShowing] 107 | ``` 108 | 109 | 4. 显示 110 | 111 | ```ObjC 112 | [self.touchView show]; 113 | ``` 114 | 115 | 5. 隐藏 116 | 117 | ```ObjC 118 | [self.touchView hide]; 119 | ``` 120 | 121 | 6. 隐藏一半至屏幕 122 | 123 | ```ObjC 124 | [self.touchView setShouldShowHalf:YES]; 125 | ``` 126 | 127 | 7. 设置初始显示位置 128 | 129 | ```ObjC 130 | [self.touchView setTouchViewPlace:DYFTouchViewAtMiddleRight]; 131 | ``` 132 | 133 | 8. 响应事件(二选一) 134 | 135 | ```ObjC 136 | - (void)presentAtIndex:(NSInteger)index { 137 | NSString *url = @"https://support.apple.com/zh-cn"; 138 | 139 | if (index == 0) { 140 | url = @"https://github.com/itenfay"; 141 | } 142 | else if (index == 1) { 143 | url = @"https://github.com/itenfay/Awesome"; 144 | } 145 | else { 146 | url = @"https://www.jianshu.com/u/7fc76f1179cc"; 147 | } 148 | 149 | SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:url]]; 150 | [self presentViewController:safariVC animated:YES completion:NULL]; 151 | } 152 | ``` 153 | 154 | - Block实现 155 | 156 | ```ObjC 157 | - (IBAction)configureAction:(id)sender { 158 | if (!_touchView) { 159 | [self configTouchViewDotImages]; 160 | [self configTouchViewUnits]; 161 | [self configTouchViewItems]; 162 | 163 | [self.touchView setShouldShowHalf:YES]; 164 | [self.touchView setTouchViewPlace:DYFTouchViewAtMiddleRight]; 165 | 166 | __weak typeof(self) weakSelf = self; 167 | [self.touchView touchViewItemDidClickedAtIndex:^(DYFAssistiveTouchView *touchView) { 168 | NSInteger index = touchView.indexOfItem; 169 | NSLog(@"Index of item: %zi", index); 170 | [weakSelf presentAtIndex:index]; 171 | }]; 172 | } 173 | } 174 | ``` 175 | 176 | - 代理实现 177 | 178 | ```ObjC 179 | // 协议 180 | Protocol: 181 | 182 | // 设置代理 183 | self.touchView.delegate = self; 184 | 185 | // 代理实现 186 | - (void)touchViewItemDidClickedAtIndex:(DYFAssistiveTouchView *)touchView { 187 | NSInteger index = touchView.indexOfItem; 188 | NSLog(@"Index of item: %zi", index); 189 | [self presentAtIndex:index]; 190 | } 191 | ``` 192 | 193 | ## Sample 194 | 195 | - [Code Sample Portal](https://github.com/itenfay/DYFAssistiveTouchView/blob/master/Basic%20Files/ViewController.m) 196 | -------------------------------------------------------------------------------- /Basic Files/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 | 43 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /DYFAssistiveTouchView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1490EF49227F663C001698ED /* DYFAssistiveTouchView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1490EF30227F663C001698ED /* DYFAssistiveTouchView.m */; }; 11 | 1490EF4A227F663C001698ED /* atv_normal_left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF34227F663C001698ED /* atv_normal_left@2x.png */; }; 12 | 1490EF4B227F663C001698ED /* atv_item_user@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF35227F663C001698ED /* atv_item_user@2x.png */; }; 13 | 1490EF4C227F663C001698ED /* atv_hide_right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF36227F663C001698ED /* atv_hide_right@2x.png */; }; 14 | 1490EF4D227F663C001698ED /* atv_item_cs@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF37227F663C001698ED /* atv_item_cs@2x.png */; }; 15 | 1490EF4E227F663C001698ED /* atv_item_cafe@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF38227F663C001698ED /* atv_item_cafe@2x.png */; }; 16 | 1490EF4F227F663C001698ED /* atv_unit1_right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF39227F663C001698ED /* atv_unit1_right@2x.png */; }; 17 | 1490EF50227F663C001698ED /* atv_unit2_left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF3A227F663C001698ED /* atv_unit2_left@2x.png */; }; 18 | 1490EF51227F663C001698ED /* atv_unit2_right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF3B227F663C001698ED /* atv_unit2_right@2x.png */; }; 19 | 1490EF52227F663C001698ED /* atv_unit1_left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF3C227F663C001698ED /* atv_unit1_left@2x.png */; }; 20 | 1490EF53227F663C001698ED /* atv_hide_left@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF3D227F663C001698ED /* atv_hide_left@2x.png */; }; 21 | 1490EF54227F663C001698ED /* atv_normal_right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF3E227F663C001698ED /* atv_normal_right@2x.png */; }; 22 | 1490EF55227F663C001698ED /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF3F227F663C001698ED /* Assets.xcassets */; }; 23 | 1490EF56227F663C001698ED /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1490EF40227F663C001698ED /* ViewController.m */; }; 24 | 1490EF57227F663C001698ED /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF41227F663C001698ED /* LaunchScreen.storyboard */; }; 25 | 1490EF58227F663C001698ED /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1490EF43227F663C001698ED /* Main.storyboard */; }; 26 | 1490EF59227F663C001698ED /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1490EF45227F663C001698ED /* main.m */; }; 27 | 1490EF5A227F663C001698ED /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1490EF46227F663C001698ED /* AppDelegate.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 1490EF2F227F663C001698ED /* DYFAssistiveTouchView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DYFAssistiveTouchView.h; sourceTree = ""; }; 32 | 1490EF30227F663C001698ED /* DYFAssistiveTouchView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DYFAssistiveTouchView.m; sourceTree = ""; }; 33 | 1490EF32227F663C001698ED /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 34 | 1490EF34227F663C001698ED /* atv_normal_left@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_normal_left@2x.png"; sourceTree = ""; }; 35 | 1490EF35227F663C001698ED /* atv_item_user@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_item_user@2x.png"; sourceTree = ""; }; 36 | 1490EF36227F663C001698ED /* atv_hide_right@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_hide_right@2x.png"; sourceTree = ""; }; 37 | 1490EF37227F663C001698ED /* atv_item_cs@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_item_cs@2x.png"; sourceTree = ""; }; 38 | 1490EF38227F663C001698ED /* atv_item_cafe@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_item_cafe@2x.png"; sourceTree = ""; }; 39 | 1490EF39227F663C001698ED /* atv_unit1_right@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_unit1_right@2x.png"; sourceTree = ""; }; 40 | 1490EF3A227F663C001698ED /* atv_unit2_left@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_unit2_left@2x.png"; sourceTree = ""; }; 41 | 1490EF3B227F663C001698ED /* atv_unit2_right@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_unit2_right@2x.png"; sourceTree = ""; }; 42 | 1490EF3C227F663C001698ED /* atv_unit1_left@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_unit1_left@2x.png"; sourceTree = ""; }; 43 | 1490EF3D227F663C001698ED /* atv_hide_left@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_hide_left@2x.png"; sourceTree = ""; }; 44 | 1490EF3E227F663C001698ED /* atv_normal_right@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "atv_normal_right@2x.png"; sourceTree = ""; }; 45 | 1490EF3F227F663C001698ED /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 46 | 1490EF40227F663C001698ED /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 47 | 1490EF42227F663C001698ED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 48 | 1490EF44227F663C001698ED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | 1490EF45227F663C001698ED /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 50 | 1490EF46227F663C001698ED /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 51 | 1490EF47227F663C001698ED /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 1490EF48227F663C001698ED /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 53 | 966884471D6C2C94002105A3 /* DYFAssistiveTouchView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DYFAssistiveTouchView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 966884441D6C2C94002105A3 /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | /* End PBXFrameworksBuildPhase section */ 65 | 66 | /* Begin PBXGroup section */ 67 | 1490EF2E227F663C001698ED /* Classes */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 1490EF2F227F663C001698ED /* DYFAssistiveTouchView.h */, 71 | 1490EF30227F663C001698ED /* DYFAssistiveTouchView.m */, 72 | ); 73 | path = Classes; 74 | sourceTree = ""; 75 | }; 76 | 1490EF31227F663C001698ED /* Basic Files */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 1490EF32227F663C001698ED /* AppDelegate.h */, 80 | 1490EF46227F663C001698ED /* AppDelegate.m */, 81 | 1490EF48227F663C001698ED /* ViewController.h */, 82 | 1490EF40227F663C001698ED /* ViewController.m */, 83 | 1490EF3F227F663C001698ED /* Assets.xcassets */, 84 | 1490EF43227F663C001698ED /* Main.storyboard */, 85 | 1490EF41227F663C001698ED /* LaunchScreen.storyboard */, 86 | 1490EF33227F663C001698ED /* Images */, 87 | 1490EF5C227F667E001698ED /* Supporting Files */, 88 | ); 89 | path = "Basic Files"; 90 | sourceTree = ""; 91 | }; 92 | 1490EF33227F663C001698ED /* Images */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 1490EF34227F663C001698ED /* atv_normal_left@2x.png */, 96 | 1490EF35227F663C001698ED /* atv_item_user@2x.png */, 97 | 1490EF36227F663C001698ED /* atv_hide_right@2x.png */, 98 | 1490EF37227F663C001698ED /* atv_item_cs@2x.png */, 99 | 1490EF38227F663C001698ED /* atv_item_cafe@2x.png */, 100 | 1490EF39227F663C001698ED /* atv_unit1_right@2x.png */, 101 | 1490EF3A227F663C001698ED /* atv_unit2_left@2x.png */, 102 | 1490EF3B227F663C001698ED /* atv_unit2_right@2x.png */, 103 | 1490EF3C227F663C001698ED /* atv_unit1_left@2x.png */, 104 | 1490EF3D227F663C001698ED /* atv_hide_left@2x.png */, 105 | 1490EF3E227F663C001698ED /* atv_normal_right@2x.png */, 106 | ); 107 | path = Images; 108 | sourceTree = ""; 109 | }; 110 | 1490EF5C227F667E001698ED /* Supporting Files */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 1490EF47227F663C001698ED /* Info.plist */, 114 | 1490EF45227F663C001698ED /* main.m */, 115 | ); 116 | path = "Supporting Files"; 117 | sourceTree = ""; 118 | }; 119 | 9668843E1D6C2C94002105A3 = { 120 | isa = PBXGroup; 121 | children = ( 122 | 1490EF2E227F663C001698ED /* Classes */, 123 | 1490EF31227F663C001698ED /* Basic Files */, 124 | 966884481D6C2C94002105A3 /* Products */, 125 | ); 126 | sourceTree = ""; 127 | }; 128 | 966884481D6C2C94002105A3 /* Products */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 966884471D6C2C94002105A3 /* DYFAssistiveTouchView.app */, 132 | ); 133 | name = Products; 134 | sourceTree = ""; 135 | }; 136 | /* End PBXGroup section */ 137 | 138 | /* Begin PBXNativeTarget section */ 139 | 966884461D6C2C94002105A3 /* DYFAssistiveTouchView */ = { 140 | isa = PBXNativeTarget; 141 | buildConfigurationList = 9668845E1D6C2C94002105A3 /* Build configuration list for PBXNativeTarget "DYFAssistiveTouchView" */; 142 | buildPhases = ( 143 | 966884431D6C2C94002105A3 /* Sources */, 144 | 966884441D6C2C94002105A3 /* Frameworks */, 145 | 966884451D6C2C94002105A3 /* Resources */, 146 | ); 147 | buildRules = ( 148 | ); 149 | dependencies = ( 150 | ); 151 | name = DYFAssistiveTouchView; 152 | productName = YFAssistiveTouch; 153 | productReference = 966884471D6C2C94002105A3 /* DYFAssistiveTouchView.app */; 154 | productType = "com.apple.product-type.application"; 155 | }; 156 | /* End PBXNativeTarget section */ 157 | 158 | /* Begin PBXProject section */ 159 | 9668843F1D6C2C94002105A3 /* Project object */ = { 160 | isa = PBXProject; 161 | attributes = { 162 | CLASSPREFIX = DYF; 163 | LastUpgradeCheck = 0720; 164 | ORGANIZATIONNAME = dyf; 165 | TargetAttributes = { 166 | 966884461D6C2C94002105A3 = { 167 | CreatedOnToolsVersion = 7.2.1; 168 | DevelopmentTeam = KCBQ48PTUV; 169 | ProvisioningStyle = Automatic; 170 | }; 171 | }; 172 | }; 173 | buildConfigurationList = 966884421D6C2C94002105A3 /* Build configuration list for PBXProject "DYFAssistiveTouchView" */; 174 | compatibilityVersion = "Xcode 3.2"; 175 | developmentRegion = English; 176 | hasScannedForEncodings = 0; 177 | knownRegions = ( 178 | English, 179 | en, 180 | Base, 181 | ); 182 | mainGroup = 9668843E1D6C2C94002105A3; 183 | productRefGroup = 966884481D6C2C94002105A3 /* Products */; 184 | projectDirPath = ""; 185 | projectRoot = ""; 186 | targets = ( 187 | 966884461D6C2C94002105A3 /* DYFAssistiveTouchView */, 188 | ); 189 | }; 190 | /* End PBXProject section */ 191 | 192 | /* Begin PBXResourcesBuildPhase section */ 193 | 966884451D6C2C94002105A3 /* Resources */ = { 194 | isa = PBXResourcesBuildPhase; 195 | buildActionMask = 2147483647; 196 | files = ( 197 | 1490EF4E227F663C001698ED /* atv_item_cafe@2x.png in Resources */, 198 | 1490EF4B227F663C001698ED /* atv_item_user@2x.png in Resources */, 199 | 1490EF4D227F663C001698ED /* atv_item_cs@2x.png in Resources */, 200 | 1490EF53227F663C001698ED /* atv_hide_left@2x.png in Resources */, 201 | 1490EF50227F663C001698ED /* atv_unit2_left@2x.png in Resources */, 202 | 1490EF51227F663C001698ED /* atv_unit2_right@2x.png in Resources */, 203 | 1490EF4A227F663C001698ED /* atv_normal_left@2x.png in Resources */, 204 | 1490EF58227F663C001698ED /* Main.storyboard in Resources */, 205 | 1490EF57227F663C001698ED /* LaunchScreen.storyboard in Resources */, 206 | 1490EF4C227F663C001698ED /* atv_hide_right@2x.png in Resources */, 207 | 1490EF4F227F663C001698ED /* atv_unit1_right@2x.png in Resources */, 208 | 1490EF52227F663C001698ED /* atv_unit1_left@2x.png in Resources */, 209 | 1490EF55227F663C001698ED /* Assets.xcassets in Resources */, 210 | 1490EF54227F663C001698ED /* atv_normal_right@2x.png in Resources */, 211 | ); 212 | runOnlyForDeploymentPostprocessing = 0; 213 | }; 214 | /* End PBXResourcesBuildPhase section */ 215 | 216 | /* Begin PBXSourcesBuildPhase section */ 217 | 966884431D6C2C94002105A3 /* Sources */ = { 218 | isa = PBXSourcesBuildPhase; 219 | buildActionMask = 2147483647; 220 | files = ( 221 | 1490EF5A227F663C001698ED /* AppDelegate.m in Sources */, 222 | 1490EF56227F663C001698ED /* ViewController.m in Sources */, 223 | 1490EF59227F663C001698ED /* main.m in Sources */, 224 | 1490EF49227F663C001698ED /* DYFAssistiveTouchView.m in Sources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | /* End PBXSourcesBuildPhase section */ 229 | 230 | /* Begin PBXVariantGroup section */ 231 | 1490EF41227F663C001698ED /* LaunchScreen.storyboard */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | 1490EF42227F663C001698ED /* Base */, 235 | ); 236 | name = LaunchScreen.storyboard; 237 | sourceTree = ""; 238 | }; 239 | 1490EF43227F663C001698ED /* Main.storyboard */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | 1490EF44227F663C001698ED /* Base */, 243 | ); 244 | name = Main.storyboard; 245 | sourceTree = ""; 246 | }; 247 | /* End PBXVariantGroup section */ 248 | 249 | /* Begin XCBuildConfiguration section */ 250 | 9668845C1D6C2C94002105A3 /* Debug */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 255 | CLANG_CXX_LIBRARY = "libc++"; 256 | CLANG_ENABLE_MODULES = YES; 257 | CLANG_ENABLE_OBJC_ARC = YES; 258 | CLANG_WARN_BOOL_CONVERSION = YES; 259 | CLANG_WARN_CONSTANT_CONVERSION = YES; 260 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 261 | CLANG_WARN_EMPTY_BODY = YES; 262 | CLANG_WARN_ENUM_CONVERSION = YES; 263 | CLANG_WARN_INT_CONVERSION = YES; 264 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 265 | CLANG_WARN_UNREACHABLE_CODE = YES; 266 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 267 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 268 | COPY_PHASE_STRIP = NO; 269 | DEBUG_INFORMATION_FORMAT = dwarf; 270 | ENABLE_STRICT_OBJC_MSGSEND = YES; 271 | ENABLE_TESTABILITY = YES; 272 | GCC_C_LANGUAGE_STANDARD = gnu99; 273 | GCC_DYNAMIC_NO_PIC = NO; 274 | GCC_NO_COMMON_BLOCKS = YES; 275 | GCC_OPTIMIZATION_LEVEL = 0; 276 | GCC_PREPROCESSOR_DEFINITIONS = ( 277 | "DEBUG=1", 278 | "$(inherited)", 279 | ); 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 282 | GCC_WARN_UNDECLARED_SELECTOR = YES; 283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 284 | GCC_WARN_UNUSED_FUNCTION = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 287 | MTL_ENABLE_DEBUG_INFO = YES; 288 | ONLY_ACTIVE_ARCH = YES; 289 | SDKROOT = iphoneos; 290 | TARGETED_DEVICE_FAMILY = "1,2"; 291 | }; 292 | name = Debug; 293 | }; 294 | 9668845D1D6C2C94002105A3 /* Release */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ALWAYS_SEARCH_USER_PATHS = NO; 298 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 299 | CLANG_CXX_LIBRARY = "libc++"; 300 | CLANG_ENABLE_MODULES = YES; 301 | CLANG_ENABLE_OBJC_ARC = YES; 302 | CLANG_WARN_BOOL_CONVERSION = YES; 303 | CLANG_WARN_CONSTANT_CONVERSION = YES; 304 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 305 | CLANG_WARN_EMPTY_BODY = YES; 306 | CLANG_WARN_ENUM_CONVERSION = YES; 307 | CLANG_WARN_INT_CONVERSION = YES; 308 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 309 | CLANG_WARN_UNREACHABLE_CODE = YES; 310 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 311 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 312 | COPY_PHASE_STRIP = NO; 313 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 314 | ENABLE_NS_ASSERTIONS = NO; 315 | ENABLE_STRICT_OBJC_MSGSEND = YES; 316 | GCC_C_LANGUAGE_STANDARD = gnu99; 317 | GCC_NO_COMMON_BLOCKS = YES; 318 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 319 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 320 | GCC_WARN_UNDECLARED_SELECTOR = YES; 321 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 322 | GCC_WARN_UNUSED_FUNCTION = YES; 323 | GCC_WARN_UNUSED_VARIABLE = YES; 324 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 325 | MTL_ENABLE_DEBUG_INFO = NO; 326 | SDKROOT = iphoneos; 327 | TARGETED_DEVICE_FAMILY = "1,2"; 328 | VALIDATE_PRODUCT = YES; 329 | }; 330 | name = Release; 331 | }; 332 | 9668845F1D6C2C94002105A3 /* Debug */ = { 333 | isa = XCBuildConfiguration; 334 | buildSettings = { 335 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 336 | CODE_SIGN_IDENTITY = "iPhone Developer"; 337 | CODE_SIGN_STYLE = Automatic; 338 | CURRENT_PROJECT_VERSION = 2; 339 | DEVELOPMENT_TEAM = KCBQ48PTUV; 340 | INFOPLIST_FILE = "$(SRCROOT)/Basic Files/Supporting Files/Info.plist"; 341 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 342 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 343 | MARKETING_VERSION = 4.3.1; 344 | PRODUCT_BUNDLE_IDENTIFIER = com.asd.assistivetouchview; 345 | PRODUCT_NAME = DYFAssistiveTouchView; 346 | PROVISIONING_PROFILE = ""; 347 | PROVISIONING_PROFILE_SPECIFIER = ""; 348 | }; 349 | name = Debug; 350 | }; 351 | 966884601D6C2C94002105A3 /* Release */ = { 352 | isa = XCBuildConfiguration; 353 | buildSettings = { 354 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 355 | CODE_SIGN_IDENTITY = "iPhone Developer"; 356 | CODE_SIGN_STYLE = Automatic; 357 | CURRENT_PROJECT_VERSION = 2; 358 | DEVELOPMENT_TEAM = KCBQ48PTUV; 359 | INFOPLIST_FILE = "$(SRCROOT)/Basic Files/Supporting Files/Info.plist"; 360 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 361 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 362 | MARKETING_VERSION = 4.3.1; 363 | PRODUCT_BUNDLE_IDENTIFIER = com.asd.assistivetouchview; 364 | PRODUCT_NAME = DYFAssistiveTouchView; 365 | PROVISIONING_PROFILE = ""; 366 | PROVISIONING_PROFILE_SPECIFIER = ""; 367 | }; 368 | name = Release; 369 | }; 370 | /* End XCBuildConfiguration section */ 371 | 372 | /* Begin XCConfigurationList section */ 373 | 966884421D6C2C94002105A3 /* Build configuration list for PBXProject "DYFAssistiveTouchView" */ = { 374 | isa = XCConfigurationList; 375 | buildConfigurations = ( 376 | 9668845C1D6C2C94002105A3 /* Debug */, 377 | 9668845D1D6C2C94002105A3 /* Release */, 378 | ); 379 | defaultConfigurationIsVisible = 0; 380 | defaultConfigurationName = Release; 381 | }; 382 | 9668845E1D6C2C94002105A3 /* Build configuration list for PBXNativeTarget "DYFAssistiveTouchView" */ = { 383 | isa = XCConfigurationList; 384 | buildConfigurations = ( 385 | 9668845F1D6C2C94002105A3 /* Debug */, 386 | 966884601D6C2C94002105A3 /* Release */, 387 | ); 388 | defaultConfigurationIsVisible = 0; 389 | defaultConfigurationName = Release; 390 | }; 391 | /* End XCConfigurationList section */ 392 | }; 393 | rootObject = 9668843F1D6C2C94002105A3 /* Project object */; 394 | } 395 | -------------------------------------------------------------------------------- /Classes/DYFAssistiveTouchView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DYFAssistiveTouchView.m 3 | // 4 | // Created by Tenfay on 14/10/31. 5 | // Copyright (c) 2014 Tenfay. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | #import 27 | #import "DYFAssistiveTouchView.h" 28 | 29 | #pragma mark - macros 30 | 31 | #define ScreenW [UIScreen mainScreen].bounds.size.width 32 | #define ScreenH [UIScreen mainScreen].bounds.size.height 33 | #define SharedApp [UIApplication sharedApplication] 34 | #define IsPortrait(ori) UIInterfaceOrientationIsPortrait(ori) 35 | 36 | #pragma mark - category 37 | 38 | @interface UIView (ATVEasyFrame) 39 | @property (nonatomic, assign) CGFloat x; 40 | @property (nonatomic, assign) CGFloat y; 41 | @property (nonatomic, assign) CGFloat width; 42 | @property (nonatomic, assign) CGFloat height; 43 | @property (nonatomic, assign) CGSize size; 44 | @property (nonatomic, assign) CGFloat centerX; 45 | @property (nonatomic, assign) CGFloat centerY; 46 | @end 47 | 48 | @implementation UIView (ATVEasyFrame) 49 | @dynamic x; 50 | @dynamic y; 51 | @dynamic width; 52 | @dynamic height; 53 | @dynamic size; 54 | @dynamic centerX; 55 | @dynamic centerY; 56 | 57 | - (void)setX:(CGFloat)x { 58 | CGRect frame = self.frame; 59 | frame.origin.x = x; 60 | self.frame= frame; 61 | } 62 | 63 | - (CGFloat)x { 64 | return self.frame.origin.x; 65 | } 66 | 67 | - (void)setY:(CGFloat)y { 68 | CGRect frame = self.frame; 69 | frame.origin.y = y; 70 | self.frame= frame; 71 | } 72 | 73 | - (CGFloat)y { 74 | return self.frame.origin.y; 75 | } 76 | 77 | - (void)setWidth:(CGFloat)width { 78 | CGRect frame = self.frame; 79 | frame.size.width = width; 80 | self.frame= frame; 81 | } 82 | 83 | - (CGFloat)width { 84 | return self.frame.size.width; 85 | } 86 | 87 | - (void)setHeight:(CGFloat)height { 88 | CGRect frame = self.frame; 89 | frame.size.height = height; 90 | self.frame= frame; 91 | } 92 | 93 | - (CGFloat)height { 94 | return self.frame.size.height; 95 | } 96 | 97 | - (void)setSize:(CGSize)size { 98 | CGRect frame = self.frame; 99 | frame.size = size; 100 | self.frame= frame; 101 | } 102 | 103 | - (CGSize)size { 104 | return self.frame.size; 105 | } 106 | 107 | - (void)setCenterX:(CGFloat)centerX { 108 | CGPoint point = self.center; 109 | point.x = centerX; 110 | self.center = point; 111 | } 112 | 113 | - (CGFloat)centerX { 114 | return self.center.x; 115 | } 116 | 117 | - (void)setCenterY:(CGFloat)centerY { 118 | CGPoint point = self.center; 119 | point.y = centerY; 120 | self.center = point; 121 | } 122 | 123 | - (CGFloat)centerY { 124 | return self.center.y; 125 | } 126 | @end 127 | 128 | @implementation DYFAssistiveTouchObject 129 | 130 | @end 131 | 132 | @implementation DYFAssistiveTouchUnit 133 | 134 | @end 135 | 136 | @implementation DYFAssistiveTouchItem 137 | 138 | @end 139 | 140 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 141 | @interface DYFAssistiveTouchView () 142 | #else 143 | @interface DYFAssistiveTouchView () 144 | #endif 145 | @property (nonatomic, assign) BOOL shouldIndentHalf; 146 | @property (nonatomic, assign) CGPoint beginPoint; 147 | @property (nonatomic, strong) UIImageView *imageView; 148 | @property (nonatomic, strong) UIView *toolBar; 149 | @property (nonatomic, copy ) DYFTouchViewItemDidClickedBlock itemDidClickedBlock; 150 | @end 151 | 152 | @implementation DYFAssistiveTouchView 153 | 154 | - (void)dealloc { 155 | [self unregisterOrientationObserver]; 156 | } 157 | 158 | - (id)initWithFrame:(CGRect)frame { 159 | self = [super initWithFrame:frame]; 160 | if (self) { 161 | [self setup]; 162 | [self addGesture]; 163 | [self registerOrientationObserver]; 164 | } 165 | return self; 166 | } 167 | 168 | - (void)setup { 169 | [self setUserInteractionEnabled:YES]; 170 | [self setBackgroundColor:[UIColor clearColor]]; 171 | 172 | [self setShowing:NO]; 173 | [self setMoving:NO]; 174 | [self setUnfolded:NO]; 175 | [self setDistanceOfItem:10.f]; 176 | 177 | [self layoutAfterDelay]; 178 | 179 | _touchObject = [[DYFAssistiveTouchObject alloc] init]; 180 | _unitObject = [[DYFAssistiveTouchUnit alloc] init]; 181 | } 182 | 183 | - (void)addGesture { 184 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init]; 185 | [tap addTarget:self action:@selector(tapGestureAction:)]; 186 | [self addGestureRecognizer:tap]; 187 | } 188 | 189 | - (void)unregisterOrientationObserver { 190 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; 191 | } 192 | 193 | - (void)registerOrientationObserver { 194 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationDidChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; 195 | } 196 | 197 | - (UIInterfaceOrientation)uiOrientation { 198 | return SharedApp.statusBarOrientation; 199 | } 200 | 201 | - (BOOL)iOS8OrNewer { 202 | return ([UIDevice currentDevice].systemVersion.doubleValue >= 8.0); 203 | } 204 | 205 | - (UIView *)mainView { 206 | UIViewController *vc = SharedApp.windows[0].rootViewController; 207 | while (vc.presentedViewController) { 208 | vc = vc.presentedViewController; 209 | } 210 | return vc.view; 211 | } 212 | 213 | - (void)makeHidden:(BOOL)hidden { 214 | [self setHidden:hidden]; 215 | } 216 | 217 | - (void)layoutAfterDelay { 218 | [self performSelector:@selector(layoutViews) withObject:nil afterDelay:1.f]; 219 | } 220 | 221 | - (void)layoutViews { 222 | [self setupImageView]; 223 | [self addToSuperview]; 224 | [self setAlpha:0.f]; 225 | } 226 | 227 | - (void)addToSuperview { 228 | UIView *view = [self mainView]; 229 | [view addSubview:self]; 230 | } 231 | 232 | - (void)sendToFront { 233 | if (self.superview) { 234 | [self.superview bringSubviewToFront:self]; 235 | } 236 | } 237 | 238 | - (void)setupImageView { 239 | _imageView = [[UIImageView alloc] init]; 240 | _imageView.backgroundColor = [UIColor clearColor]; 241 | _imageView.x = 0.f; 242 | _imageView.y = 0.f; 243 | _imageView.size = self.size; 244 | [self addSubview:_imageView]; 245 | } 246 | 247 | - (void)show { 248 | [self setAlpha:0.f]; 249 | 250 | [UIView animateWithDuration:0.5f animations:^{ 251 | [self setAlpha:1.f]; 252 | } completion:^(BOOL finished) { 253 | [self setShowing:YES]; 254 | [self setTouchViewNormalState]; 255 | [self setTouchViewNormalImage]; 256 | [self makeTouchViewTranslucentAfterDelay]; 257 | }]; 258 | 259 | [self makeHidden:NO]; 260 | } 261 | 262 | - (void)hide { 263 | [UIView animateWithDuration:0.5f animations:^{ 264 | [self setAlpha:0.f]; 265 | } completion:^(BOOL finished) { 266 | [self setShowing:NO]; 267 | [self makeHidden:YES]; 268 | if (self.isUnfolded) { 269 | [self setUnfolded:NO]; 270 | } 271 | [self removeToolBar]; 272 | }]; 273 | 274 | [self cancelMakeTouchViewTranslucentRequest]; 275 | } 276 | 277 | - (void)setTouchViewPlace:(DYFTouchViewPlace)place { 278 | switch (place) { 279 | case DYFTouchViewAtTopLeft: 280 | [self setTouchViewLocationWithPlace:DYFTouchViewAtTopLeft]; 281 | break; 282 | case DYFTouchViewAtTopRight: 283 | [self setTouchViewLocationWithPlace:DYFTouchViewAtTopRight]; 284 | break; 285 | case DYFTouchViewAtBottomLeft: 286 | [self setTouchViewLocationWithPlace:DYFTouchViewAtBottomLeft]; 287 | break; 288 | case DYFTouchViewAtBottomRight: 289 | [self setTouchViewLocationWithPlace:DYFTouchViewAtBottomRight]; 290 | break; 291 | case DYFTouchViewAtMiddleRight: 292 | [self setTouchViewLocationWithPlace:DYFTouchViewAtMiddleRight]; 293 | break; 294 | default: 295 | case DYFTouchViewAtMiddleLeft: 296 | [self setTouchViewLocationWithPlace:DYFTouchViewAtMiddleLeft]; 297 | break; 298 | } 299 | } 300 | 301 | - (void)setTouchViewLocationWithPlace:(DYFTouchViewPlace)place { 302 | CGFloat width = 0; 303 | CGFloat height = 0; 304 | 305 | if (IsPortrait([self uiOrientation]) || [self iOS8OrNewer]) { 306 | width = ScreenW; 307 | height = ScreenH; 308 | } else { 309 | width = ScreenH; 310 | height = ScreenW; 311 | } 312 | 313 | if (place == DYFTouchViewAtTopLeft) { 314 | self.x = 0; 315 | self.y = 0; 316 | } else if (place == DYFTouchViewAtTopRight) { 317 | self.x = width - self.width; 318 | self.y = 0; 319 | } else if (place == DYFTouchViewAtMiddleLeft) { 320 | self.x = 0; 321 | self.centerY = height/2; 322 | } else if (place == DYFTouchViewAtMiddleRight) { 323 | self.x = width - self.width; 324 | self.centerY = height/2; 325 | } else if (place == DYFTouchViewAtBottomLeft) { 326 | self.x = 0; 327 | self.y = height; 328 | } else { 329 | self.x = width - self.width; 330 | self.y = height; 331 | } 332 | } 333 | 334 | - (void)touchViewItemDidClickedAtIndex:(DYFTouchViewItemDidClickedBlock)block { 335 | self.itemDidClickedBlock = block; 336 | } 337 | 338 | - (void)tapGestureAction:(UITapGestureRecognizer *)gesture { 339 | [self handleUIResponds]; 340 | } 341 | 342 | - (void)setTouchViewNormalImage { 343 | if ([self touchViewAtRight]) { 344 | _imageView.image = _touchObject.rightNormalImage; 345 | } else { 346 | _imageView.image = _touchObject.leftNormalImage; 347 | } 348 | } 349 | 350 | - (void)setTouchViewHighlightedImage { 351 | if ([self touchViewAtRight]) { 352 | if (_touchObject.rightHighlightedImage) { 353 | _imageView.highlightedImage = _touchObject.rightHighlightedImage; 354 | } 355 | } else { 356 | if (_touchObject.leftHighlightedImage) { 357 | _imageView.highlightedImage = _touchObject.leftHighlightedImage; 358 | } 359 | } 360 | } 361 | 362 | - (void)setTouchViewTranslucentImage { 363 | if ([self touchViewAtRight]) { 364 | if (_touchObject.rightTranslucentImage) { 365 | _imageView.image = _touchObject.rightTranslucentImage; 366 | } 367 | } else { 368 | if (_touchObject.leftTranslucentImage) { 369 | _imageView.image = _touchObject.leftTranslucentImage; 370 | } 371 | } 372 | } 373 | 374 | - (void)setTouchViewNormalState { 375 | _imageView.highlighted = NO; 376 | } 377 | 378 | - (void)setTouchViewHighlightedState { 379 | _imageView.highlighted = YES; 380 | } 381 | 382 | - (void)handleUIResponds { 383 | if (self.isUnfolded) { 384 | [self foldToolBar]; 385 | } else { 386 | [self unfoldToolBar]; 387 | } 388 | } 389 | 390 | - (void)makeTouchViewTranslucentAfterDelay { 391 | if (!self.isUnfolded && !self.isMoving) { 392 | [self performSelector:@selector(makeTouchViewTranslucent) withObject:nil afterDelay:8.f]; 393 | } 394 | } 395 | 396 | - (void)cancelMakeTouchViewTranslucentRequest { 397 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(makeTouchViewTranslucent) object:nil]; 398 | } 399 | 400 | - (void)makeTouchViewTranslucent { 401 | [self setTouchViewTranslucentImage]; 402 | [self sendToFront]; 403 | if (self.shouldShowHalf) { 404 | [UIView animateWithDuration:0.5f animations:^{ 405 | [self updateTouchViewLayout:YES]; 406 | }]; 407 | } 408 | } 409 | 410 | - (void)unfoldToolBar { 411 | if (![self isMoving]) { 412 | [self makeHidden:YES]; 413 | [self setUnfolded:YES]; 414 | [self setupToolBar]; 415 | [self showToolBarWithAnimation]; 416 | } 417 | } 418 | 419 | - (void)foldToolBar { 420 | [self setUnfolded:NO]; 421 | [self makeToolBarHidden:YES]; 422 | [self hideToolBarWithAnimation]; 423 | } 424 | 425 | - (void)setupToolBar { 426 | UIView *view = [self mainView]; 427 | 428 | _toolBar = [[UIView alloc] init]; 429 | _toolBar.backgroundColor = [UIColor clearColor]; 430 | _toolBar.userInteractionEnabled = YES; 431 | _toolBar.height = self.height; 432 | 433 | [view addSubview:_toolBar]; 434 | 435 | [self addToolBarUnits]; 436 | } 437 | 438 | - (void)makeToolBarHidden:(BOOL)hidden { 439 | [_toolBar setHidden:YES]; 440 | } 441 | 442 | - (UIImage *)tbTouchImage { 443 | if ([self touchViewAtRight]) { 444 | return _unitObject.rightTouchImage; 445 | } 446 | return _unitObject.leftTouchImage; 447 | } 448 | 449 | - (UIImage *)tbItemBackgroundImage { 450 | if ([self touchViewAtRight]) { 451 | UIImage *rightItemBackgroundImage = _unitObject.rightItemBackgroundImage; 452 | UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 30, 0, 10); 453 | rightItemBackgroundImage = [rightItemBackgroundImage resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeStretch]; 454 | return rightItemBackgroundImage; 455 | } else { 456 | UIImage *leftItemBackgroundImage = _unitObject.leftItemBackgroundImage; 457 | UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 10, 0, 30); 458 | leftItemBackgroundImage = [leftItemBackgroundImage resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeStretch]; 459 | return leftItemBackgroundImage; 460 | } 461 | } 462 | 463 | - (void)addToolBarUnits { 464 | CGFloat length = (self.items.count + 1)*self.distanceOfItem + 20; 465 | 466 | for (int idx = 0; idx < self.items.count; idx++) { 467 | DYFAssistiveTouchItem *item = [self.items objectAtIndex:idx]; 468 | length += item.image.size.width; 469 | } 470 | 471 | UIImage *touchImage = [self tbTouchImage]; 472 | [_toolBar setWidth:touchImage.size.width + length]; 473 | 474 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 475 | button.showsTouchWhenHighlighted = YES; 476 | button.adjustsImageWhenHighlighted = NO; 477 | if ([self touchViewAtRight]) { 478 | button.x = length; 479 | } else { 480 | button.x = 0; 481 | } 482 | button.y = 0; 483 | button.width = touchImage.size.width; 484 | button.height = touchImage.size.height; 485 | if (touchImage) { 486 | [button setImage:touchImage forState:UIControlStateNormal]; 487 | } 488 | [button addTarget:self action:@selector(touchButtonDidClicked:) forControlEvents:UIControlEventTouchUpInside]; 489 | [_toolBar addSubview:button]; 490 | 491 | UIImage *itemBackgroundImage = [self tbItemBackgroundImage]; 492 | UIImageView *itemBackgroundImageView = [[UIImageView alloc] init]; 493 | itemBackgroundImageView.userInteractionEnabled = YES; 494 | itemBackgroundImageView.image = itemBackgroundImage; 495 | if ([self touchViewAtRight]) { 496 | itemBackgroundImageView.x = 0; 497 | } else { 498 | itemBackgroundImageView.x = touchImage.size.width; 499 | } 500 | itemBackgroundImageView.y = (touchImage.size.height - itemBackgroundImage.size.height)/2; 501 | itemBackgroundImageView.width = length; 502 | itemBackgroundImageView.height = itemBackgroundImage.size.height; 503 | [_toolBar addSubview:itemBackgroundImageView]; 504 | 505 | [self addToolBarItems:itemBackgroundImageView]; 506 | } 507 | 508 | - (void)addToolBarItems:(UIImageView *)itemBackgroundImageView { 509 | CGFloat width = itemBackgroundImageView.width; 510 | CGFloat height = itemBackgroundImageView.height; 511 | 512 | for (int i = 0; i < self.items.count; i++) { 513 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 514 | DYFAssistiveTouchItem *item = [self.items objectAtIndex:i]; 515 | CGSize itemSize = item.image.size; 516 | if ([self touchViewAtRight]) { 517 | button.x = width - (i + 1)*(itemSize.width + self.distanceOfItem); 518 | } else { 519 | button.x = self.distanceOfItem + i*(self.distanceOfItem + itemSize.width); 520 | } 521 | button.y = (height- itemSize.height)/2; 522 | button.width = itemSize.width; 523 | button.height = itemSize.height; 524 | if (item.image) { 525 | [button setImage:item.image forState:UIControlStateNormal]; 526 | } 527 | if (item.highlightedImage) { 528 | [button setImage:item.highlightedImage forState:UIControlStateHighlighted]; 529 | } 530 | [button setTag:i + 100]; 531 | [button addTarget:self action:@selector(toolBarItemAction:) forControlEvents:UIControlEventTouchUpInside]; 532 | [itemBackgroundImageView addSubview:button]; 533 | } 534 | 535 | [self updateToolBarOrigin]; 536 | } 537 | 538 | - (void)updateToolBarOrigin { 539 | if ([self touchViewAtRight]) { 540 | if (self.shouldShowHalf && self.shouldIndentHalf) { 541 | _toolBar.x = self.x - _toolBar.width + self.width/2; 542 | } else { 543 | _toolBar.x = self.x - _toolBar.width + self.width; 544 | } 545 | _toolBar.y = self.y; 546 | } else { 547 | if (self.shouldShowHalf && self.shouldIndentHalf) { 548 | _toolBar.x = self.x + self.width/2; 549 | } else { 550 | _toolBar.x = self.x; 551 | } 552 | _toolBar.y = self.y; 553 | } 554 | } 555 | 556 | - (void)showToolBarWithAnimation { 557 | if ([self touchViewAtRight]) { 558 | [self setToolBarAnimationWithType:kCATransitionPush subtype:kCATransitionFromRight]; 559 | } else { 560 | [self setToolBarAnimationWithType:kCATransitionPush subtype:kCATransitionFromLeft]; 561 | } 562 | } 563 | 564 | - (void)hideToolBarWithAnimation { 565 | if ([self touchViewAtRight]) { 566 | [self setToolBarAnimationWithType:kCATransitionPush subtype:kCATransitionFromLeft]; 567 | } else { 568 | [self setToolBarAnimationWithType:kCATransitionPush subtype:kCATransitionFromRight]; 569 | } 570 | } 571 | 572 | - (BOOL)touchViewAtRight { 573 | BOOL isAtRight = NO; 574 | if (IsPortrait([self uiOrientation]) || [self iOS8OrNewer]) { 575 | if (self.centerX < ScreenW/2) { 576 | isAtRight = NO; 577 | } else { 578 | isAtRight = YES; 579 | } 580 | } else { 581 | if (self.centerX < ScreenH/2) { 582 | isAtRight = NO; 583 | } else { 584 | isAtRight = YES; 585 | } 586 | } 587 | return isAtRight; 588 | } 589 | 590 | #pragma mark - 按钮触发事件 591 | 592 | - (void)touchButtonDidClicked:(UIButton *)sender { 593 | [self handleUIResponds]; 594 | } 595 | 596 | - (void)toolBarItemAction:(UIButton *)sender { 597 | [self handleUIResponds]; 598 | _indexOfItem = sender.tag - 100; 599 | if ([self.delegate respondsToSelector:@selector(touchViewItemDidClickedAtIndex:)]) { 600 | [self.delegate touchViewItemDidClickedAtIndex:self]; 601 | } 602 | if (self.itemDidClickedBlock) { 603 | self.itemDidClickedBlock(self); 604 | } 605 | } 606 | 607 | #pragma mark - Touches 608 | 609 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 610 | [self cancelMakeTouchViewTranslucentRequest]; 611 | UITouch *touch = [touches anyObject]; 612 | _beginPoint = [touch locationInView:self]; 613 | } 614 | 615 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 616 | if (self.isUnfolded) return; 617 | 618 | [self setMoving:YES]; 619 | 620 | UITouch *touch = [touches anyObject]; 621 | CGPoint location = [touch locationInView:self]; 622 | 623 | CGFloat dx = location.x - _beginPoint.x; 624 | CGFloat dy = location.y - _beginPoint.y; 625 | 626 | self.centerX = self.centerX + dx; 627 | self.centerY = self.centerY + dy; 628 | 629 | [self setTouchViewHighlightedState]; 630 | [self setTouchViewHighlightedImage]; 631 | } 632 | 633 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 634 | [self setTouchViewNormalState]; 635 | [self setTouchViewNormalImage]; 636 | [self makeTouchViewLocateScreenEdgeWithAnimation]; 637 | } 638 | 639 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { 640 | [self setTouchViewNormalState]; 641 | [self setTouchViewNormalImage]; 642 | [self makeTouchViewLocateScreenEdgeWithAnimation]; 643 | } 644 | 645 | - (void)updateTouchViewLayout:(BOOL)setNeedsIndentHalf { 646 | [self setShouldIndentHalf:setNeedsIndentHalf]; 647 | 648 | CGFloat dw = 0; 649 | CGFloat dh = 0; 650 | if (IsPortrait([self uiOrientation]) || [self iOS8OrNewer]) { 651 | dw = ScreenW; 652 | dh = ScreenH; 653 | } else { 654 | dw = ScreenH; 655 | dh = ScreenW; 656 | } 657 | 658 | CGFloat left = self.width/2; 659 | CGFloat top = self.height/2; 660 | 661 | if (self.centerX > dw/2) { 662 | self.centerX = (self.shouldShowHalf && self.shouldIndentHalf)? dw: (dw - left); 663 | if (self.centerY > dh - top) { 664 | self.centerY = dh - top; 665 | } 666 | if (self.centerY < top) { 667 | self.centerY = top; 668 | } 669 | } else { 670 | self.centerX = (self.shouldShowHalf && self.shouldIndentHalf)? 0: left; 671 | if (self.centerY > dh - top) { 672 | self.centerY = dh - top; 673 | } 674 | if (self.centerY < top) { 675 | self.centerY = top; 676 | } 677 | } 678 | } 679 | 680 | - (void)makeTouchViewLocateScreenEdgeWithAnimation { 681 | [UIView animateWithDuration:0.3f animations:^{ 682 | [self updateTouchViewLayout:NO]; 683 | } completion:^(BOOL finished) { 684 | [self setMoving:NO]; 685 | [self makeTouchViewTranslucentAfterDelay]; 686 | }]; 687 | } 688 | 689 | - (void)removeToolBar { 690 | if (self.toolBar) { 691 | [self.toolBar removeFromSuperview]; 692 | self.toolBar = nil; 693 | } 694 | } 695 | 696 | - (void)statusBarOrientationDidChange:(NSNotification *)noti { 697 | [self updateLayout]; 698 | [self cancelMakeTouchViewTranslucentRequest]; 699 | } 700 | 701 | - (void)updateLayout { 702 | [self setNeedsLayout]; 703 | } 704 | 705 | - (void)layoutSubviews { 706 | if (self.isUnfolded) { 707 | [self removeToolBar]; 708 | [self setUnfolded:NO]; 709 | } 710 | [self makeHidden:NO]; 711 | [self setTouchViewNormalState]; 712 | [self setTouchViewNormalImage]; 713 | [self makeTouchViewLocateScreenEdgeWithAnimation]; 714 | } 715 | 716 | - (void)setShowing:(BOOL)showing { 717 | _showing = showing; 718 | } 719 | 720 | - (void)setMoving:(BOOL)moving { 721 | _moving = moving; 722 | } 723 | 724 | - (void)setUnfolded:(BOOL)unfolded { 725 | _unfolded = unfolded; 726 | } 727 | 728 | - (void)setToolBarAnimationWithType:(NSString *)type subtype:(NSString *)subtype { 729 | if (self.toolBar) { 730 | CATransition *animation = [CATransition animation]; 731 | animation.duration = 0.3f; 732 | animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 733 | animation.type = type; 734 | animation.subtype = subtype; 735 | animation.delegate = self; 736 | [self.toolBar.layer addAnimation:animation forKey:@"atvanimation"]; 737 | } 738 | } 739 | 740 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 741 | if (flag) { 742 | if (self.toolBar) { 743 | [self.toolBar.layer removeAnimationForKey:@"atvanimation"]; 744 | } 745 | 746 | if (![self isUnfolded]) { 747 | [self removeToolBar]; 748 | [self setTouchViewNormalState]; 749 | [self setTouchViewNormalImage]; 750 | [self makeHidden:NO]; 751 | 752 | [self setAlpha:0.f]; 753 | [UIView animateWithDuration:0.5f delay:0.3f options:UIViewAnimationOptionCurveEaseInOut animations:^{ 754 | [self setAlpha:1.f]; 755 | } completion:^(BOOL finished) { 756 | [self makeTouchViewTranslucentAfterDelay]; 757 | }]; 758 | } 759 | } 760 | } 761 | 762 | @end 763 | --------------------------------------------------------------------------------