Skip to content

Commit 7dd9c3d

Browse files
committed
add iOS 8.0 test; dynamically change the wave cycles can work
1 parent e5d3666 commit 7dd9c3d

File tree

4 files changed

+74
-37
lines changed

4 files changed

+74
-37
lines changed

Example/JWWaveView/TestExamples/ClickToRemove/JWClickToRemove.storyboard

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,22 @@
3939
<action selector="clickToRemoveWaveView:" destination="4UP-kR-Cxk" eventType="touchUpInside" id="sGm-Hv-uba"/>
4040
</connections>
4141
</button>
42+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IMd-38-N5B">
43+
<rect key="frame" x="104.5" y="494" width="111" height="30"/>
44+
<state key="normal" title="Add Wave Cycle"/>
45+
<connections>
46+
<action selector="clickToAddWaveCycle:" destination="4UP-kR-Cxk" eventType="touchUpInside" id="v2S-U9-VeU"/>
47+
</connections>
48+
</button>
4249
</subviews>
4350
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
4451
<constraints>
4552
<constraint firstItem="DH6-gF-Yr9" firstAttribute="centerY" secondItem="leL-7A-GzG" secondAttribute="centerY" id="7i0-Hq-uAu"/>
4653
<constraint firstItem="c8C-kS-923" firstAttribute="top" secondItem="DH6-gF-Yr9" secondAttribute="bottom" constant="80" id="O8c-Mw-Wke"/>
4754
<constraint firstItem="c8C-kS-923" firstAttribute="centerX" secondItem="leL-7A-GzG" secondAttribute="centerX" id="RdF-tb-3mh"/>
55+
<constraint firstItem="IMd-38-N5B" firstAttribute="centerX" secondItem="leL-7A-GzG" secondAttribute="centerX" id="lba-j1-upT"/>
4856
<constraint firstItem="DH6-gF-Yr9" firstAttribute="centerX" secondItem="leL-7A-GzG" secondAttribute="centerX" id="nIO-a9-gyL"/>
57+
<constraint firstItem="IMd-38-N5B" firstAttribute="top" secondItem="c8C-kS-923" secondAttribute="bottom" constant="30" id="rhS-0I-Tjv"/>
4958
</constraints>
5059
</view>
5160
<connections>

Example/JWWaveView/TestExamples/ClickToRemove/JWClickToRemoveWaveViewTestController.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ - (IBAction)clickToRemoveWaveView:(UIButton *)sender {
5454
}
5555
}
5656

57+
- (IBAction)clickToAddWaveCycle:(UIButton *)sender {
58+
NSInteger currentCycle = self.waveView.waveCycles;
59+
currentCycle++;
60+
self.waveView.waveCycles = currentCycle;
61+
}
62+
5763
- (void)setAnimationPaused:(BOOL)animationPaused {
5864
_animationPaused = animationPaused;
5965
}

JWWaveView.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
Pod::Spec.new do |s|
1010
s.name = 'JWWaveView'
11-
s.version = '0.2.3'
11+
s.version = '0.2.4'
1212
s.summary = 'Providing a water waving effect for any of your UIView instance.'
1313

1414
# This description is used to generate tags and improve search results.

JWWaveView/Classes/JWWaveView.m

Lines changed: 58 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
@interface JWWaveView ()
1414
@property (nonatomic, strong) CAShapeLayer *waveShapeLayer;
15+
@property (nonatomic, assign) BOOL shouldRestart; //if animation was started once; set this flat to YES;
1516
@end
1617

1718
@implementation JWWaveView
@@ -20,19 +21,14 @@ @implementation JWWaveView
2021
- (void)startWavingIfNeeded {
2122
CAReplicatorLayer *replicatorLayer = [self replicatorLayer];
2223
CGRect replicatorRect = replicatorLayer.bounds;
23-
if (CGRectIsEmpty(replicatorRect)) {
24-
return;
25-
}
26-
2724
self.waveShapeLayer.frame = replicatorRect;
28-
CGFloat instanceWidth = CGRectGetWidth(replicatorRect);
29-
replicatorLayer.instanceTransform = CATransform3DMakeTranslation(instanceWidth, 0, 0);
3025

3126
//setup shape
32-
[self setupWavePath];
33-
27+
[self renewWavePathWithForceRenew:NO animated:NO];
28+
3429
//restart animtion
3530
[self restartWaveShapeTranslation];
31+
_shouldRestart = YES;
3632
}
3733

