mirror of
https://github.com/joeblau/COSTouchVisualizer.git
synced 2024-08-16 07:50:24 +03:00
Refactor code to modern obj-c
This commit is contained in:
parent
ad729c993d
commit
b00850925c
15
Classes/COSOverlayVisualizerWindow.h
Normal file
15
Classes/COSOverlayVisualizerWindow.h
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// COSOverlayVisualizerWindow.h
|
||||
// COSTouchVisualizer
|
||||
//
|
||||
// Created by Joseph Blau on 11/30/17.
|
||||
// Copyright © 2017 conopsys. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface COSOverlayVisualizerWindow : UIWindow
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
|
||||
|
||||
@end
|
31
Classes/COSOverlayVisualizerWindow.m
Normal file
31
Classes/COSOverlayVisualizerWindow.m
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// COSOverlayVisualizerWindow.m
|
||||
// COSTouchVisualizer
|
||||
//
|
||||
// Created by Joseph Blau on 11/30/17.
|
||||
// Copyright © 2017 conopsys. All rights reserved.
|
||||
//
|
||||
|
||||
#import "COSOverlayVisualizerWindow.h"
|
||||
|
||||
@implementation COSOverlayVisualizerWindow
|
||||
|
||||
// UIKit tries to get the rootViewController from the overlay window.
|
||||
// Instead, try to find the rootViewController on some other
|
||||
// application window.
|
||||
// Fixes problems with status bar hiding, because it considers the
|
||||
// overlay window a candidate for controlling the status bar.
|
||||
- (UIViewController *)rootViewController {
|
||||
|
||||
for (UIWindow *window in [UIApplication sharedApplication].windows) {
|
||||
if (self == window) {
|
||||
continue;
|
||||
}
|
||||
if (window.rootViewController != nil) {
|
||||
return window.rootViewController;
|
||||
}
|
||||
}
|
||||
return [super rootViewController];
|
||||
}
|
||||
|
||||
@end
|
26
Classes/COSTouchConfig.h
Normal file
26
Classes/COSTouchConfig.h
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// COSTouchConfig.h
|
||||
// COSTouchVisualizer
|
||||
//
|
||||
// Created by Joseph Blau on 12/2/17.
|
||||
// Copyright © 2017 conopsys. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef NS_ENUM(NSUInteger, COSTouchConfigTpye) {
|
||||
COSTouchConfigTpyeContact,
|
||||
COSTouchConfigTpyeRipple,
|
||||
};
|
||||
|
||||
@interface COSTouchConfig : NSObject
|
||||
|
||||
@property (nonatomic) CGFloat alpha;
|
||||
@property (nonatomic) NSTimeInterval fadeDuration;
|
||||
@property (nonatomic, nullable) UIColor *strokeColor;
|
||||
@property (nonatomic, nullable) UIColor *fillColor;
|
||||
|
||||
-(nonnull instancetype)initWithTouchConfigType:(COSTouchConfigTpye)configType NS_DESIGNATED_INITIALIZER;
|
||||
-(nonnull instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
49
Classes/COSTouchConfig.m
Normal file
49
Classes/COSTouchConfig.m
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// COSTouchConfig.m
|
||||
// COSTouchVisualizer
|
||||
//
|
||||
// Created by Joseph Blau on 12/2/17.
|
||||
// Copyright © 2017 conopsys. All rights reserved.
|
||||
//
|
||||
|
||||
#import "COSTouchConfig.h"
|
||||
|
||||
static const CGFloat COSTouchConfigContactAlpha = 0.5f;
|
||||
static const CGFloat COSTouchConfigRippleAlpha = 0.2f;
|
||||
static const NSTimeInterval COSTouchConfigContactFadeDuration = 0.3;
|
||||
static const NSTimeInterval COSTouchConfigRippleFadeDuration = 0.2;
|
||||
|
||||
@implementation COSTouchConfig
|
||||
|
||||
-(instancetype)initWithTouchConfigType:(COSTouchConfigTpye)configType {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
switch (configType) {
|
||||
case COSTouchConfigTpyeContact:
|
||||
[self _configureContact];
|
||||
break;
|
||||
case COSTouchConfigTpyeRipple:
|
||||
[self _configureRipple];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
-(void)_configureContact {
|
||||
self.strokeColor = [UIColor blackColor];
|
||||
self.fillColor = [UIColor blackColor];
|
||||
self.alpha = COSTouchConfigContactAlpha;
|
||||
self.fadeDuration = COSTouchConfigContactFadeDuration;
|
||||
}
|
||||
|
||||
- (void)_configureRipple {
|
||||
self.strokeColor = [UIColor whiteColor];
|
||||
self.fillColor = [UIColor blueColor];
|
||||
self.alpha = COSTouchConfigRippleAlpha;
|
||||
self.fadeDuration = COSTouchConfigRippleFadeDuration;
|
||||
}
|
||||
|
||||
@end
|
19
Classes/COSTouchImageFactory.h
Normal file
19
Classes/COSTouchImageFactory.h
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// COSTouchImageFactory.h
|
||||
// COSTouchVisualizer
|
||||
//
|
||||
// Created by Joseph Blau on 12/2/17.
|
||||
// Copyright © 2017 conopsys. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class COSTouchConfig;
|
||||
|
||||
@interface COSTouchImageFactory : NSObject
|
||||
|
||||
+(nonnull UIImage *)imageWithTouchConfig:(nonnull COSTouchConfig*)touchConfig;
|
||||
|
||||
-(nonnull instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
48
Classes/COSTouchImageFactory.m
Normal file
48
Classes/COSTouchImageFactory.m
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// COSTouchImageFactory.m
|
||||
// COSTouchVisualizer
|
||||
//
|
||||
// Created by Joseph Blau on 12/2/17.
|
||||
// Copyright © 2017 conopsys. All rights reserved.
|
||||
//
|
||||
|
||||
#import "COSTouchImageFactory.h"
|
||||
#import "COSTouchConfig.h"
|
||||
|
||||
static const CGFloat COSTouchImageFactorySideSize = 50.0f;
|
||||
|
||||
@implementation COSTouchImageFactory
|
||||
|
||||
+(UIImage *)imageWithTouchConfig:(COSTouchConfig *)touchConfig {
|
||||
UIImage *touchImage = ({
|
||||
UIImage *image = [UIImage new];
|
||||
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0.0f,
|
||||
0.0f,
|
||||
COSTouchImageFactorySideSize,
|
||||
COSTouchImageFactorySideSize)];
|
||||
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
||||
CGPoint center = CGPointMake(COSTouchImageFactorySideSize / 2.0f,
|
||||
COSTouchImageFactorySideSize / 2.0f);
|
||||
|
||||
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:center
|
||||
radius:22.0
|
||||
startAngle:0
|
||||
endAngle:2 * M_PI
|
||||
clockwise:YES];
|
||||
drawPath.lineWidth = 2.0;
|
||||
|
||||
[touchConfig.strokeColor setStroke];
|
||||
[touchConfig.fillColor setFill];
|
||||
|
||||
[drawPath stroke];
|
||||
[drawPath fill];
|
||||
[clipPath addClip];
|
||||
image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
image;
|
||||
});
|
||||
return touchImage;
|
||||
}
|
||||
|
||||
@end
|
17
Classes/COSTouchImageView.h
Normal file
17
Classes/COSTouchImageView.h
Normal file
@ -0,0 +1,17 @@
|
||||
//
|
||||
// COSTouchSpotView.h
|
||||
// COSTouchVisualizer
|
||||
//
|
||||
// Created by Joseph Blau on 11/30/17.
|
||||
// Copyright © 2017 conopsys. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface COSTouchImageView : UIImageView
|
||||
|
||||
@property (nonatomic) NSTimeInterval timestamp;
|
||||
@property (nonatomic) BOOL shouldAutomaticallyRemoveAfterTimeout;
|
||||
@property (nonatomic, getter=isFadingOut) BOOL fadingOut;
|
||||
|
||||
@end
|
13
Classes/COSTouchImageView.m
Normal file
13
Classes/COSTouchImageView.m
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// COSTouchSpotView.m
|
||||
// COSTouchVisualizer
|
||||
//
|
||||
// Created by Joseph Blau on 11/30/17.
|
||||
// Copyright © 2017 conopsys. All rights reserved.
|
||||
//
|
||||
|
||||
#import "COSTouchImageView.h"
|
||||
|
||||
@implementation COSTouchImageView
|
||||
|
||||
@end
|
@ -12,6 +12,14 @@
|
||||
A71946C61C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A71946C21C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m */; };
|
||||
A71946C81C7EFB69003B7C4A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6F67FD018DE12B4001C954A /* UIKit.framework */; };
|
||||
A71946C91C7EFB74003B7C4A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6F67FCC18DE12B4001C954A /* Foundation.framework */; };
|
||||
E6C633A91FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C633A71FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h */; };
|
||||
E6C633AA1FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C633A81FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m */; };
|
||||
E6C633AD1FD0FC8E000DA40C /* COSTouchImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C633AB1FD0FC8E000DA40C /* COSTouchImageView.h */; };
|
||||
E6C633AE1FD0FC8E000DA40C /* COSTouchImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C633AC1FD0FC8E000DA40C /* COSTouchImageView.m */; };
|
||||
E6C633B11FD2CCB2000DA40C /* COSTouchConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C633AF1FD2CCB2000DA40C /* COSTouchConfig.h */; };
|
||||
E6C633B21FD2CCB2000DA40C /* COSTouchConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C633B01FD2CCB2000DA40C /* COSTouchConfig.m */; };
|
||||
E6C633B51FD2D4FD000DA40C /* COSTouchImageFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C633B31FD2D4FD000DA40C /* COSTouchImageFactory.h */; };
|
||||
E6C633B61FD2D4FD000DA40C /* COSTouchImageFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C633B41FD2D4FD000DA40C /* COSTouchImageFactory.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -20,6 +28,14 @@
|
||||
A71946C11C7EFB1F003B7C4A /* COSTouchVisualizerWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = COSTouchVisualizerWindow.h; sourceTree = "<group>"; };
|
||||
A71946C21C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = COSTouchVisualizerWindow.m; sourceTree = "<group>"; };
|
||||
A71946C31C7EFB1F003B7C4A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
E6C633A71FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = COSOverlayVisualizerWindow.h; sourceTree = "<group>"; };
|
||||
E6C633A81FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = COSOverlayVisualizerWindow.m; sourceTree = "<group>"; };
|
||||
E6C633AB1FD0FC8E000DA40C /* COSTouchImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = COSTouchImageView.h; sourceTree = "<group>"; };
|
||||
E6C633AC1FD0FC8E000DA40C /* COSTouchImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = COSTouchImageView.m; sourceTree = "<group>"; };
|
||||
E6C633AF1FD2CCB2000DA40C /* COSTouchConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = COSTouchConfig.h; sourceTree = "<group>"; };
|
||||
E6C633B01FD2CCB2000DA40C /* COSTouchConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = COSTouchConfig.m; sourceTree = "<group>"; };
|
||||
E6C633B31FD2D4FD000DA40C /* COSTouchImageFactory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = COSTouchImageFactory.h; sourceTree = "<group>"; };
|
||||
E6C633B41FD2D4FD000DA40C /* COSTouchImageFactory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = COSTouchImageFactory.m; sourceTree = "<group>"; };
|
||||
E6F67FCC18DE12B4001C954A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
E6F67FD018DE12B4001C954A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
@ -44,6 +60,14 @@
|
||||
A71946C11C7EFB1F003B7C4A /* COSTouchVisualizerWindow.h */,
|
||||
A71946C21C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m */,
|
||||
A71946C31C7EFB1F003B7C4A /* Info.plist */,
|
||||
E6C633A71FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h */,
|
||||
E6C633A81FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m */,
|
||||
E6C633AB1FD0FC8E000DA40C /* COSTouchImageView.h */,
|
||||
E6C633AC1FD0FC8E000DA40C /* COSTouchImageView.m */,
|
||||
E6C633AF1FD2CCB2000DA40C /* COSTouchConfig.h */,
|
||||
E6C633B01FD2CCB2000DA40C /* COSTouchConfig.m */,
|
||||
E6C633B31FD2D4FD000DA40C /* COSTouchImageFactory.h */,
|
||||
E6C633B41FD2D4FD000DA40C /* COSTouchImageFactory.m */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
@ -81,7 +105,11 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E6C633A91FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h in Headers */,
|
||||
E6C633B51FD2D4FD000DA40C /* COSTouchImageFactory.h in Headers */,
|
||||
E6C633AD1FD0FC8E000DA40C /* COSTouchImageView.h in Headers */,
|
||||
A71946C51C7EFB1F003B7C4A /* COSTouchVisualizerWindow.h in Headers */,
|
||||
E6C633B11FD2CCB2000DA40C /* COSTouchConfig.h in Headers */,
|
||||
A71946C41C7EFB1F003B7C4A /* COSTouchVisualizer.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -155,6 +183,10 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E6C633AA1FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m in Sources */,
|
||||
E6C633B61FD2D4FD000DA40C /* COSTouchImageFactory.m in Sources */,
|
||||
E6C633B21FD2CCB2000DA40C /* COSTouchConfig.m in Sources */,
|
||||
E6C633AE1FD0FC8E000DA40C /* COSTouchImageView.m in Sources */,
|
||||
A71946C61C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -7,36 +7,32 @@
|
||||
//
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
@protocol COSTouchVisualizerWindowDelegate;
|
||||
typedef NS_ENUM(NSUInteger, COSTouchVisualizerWindowTouchVisibility) {
|
||||
COSTouchVisualizerWindowTouchVisibilityNever,
|
||||
COSTouchVisualizerWindowTouchVisibilityRemoteOnly,
|
||||
COSTouchVisualizerWindowTouchVisibilityRemoteAndLocal,
|
||||
};
|
||||
|
||||
@class COSTouchVisualizerWindow;
|
||||
@class COSTouchConfig;
|
||||
|
||||
@interface COSTouchVisualizerWindow : UIWindow
|
||||
|
||||
@property (nonatomic, readonly, getter=isActive) BOOL active;
|
||||
@property (nonatomic, weak) id<COSTouchVisualizerWindowDelegate> touchVisualizerWindowDelegate;
|
||||
@property (nonatomic, readonly, getter=isMorphEnabled) BOOL morphEnabled;
|
||||
@property (nonatomic, readonly, nonnull) COSTouchConfig *touchContactConfig;
|
||||
@property (nonatomic, readonly, nonnull) COSTouchConfig *touchRippleConfig;
|
||||
@property (nonatomic, readonly) COSTouchVisualizerWindowTouchVisibility touchVisibility;
|
||||
|
||||
// Touch effects
|
||||
@property (nonatomic) UIImage *touchImage;
|
||||
@property (nonatomic) CGFloat touchAlpha;
|
||||
@property (nonatomic) NSTimeInterval fadeDuration;
|
||||
@property (nonatomic) UIColor *strokeColor;
|
||||
@property (nonatomic) UIColor *fillColor;
|
||||
-(nonnull instancetype)initWithFrame:(CGRect)frame
|
||||
morphEnabled:(BOOL)morphEnabled
|
||||
touchVisibility:(COSTouchVisualizerWindowTouchVisibility)touchVisibility
|
||||
contactConfig:(nullable COSTouchConfig*)contactConfig
|
||||
rippleConfig:(nullable COSTouchConfig*)rippleConfig NS_DESIGNATED_INITIALIZER;
|
||||
-(nonnull instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
|
||||
-(nonnull instancetype)init NS_UNAVAILABLE;
|
||||
-(nonnull instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
|
||||
|
||||
// Ripple Effects
|
||||
@property (nonatomic) UIImage *rippleImage;
|
||||
@property (nonatomic) CGFloat rippleAlpha;
|
||||
@property (nonatomic) NSTimeInterval rippleFadeDuration;
|
||||
@property (nonatomic) UIColor *rippleStrokeColor;
|
||||
@property (nonatomic) UIColor *rippleFillColor;
|
||||
|
||||
@property (nonatomic) BOOL stationaryMorphEnabled; // default: YES
|
||||
|
||||
@end
|
||||
|
||||
@protocol COSTouchVisualizerWindowDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
- (BOOL)touchVisualizerWindowShouldShowFingertip:(COSTouchVisualizerWindow *)window;
|
||||
- (BOOL)touchVisualizerWindowShouldAlwaysShowFingertip:(COSTouchVisualizerWindow *)window;
|
||||
|
||||
@end
|
||||
|
@ -7,46 +7,12 @@
|
||||
//
|
||||
|
||||
#import "COSTouchVisualizerWindow.h"
|
||||
#import "COSOverlayVisualizerWindow.h"
|
||||
#import "COSTouchImageView.h"
|
||||
#import "COSTouchConfig.h"
|
||||
#import "COSTouchImageFactory.h"
|
||||
|
||||
#pragma mark - Touch Visualizer Window
|
||||
|
||||
@interface TouchVisualizerWindow : UIWindow
|
||||
@end
|
||||
|
||||
@implementation TouchVisualizerWindow
|
||||
|
||||
// UIKit tries to get the rootViewController from the overlay window.
|
||||
// Instead, try to find the rootViewController on some other
|
||||
// application window.
|
||||
// Fixes problems with status bar hiding, because it considers the
|
||||
// overlay window a candidate for controlling the status bar.
|
||||
- (UIViewController *)rootViewController {
|
||||
for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
|
||||
if (self == window)
|
||||
continue;
|
||||
UIViewController *realRootViewController = window.rootViewController;
|
||||
if (realRootViewController != nil)
|
||||
return realRootViewController;
|
||||
}
|
||||
return [super rootViewController];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Conopsys Touch Spot View
|
||||
|
||||
@interface COSTouchSpotView : UIImageView
|
||||
|
||||
@property (nonatomic) NSTimeInterval timestamp;
|
||||
@property (nonatomic) BOOL shouldAutomaticallyRemoveAfterTimeout;
|
||||
@property (nonatomic, getter=isFadingOut) BOOL fadingOut;
|
||||
|
||||
@end
|
||||
|
||||
@implementation COSTouchSpotView
|
||||
@end
|
||||
|
||||
#pragma mark - Conopsys Touch Visualizer Window
|
||||
static const NSTimeInterval COSTouchVisualizerWindowRemoveDelay = 0.2;
|
||||
|
||||
@interface COSTouchVisualizerWindow ()
|
||||
|
||||
@ -56,97 +22,43 @@
|
||||
@property (nonatomic) NSTimer *timer;
|
||||
@property (nonatomic) NSSet *allTouches;
|
||||
|
||||
- (void)COSTouchVisualizerWindow_commonInit;
|
||||
- (void)scheduleFingerTipRemoval;
|
||||
- (void)cancelScheduledFingerTipRemoval;
|
||||
- (void)removeInactiveFingerTips;
|
||||
- (void)removeFingerTipWithHash:(NSUInteger)hash animated:(BOOL)animated;
|
||||
- (BOOL)shouldAutomaticallyRemoveFingerTipForTouch:(UITouch *)touch;
|
||||
@property (nonatomic) UIImage *touchImage;
|
||||
@property (nonatomic) UIImage *rippleImage;
|
||||
|
||||
@property (nonatomic) COSTouchConfig *touchContactConfig;
|
||||
@property (nonatomic) COSTouchConfig *touchRippleConfig;
|
||||
|
||||
@end
|
||||
|
||||
@implementation COSTouchVisualizerWindow
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder {
|
||||
// This covers NIB-loaded windows.
|
||||
if (self = [super initWithCoder:decoder])
|
||||
[self COSTouchVisualizerWindow_commonInit];
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
morphEnabled:(BOOL)morphEnabled
|
||||
touchVisibility:(COSTouchVisualizerWindowTouchVisibility)touchVisibility
|
||||
contactConfig:(COSTouchConfig *)contactConfig
|
||||
rippleConfig:(COSTouchConfig *)rippleConfig {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
_morphEnabled = morphEnabled;
|
||||
_touchVisibility = touchVisibility;
|
||||
_touchContactConfig = contactConfig ?: [[COSTouchConfig alloc] initWithTouchConfigType:COSTouchConfigTpyeContact];
|
||||
_touchRippleConfig = rippleConfig ?: [[COSTouchConfig alloc] initWithTouchConfigType:COSTouchConfigTpyeRipple];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)rect {
|
||||
// This covers programmatically-created windows.
|
||||
if (self = [super initWithFrame:rect])
|
||||
[self COSTouchVisualizerWindow_commonInit];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)COSTouchVisualizerWindow_commonInit {
|
||||
self.strokeColor = [UIColor blackColor];
|
||||
self.fillColor = [UIColor whiteColor];
|
||||
self.rippleStrokeColor = [UIColor whiteColor];
|
||||
self.rippleFillColor = [UIColor blueColor];
|
||||
self.touchAlpha = 0.5;
|
||||
self.fadeDuration = 0.3;
|
||||
self.rippleAlpha = 0.2;
|
||||
self.rippleFadeDuration = 0.2;
|
||||
self.stationaryMorphEnabled = YES;
|
||||
}
|
||||
|
||||
#pragma mark - Touch / Ripple and Images
|
||||
|
||||
- (UIImage *)touchImage {
|
||||
if (!_touchImage) {
|
||||
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50.0, 50.0)];
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
||||
|
||||
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25.0, 25.0)
|
||||
radius:22.0
|
||||
startAngle:0
|
||||
endAngle:2 * M_PI
|
||||
clockwise:YES];
|
||||
|
||||
drawPath.lineWidth = 2.0;
|
||||
|
||||
[self.strokeColor setStroke];
|
||||
[self.fillColor setFill];
|
||||
|
||||
[drawPath stroke];
|
||||
[drawPath fill];
|
||||
|
||||
[clipPath addClip];
|
||||
|
||||
_touchImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
_touchImage = [COSTouchImageFactory imageWithTouchConfig:self.touchContactConfig];
|
||||
}
|
||||
return _touchImage;
|
||||
}
|
||||
|
||||
- (UIImage *)rippleImage {
|
||||
if (!_rippleImage) {
|
||||
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50.0, 50.0)];
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
||||
|
||||
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25.0, 25.0)
|
||||
radius:22.0
|
||||
startAngle:0
|
||||
endAngle:2 * M_PI
|
||||
clockwise:YES];
|
||||
|
||||
drawPath.lineWidth = 2.0;
|
||||
|
||||
[self.rippleStrokeColor setStroke];
|
||||
[self.rippleFillColor setFill];
|
||||
|
||||
[drawPath stroke];
|
||||
[drawPath fill];
|
||||
|
||||
[clipPath addClip];
|
||||
|
||||
_rippleImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
_rippleImage = [COSTouchImageFactory imageWithTouchConfig:self.touchRippleConfig];
|
||||
}
|
||||
return _rippleImage;
|
||||
}
|
||||
@ -165,98 +77,94 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isActive {
|
||||
// should show fingertip or not
|
||||
if (![self.touchVisualizerWindowDelegate respondsToSelector:@selector(touchVisualizerWindowShouldShowFingertip:)] ||
|
||||
[self.touchVisualizerWindowDelegate touchVisualizerWindowShouldShowFingertip:self]) {
|
||||
// should always show or only when any screen is mirrored.
|
||||
return (([self.touchVisualizerWindowDelegate respondsToSelector:@selector(touchVisualizerWindowShouldAlwaysShowFingertip:)] &&
|
||||
[self.touchVisualizerWindowDelegate touchVisualizerWindowShouldAlwaysShowFingertip:self]) ||
|
||||
[self anyScreenIsMirrored]);
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UIWindow overrides
|
||||
|
||||
- (void)sendEvent:(UIEvent *)event {
|
||||
if (self.active) {
|
||||
self.allTouches = [event allTouches];
|
||||
for (UITouch *touch in [self.allTouches allObjects]) {
|
||||
switch (touch.phase) {
|
||||
case UITouchPhaseBegan:
|
||||
case UITouchPhaseMoved: {
|
||||
// Generate ripples
|
||||
COSTouchSpotView *rippleView = [[COSTouchSpotView alloc] initWithImage:self.rippleImage];
|
||||
[self.overlayWindow addSubview:rippleView];
|
||||
|
||||
rippleView.alpha = self.rippleAlpha;
|
||||
rippleView.center = [touch locationInView:self.overlayWindow];
|
||||
|
||||
[UIView animateWithDuration:self.rippleFadeDuration
|
||||
delay:0.0
|
||||
options:UIViewAnimationOptionCurveEaseIn // See other
|
||||
// options
|
||||
animations:^{
|
||||
[rippleView setAlpha:0.0];
|
||||
[rippleView setFrame:CGRectInset(rippleView.frame, 25, 25)];
|
||||
} completion:^(BOOL finished) {
|
||||
[rippleView removeFromSuperview];
|
||||
}];
|
||||
}
|
||||
case UITouchPhaseStationary: {
|
||||
COSTouchSpotView *touchView = (COSTouchSpotView *)[self.overlayWindow viewWithTag:touch.hash];
|
||||
|
||||
if (touch.phase != UITouchPhaseStationary && touchView != nil && [touchView isFadingOut]) {
|
||||
[self.timer invalidate];
|
||||
[touchView removeFromSuperview];
|
||||
touchView = nil;
|
||||
[super sendEvent:event];
|
||||
|
||||
switch (self.touchVisibility) {
|
||||
case COSTouchVisualizerWindowTouchVisibilityNever:
|
||||
return;
|
||||
break;
|
||||
|
||||
case COSTouchVisualizerWindowTouchVisibilityRemoteOnly:
|
||||
case COSTouchVisualizerWindowTouchVisibilityRemoteAndLocal: {
|
||||
self.allTouches = [event allTouches];
|
||||
for (UITouch *touch in [self.allTouches allObjects]) {
|
||||
switch (touch.phase) {
|
||||
case UITouchPhaseBegan:
|
||||
case UITouchPhaseMoved: {
|
||||
// Generate ripples
|
||||
COSTouchImageView *rippleView = [[COSTouchImageView alloc] initWithImage:self.rippleImage];
|
||||
[self.overlayWindow addSubview:rippleView];
|
||||
|
||||
rippleView.alpha = self.touchRippleConfig.alpha;
|
||||
rippleView.center = [touch locationInView:self.overlayWindow];
|
||||
|
||||
[UIView animateWithDuration:self.touchRippleConfig.fadeDuration
|
||||
delay:0.0
|
||||
options:UIViewAnimationOptionCurveEaseIn
|
||||
animations:^{
|
||||
[rippleView setAlpha:0.0];
|
||||
[rippleView setFrame:CGRectInset(rippleView.frame, 25, 25)];
|
||||
} completion:^(BOOL finished) {
|
||||
[rippleView removeFromSuperview];
|
||||
}];
|
||||
}
|
||||
|
||||
if (touchView == nil && touch.phase != UITouchPhaseStationary) {
|
||||
touchView = [[COSTouchSpotView alloc] initWithImage:self.touchImage];
|
||||
[self.overlayWindow addSubview:touchView];
|
||||
|
||||
if (self.stationaryMorphEnabled) {
|
||||
if (self.timer) {
|
||||
[self.timer invalidate];
|
||||
}
|
||||
|
||||
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.6
|
||||
target:self
|
||||
selector:@selector(performMorph:)
|
||||
userInfo:touchView
|
||||
repeats:YES];
|
||||
case UITouchPhaseStationary: {
|
||||
COSTouchImageView *touchView = (COSTouchImageView *)[self.overlayWindow viewWithTag:touch.hash];
|
||||
|
||||
if (touch.phase != UITouchPhaseStationary && touchView != nil && [touchView isFadingOut]) {
|
||||
[self.timer invalidate];
|
||||
[touchView removeFromSuperview];
|
||||
touchView = nil;
|
||||
}
|
||||
|
||||
if (touchView == nil && touch.phase != UITouchPhaseStationary) {
|
||||
touchView = [[COSTouchImageView alloc] initWithImage:self.touchImage];
|
||||
[self.overlayWindow addSubview:touchView];
|
||||
|
||||
if (self.morphEnabled) {
|
||||
if (self.timer) {
|
||||
[self.timer invalidate];
|
||||
}
|
||||
|
||||
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.6
|
||||
target:self
|
||||
selector:@selector(performMorphWithTouchView:)
|
||||
userInfo:touchView
|
||||
repeats:YES];
|
||||
}
|
||||
}
|
||||
if (![touchView isFadingOut]) {
|
||||
touchView.alpha = self.touchContactConfig.alpha;
|
||||
touchView.center = [touch locationInView:self.overlayWindow];
|
||||
touchView.tag = touch.hash;
|
||||
touchView.timestamp = touch.timestamp;
|
||||
touchView.shouldAutomaticallyRemoveAfterTimeout = [self shouldAutomaticallyRemoveFingerTipForTouch:touch];
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (![touchView isFadingOut]) {
|
||||
touchView.alpha = self.touchAlpha;
|
||||
touchView.center = [touch locationInView:self.overlayWindow];
|
||||
touchView.tag = touch.hash;
|
||||
touchView.timestamp = touch.timestamp;
|
||||
touchView.shouldAutomaticallyRemoveAfterTimeout = [self shouldAutomaticallyRemoveFingerTipForTouch:touch];
|
||||
case UITouchPhaseEnded:
|
||||
case UITouchPhaseCancelled: {
|
||||
[self removeFingerTipWithHash:touch.hash animated:YES];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UITouchPhaseEnded:
|
||||
case UITouchPhaseCancelled: {
|
||||
[self removeFingerTipWithHash:touch.hash animated:YES];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[super sendEvent:event];
|
||||
|
||||
[self scheduleFingerTipRemoval]; // We may not see all UITouchPhaseEnded/UITouchPhaseCancelled events.
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (UIWindow *)overlayWindow {
|
||||
if (!_overlayWindow) {
|
||||
_overlayWindow = [[TouchVisualizerWindow alloc] initWithFrame:self.frame];
|
||||
_overlayWindow = [[COSOverlayVisualizerWindow alloc] initWithFrame:self.frame];
|
||||
_overlayWindow.userInteractionEnabled = NO;
|
||||
_overlayWindow.windowLevel = UIWindowLevelStatusBar;
|
||||
_overlayWindow.backgroundColor = [UIColor clearColor];
|
||||
@ -264,11 +172,12 @@
|
||||
}
|
||||
return _overlayWindow;
|
||||
}
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)scheduleFingerTipRemoval {
|
||||
|
||||
if (self.fingerTipRemovalScheduled)
|
||||
if (self.fingerTipRemovalScheduled) {
|
||||
return;
|
||||
}
|
||||
self.fingerTipRemovalScheduled = YES;
|
||||
[self performSelector:@selector(removeInactiveFingerTips)
|
||||
withObject:nil
|
||||
@ -286,33 +195,34 @@
|
||||
self.fingerTipRemovalScheduled = NO;
|
||||
|
||||
NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime];
|
||||
const CGFloat REMOVAL_DELAY = 0.2;
|
||||
for (COSTouchSpotView *touchView in [self.overlayWindow subviews]) {
|
||||
if (![touchView isKindOfClass:[COSTouchSpotView class]])
|
||||
|
||||
for (COSTouchImageView *touchView in [self.overlayWindow subviews]) {
|
||||
if (![touchView isKindOfClass:[COSTouchImageView class]]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (touchView.shouldAutomaticallyRemoveAfterTimeout && now > touchView.timestamp + REMOVAL_DELAY)
|
||||
if (touchView.shouldAutomaticallyRemoveAfterTimeout && now > touchView.timestamp + COSTouchVisualizerWindowRemoveDelay) {
|
||||
[self removeFingerTipWithHash:touchView.tag animated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
if ([[self.overlayWindow subviews] count])
|
||||
if ([[self.overlayWindow subviews] count]) {
|
||||
[self scheduleFingerTipRemoval];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeFingerTipWithHash:(NSUInteger)hash animated:(BOOL)animated {
|
||||
COSTouchSpotView *touchView = (COSTouchSpotView *)[self.overlayWindow viewWithTag:hash];
|
||||
if (touchView == nil)
|
||||
return;
|
||||
|
||||
if ([touchView isFadingOut])
|
||||
COSTouchImageView *touchView = (COSTouchImageView *)[self.overlayWindow viewWithTag:hash];
|
||||
if (touchView == nil || [touchView isFadingOut]) {
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL animationsWereEnabled = [UIView areAnimationsEnabled];
|
||||
|
||||
if (animated) {
|
||||
[UIView setAnimationsEnabled:YES];
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
[UIView setAnimationDuration:self.fadeDuration];
|
||||
[UIView setAnimationDuration:self.touchContactConfig.fadeDuration];
|
||||
}
|
||||
|
||||
touchView.frame = CGRectMake(touchView.center.x - touchView.frame.size.width,
|
||||
@ -329,7 +239,7 @@
|
||||
touchView.fadingOut = YES;
|
||||
[touchView performSelector:@selector(removeFromSuperview)
|
||||
withObject:nil
|
||||
afterDelay:self.fadeDuration];
|
||||
afterDelay:self.touchContactConfig.fadeDuration];
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutomaticallyRemoveFingerTipForTouch:(UITouch *)touch;
|
||||
@ -346,40 +256,39 @@
|
||||
// don't use UITouchPhaseStationary touches for those. *sigh*). So we
|
||||
// end up with this more complicated setup.
|
||||
|
||||
UIView *view = [touch view];
|
||||
view = [view hitTest:[touch locationInView:view] withEvent:nil];
|
||||
UIView *touchView = [touch view];
|
||||
touchView = [touchView hitTest:[touch locationInView:touchView] withEvent:nil];
|
||||
|
||||
while (view != nil) {
|
||||
if ([view isKindOfClass:[UITableViewCell class]]) {
|
||||
while (touchView != nil) {
|
||||
if ([touchView isKindOfClass:[UITableViewCell class]]) {
|
||||
for (UIGestureRecognizer *recognizer in [touch gestureRecognizers]) {
|
||||
if ([recognizer isKindOfClass:[UISwipeGestureRecognizer class]])
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
if ([view isKindOfClass:[UITableView class]]) {
|
||||
if ([[touch gestureRecognizers] count] == 0)
|
||||
return YES;
|
||||
if ([touchView isKindOfClass:[UITableView class]] &&
|
||||
[[touch gestureRecognizers] count] == 0) {
|
||||
return YES;
|
||||
}
|
||||
view = view.superview;
|
||||
touchView = touchView.superview;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)performMorph:(NSTimer *)theTimer {
|
||||
UIView *view = (UIView *)[theTimer userInfo];
|
||||
- (void)performMorphWithTouchView:(COSTouchImageView *)touchView {
|
||||
NSTimeInterval duration = .4;
|
||||
NSTimeInterval delay = 0;
|
||||
// Start
|
||||
view.alpha = self.touchAlpha;
|
||||
view.transform = CGAffineTransformMakeScale(1, 1);
|
||||
touchView.alpha = self.touchContactConfig.alpha;
|
||||
touchView.transform = CGAffineTransformMakeScale(1, 1);
|
||||
[UIView animateWithDuration:duration / 4
|
||||
delay:delay
|
||||
options:0
|
||||
animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(1, 1.2);
|
||||
touchView.transform = CGAffineTransformMakeScale(1, 1.2);
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:duration / 4
|
||||
@ -387,7 +296,7 @@
|
||||
options:0
|
||||
animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(1.2, 0.9);
|
||||
touchView.transform = CGAffineTransformMakeScale(1.2, 0.9);
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:duration / 4
|
||||
@ -395,7 +304,7 @@
|
||||
options:0
|
||||
animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(0.9, 0.9);
|
||||
touchView.transform = CGAffineTransformMakeScale(0.9, 0.9);
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[UIView animateWithDuration:duration / 4
|
||||
@ -403,12 +312,13 @@
|
||||
options:0
|
||||
animations:^{
|
||||
// End
|
||||
view.transform = CGAffineTransformMakeScale(1, 1);
|
||||
touchView.transform = CGAffineTransformMakeScale(1, 1);
|
||||
}
|
||||
completion:^(BOOL finished){
|
||||
// If there are no touches, remove this morping touch
|
||||
if (self.allTouches.count == 0)
|
||||
[view removeFromSuperview];
|
||||
if (self.allTouches.count == 0) {
|
||||
[touchView removeFromSuperview];
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
|
@ -13,4 +13,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: 9c382a6853b1ccb79b91a8268f272eb3ffaff4be
|
||||
|
||||
COCOAPODS: 1.1.1
|
||||
COCOAPODS: 1.3.1
|
||||
|
@ -314,13 +314,16 @@
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-TouchVisualizer-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
@ -8,9 +8,7 @@
|
||||
|
||||
#import "COSAppDelegate.h"
|
||||
#import <COSTouchVisualizerWindow.h>
|
||||
|
||||
@interface COSAppDelegate () <COSTouchVisualizerWindowDelegate>
|
||||
@end
|
||||
#import <COSTouchConfig.h>
|
||||
|
||||
@implementation COSAppDelegate
|
||||
|
||||
@ -22,25 +20,29 @@
|
||||
- (COSTouchVisualizerWindow *)window {
|
||||
static COSTouchVisualizerWindow *customWindow = nil;
|
||||
if (!customWindow) {
|
||||
customWindow = [[COSTouchVisualizerWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
COSTouchConfig *contactConfig = ({
|
||||
COSTouchConfig *config = [[COSTouchConfig alloc] initWithTouchConfigType:COSTouchConfigTpyeContact];
|
||||
config.fillColor = [UIColor purpleColor];
|
||||
config.strokeColor = [UIColor blueColor];
|
||||
config.alpha = 0.4;
|
||||
config;
|
||||
});
|
||||
|
||||
[customWindow setFillColor:[UIColor purpleColor]];
|
||||
[customWindow setStrokeColor:[UIColor blueColor]];
|
||||
[customWindow setTouchAlpha:0.4];
|
||||
|
||||
[customWindow setRippleFillColor:[UIColor purpleColor]];
|
||||
[customWindow setRippleStrokeColor:[UIColor blueColor]];
|
||||
[customWindow setRippleAlpha:0.1];
|
||||
COSTouchConfig *riippleConfig = ({
|
||||
COSTouchConfig *config = [[COSTouchConfig alloc] initWithTouchConfigType:COSTouchConfigTpyeRipple];
|
||||
config.fillColor = [UIColor purpleColor];
|
||||
config.strokeColor = [UIColor blueColor];
|
||||
config.alpha = 0.1;
|
||||
config;
|
||||
});
|
||||
|
||||
[customWindow setTouchVisualizerWindowDelegate:self];
|
||||
customWindow = [[COSTouchVisualizerWindow alloc] initWithFrame:[UIScreen mainScreen].bounds
|
||||
morphEnabled:YES
|
||||
touchVisibility:COSTouchVisualizerWindowTouchVisibilityRemoteAndLocal
|
||||
contactConfig:contactConfig
|
||||
rippleConfig:riippleConfig];
|
||||
}
|
||||
return customWindow;
|
||||
}
|
||||
|
||||
#pragma mark - COSTouchVisualizerWindowDelegate
|
||||
|
||||
- (BOOL)touchVisualizerWindowShouldAlwaysShowFingertip:(COSTouchVisualizerWindow *)window {
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in New Issue
Block a user