3834
- (void)pauseWavingIfNeeded {
@@ -81,19 +77,36 @@ - (CAReplicatorLayer *)replicatorLayer {
8177
}
8278

8379
- (void)willMoveToSuperview:(UIView *)newSuperview {
80+
[super willMoveToSuperview:newSuperview];
8481
if (!newSuperview) {
8582
[self pauseWavingIfNeeded];
8683
}
8784
else {
88-
[self restartWaveShapeTranslation];
85+
//has started before by calling the public api
86+
if (self.shouldRestart) {
87+
[self restartWaveShapeTranslation];
88+
}
8989
}
90-
[super willMoveToSuperview:newSuperview];
90+
}
91+
92+
- (void)layoutSubviews {
93+
[super layoutSubviews];
94+
CAReplicatorLayer *replicatorLayer = [self replicatorLayer];
95+
CGRect replicatorRect = replicatorLayer.bounds;
96+
self.waveShapeLayer.frame = replicatorRect;
9197
}
9298

9399
#pragma mark - Private
94100
- (void)restartWaveShapeTranslation {
101+
//layer setup
95102
CAReplicatorLayer *replicatorLayer = [self replicatorLayer];
96103
CGRect replicatorRect = replicatorLayer.bounds;
104+
CGFloat instanceWidth = CGRectGetWidth(replicatorRect);
105+
replicatorLayer.instanceTransform = CATransform3DMakeTranslation(instanceWidth, 0, 0);
106+
if (CGRectIsEmpty(replicatorRect)) {
107+
return;
108+
}
109+
97110
if (![self.waveShapeLayer animationForKey:kWaveShapeTranslationAnimationKey]) {
98111
//add translation animation to shape layer;
99112
CABasicAnimation *transAnim = [CABasicAnimation animation];
@@ -125,44 +138,49 @@ - (void)configureWaveShapes {
125138
CAReplicatorLayer *replicatorLayer = [self replicatorLayer];
126139

127140
//add two shape layers
141+
CGRect replicatorRect = replicatorLayer.bounds;
142+
self.waveShapeLayer.frame = replicatorRect;
128143
[replicatorLayer addSublayer:self.waveShapeLayer];
129144
replicatorLayer.instanceCount = 2;
130145
replicatorLayer.instanceDelay = 0;
131146
}
132147

133-
- (void)setupWavePath {
148+
- (void)renewWavePathWithForceRenew:(BOOL)forceRenew animated:(BOOL)animated {
134149
CGRect sinPathCanvasRect = self.waveShapeLayer.bounds;
135150
sinPathCanvasRect = CGRectIntegral(sinPathCanvasRect);
136151
if (CGRectIsEmpty(sinPathCanvasRect)) {
137152
return;
138153
}
139154

140-
[CATransaction begin];
141-
[CATransaction setDisableActions:YES];
142-
CGFloat canvasWidth = sinPathCanvasRect.size.width;
143-
CGFloat canvasHeight = sinPathCanvasRect.size.height;
144-
CGFloat canvasMidY = CGRectGetMidY(sinPathCanvasRect);
145-
UIBezierPath *sinPath = [UIBezierPath bezierPath];
146-
sinPath.lineWidth = 1.f;
147-
CGFloat yPos = 0;
148-
for (CGFloat xPos = 0.f; xPos <= canvasWidth; xPos += 1.f) {
149-
//wave path starts at the canvasMidY and uses (canvasHeight * 0.5) as amplitude
150-
CGFloat halfAmplitude = canvasHeight / 4.f;
151-
yPos = canvasMidY + sin((xPos)/canvasWidth * M_PI * 2 * _waveCycles) * halfAmplitude;
152-
if (fpclassify(xPos) == FP_ZERO) {
153-
[sinPath moveToPoint:(CGPoint){xPos, yPos}];
154-
}
155-
else {
156-
[sinPath addLineToPoint:(CGPoint){xPos, yPos}];
155+
//use default implicit animation
156+
if (!self.waveShapeLayer.path || forceRenew) {
157+
[CATransaction begin];
158+
[CATransaction setDisableActions:!animated];
159+
CGFloat canvasWidth = sinPathCanvasRect.size.width;
160+
CGFloat canvasHeight = sinPathCanvasRect.size.height;
161+
CGFloat canvasMidY = CGRectGetMidY(sinPathCanvasRect);
162+
UIBezierPath *sinPath = [UIBezierPath bezierPath];
163+
sinPath.lineWidth = 1.f;
164+
CGFloat yPos = 0;
165+
for (CGFloat xPos = 0.f; xPos <= canvasWidth; xPos += 1.f) {
166+
//wave path starts at the canvasMidY and uses (canvasHeight * 0.5) as amplitude
167+
CGFloat halfAmplitude = canvasHeight / 4.f;
168+
yPos = canvasMidY + sin((xPos)/canvasWidth * M_PI * 2 * _waveCycles) * halfAmplitude;
169+
if (fpclassify(xPos) == FP_ZERO) {
170+
[sinPath moveToPoint:(CGPoint){xPos, yPos}];
171+
}
172+
else {
173+
[sinPath addLineToPoint:(CGPoint){xPos, yPos}];
174+
}
157175
}
176+
177+
//close path
178+
[sinPath addLineToPoint:(CGPoint){canvasWidth, canvasHeight}];
179+
[sinPath addLineToPoint:(CGPoint){0, canvasHeight}];
180+
[sinPath closePath];
181+
self.waveShapeLayer.path = sinPath.CGPath;
182+
[CATransaction commit];
158183
}
159-
160-
//close path
161-
[sinPath addLineToPoint:(CGPoint){canvasWidth, canvasHeight}];
162-
[sinPath addLineToPoint:(CGPoint){0, canvasHeight}];
163-
[sinPath closePath];
164-
self.waveShapeLayer.path = sinPath.CGPath;
165-
[CATransaction commit];
166184
}
167185

168186
#pragma mark - Accessors
@@ -173,7 +191,11 @@ - (void)setWaveColor:(UIColor *)waveColor {
173191

174192
- (void)setWaveCycles:(NSInteger)waveCycles {
175193
if (_waveCycles != waveCycles) {
176-
_waveCycles = MAX(1, waveCycles);
194+
NSInteger adjustedCycles = MAX(1, waveCycles);
195+
if (adjustedCycles != _waveCycles) {
196+
_waveCycles = adjustedCycles;
197+
[self renewWavePathWithForceRenew:YES animated:YES];
198+
}
177199
}
178200
}
179201

0 commit comments

Comments
 (0)