質問編集履歴

2

RAMPaperSwitch classを書き換えた結果を追記しました

2020/01/17 20:40

投稿

masayoshi555
masayoshi555

スコア9

test CHANGED
File without changes
test CHANGED
@@ -120,6 +120,42 @@
120
120
 
121
121
  ```
122
122
 
123
+ ### RAMPaperSwitch classを編集(2020/1/18 05:30追記)
124
+
125
+ 以下に記載のRAMPaperSwitch class内のUIViewであるが故に、
126
+
127
+ 今回のcellでは表示できないのではないかと思い、UIView(3箇所)を全てUITableViewCellに変更し
128
+
129
+ 実行しましたが、switchは表示されませんでした。
130
+
131
+ ```
132
+
133
+ public required init(view: UIView?, color: UIColor?) {
134
+
135
+ super.init(frame: CGRect.zero)
136
+
137
+ onTintColor = color
138
+
139
+ self.commonInit(view)
140
+
141
+ }
142
+
143
+ ```
144
+
145
+ その際、ここにエラーが出たのでsuperview as? UITableViewCellとしました
146
+
147
+ ```
148
+
149
+ override open func awakeFromNib() {
150
+
151
+ self.commonInit(parentView ?? superview)
152
+
153
+ super.awakeFromNib()
154
+
155
+ }
156
+
157
+ ```
158
+
123
159
  ###PaperSwitch
124
160
 
125
161
  PaperSwitch自体は本来storyboardで配置したswitchのclassをRAMPaperSwitchと

1

RAMPaperSwitch classのコードを追記しました

2020/01/17 20:40

投稿

masayoshi555
masayoshi555

スコア9

test CHANGED
File without changes
test CHANGED
@@ -133,3 +133,343 @@
133
133
  ![イメージ説明](ccfc0f43b50c7edd519526863fff1d33.png)
134
134
 
135
135
  ![イメージ説明](332de4af429318409922a753e3eb7afe.gif)
136
+
137
+ ```
138
+
139
+ open class RAMPaperSwitch: UISwitch, CAAnimationDelegate {
140
+
141
+
142
+
143
+ struct Constants {
144
+
145
+ static let scale = "transform.scale"
146
+
147
+ static let up = "scaleUp"
148
+
149
+ static let down = "scaleDown"
150
+
151
+ }
152
+
153
+
154
+
155
+ /// The total duration of the animations, measured in seconds. Default 0.35
156
+
157
+ @IBInspectable open var duration: Double = 0.35
158
+
159
+
160
+
161
+ /// Closuer call when animation start
162
+
163
+ open var animationDidStartClosure = {(onAnimation: Bool) -> Void in }
164
+
165
+
166
+
167
+ /// Closuer call when animation finish
168
+
169
+ open var animationDidStopClosure = {(onAnimation: Bool, finished: Bool) -> Void in }
170
+
171
+
172
+
173
+ fileprivate var shape: CAShapeLayer! = CAShapeLayer()
174
+
175
+ fileprivate var radius: CGFloat = 0.0
176
+
177
+ fileprivate var oldState = false
178
+
179
+
180
+
181
+ fileprivate var defaultTintColor: UIColor?
182
+
183
+ @IBOutlet open var parentView: UIView? {
184
+
185
+ didSet {
186
+
187
+ defaultTintColor = parentView?.backgroundColor
188
+
189
+ }
190
+
191
+ }
192
+
193
+
194
+
195
+ // MARK: - Initialization
196
+
197
+
198
+
199
+ /**
200
+
201
+ Returns an initialized switch object.
202
+
203
+
204
+
205
+ - parameter view: animatable view
206
+
207
+ - parameter color: The color which fill view.
208
+
209
+
210
+
211
+ - returns: An initialized UISwitch object.
212
+
213
+ */
214
+
215
+ public required init(view: UIView?, color: UIColor?) {
216
+
217
+ super.init(frame: CGRect.zero)
218
+
219
+ onTintColor = color
220
+
221
+ self.commonInit(view)
222
+
223
+ }
224
+
225
+
226
+
227
+ public required init?(coder aDecoder: NSCoder) {
228
+
229
+ super.init(coder: aDecoder)
230
+
231
+ }
232
+
233
+
234
+
235
+ override open func awakeFromNib() {
236
+
237
+ self.commonInit(parentView ?? superview)
238
+
239
+ super.awakeFromNib()
240
+
241
+ }
242
+
243
+
244
+
245
+ // MARK: Helpers
246
+
247
+ fileprivate func commonInit(_ parentView: UIView?) {
248
+
249
+ guard let onTintColor = self.onTintColor else {
250
+
251
+ fatalError("set tint color")
252
+
253
+ }
254
+
255
+ self.parentView = parentView
256
+
257
+ defaultTintColor = parentView?.backgroundColor
258
+
259
+
260
+
261
+ layer.borderWidth = 0.5
262
+
263
+ layer.borderColor = UIColor.white.cgColor
264
+
265
+ layer.cornerRadius = frame.size.height / 2
266
+
267
+
268
+
269
+ shape.fillColor = onTintColor.cgColor
270
+
271
+ shape.masksToBounds = true
272
+
273
+
274
+
275
+ parentView?.layer.insertSublayer(shape, at: 0)
276
+
277
+ parentView?.layer.masksToBounds = true
278
+
279
+
280
+
281
+ showShapeIfNeed()
282
+
283
+
284
+
285
+ addTarget(self, action: #selector(RAMPaperSwitch.switchChanged), for: UIControl.Event.valueChanged)
286
+
287
+ }
288
+
289
+
290
+
291
+ override open func layoutSubviews() {
292
+
293
+
294
+
295
+ if let parentView = self.parentView {
296
+
297
+ let x:CGFloat = max(center.x, parentView.frame.size.width - frame.midX)
298
+
299
+ let y:CGFloat = max(center.y, parentView.frame.size.height - frame.midY)
300
+
301
+ radius = sqrt(x*x + y*y)
302
+
303
+ }
304
+
305
+
306
+
307
+ let additional = parentView == superview ? CGPoint.zero : (superview?.frame.origin ?? CGPoint.zero)
308
+
309
+
310
+
311
+ shape.frame = CGRect(x: center.x - radius + additional.x - 2, y: center.y - radius + additional.y, width: radius * 2, height: radius * 2)
312
+
313
+ shape.anchorPoint = CGPoint(x: 0.5, y: 0.5)
314
+
315
+ shape.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: radius * 2, height: radius * 2)).cgPath
316
+
317
+ }
318
+
319
+
320
+
321
+ // MARK: - Public
322
+
323
+ open override func setOn(_ on: Bool, animated: Bool) {
324
+
325
+ let changed:Bool = on != self.isOn
326
+
327
+
328
+
329
+ super.setOn(on, animated: animated)
330
+
331
+
332
+
333
+ if changed {
334
+
335
+ switchChangeWithAnimation(animated)
336
+
337
+ }
338
+
339
+ }
340
+
341
+
342
+
343
+ // MARK: - Private
344
+
345
+ fileprivate func showShapeIfNeed() {
346
+
347
+ shape.transform = isOn ? CATransform3DMakeScale(1.0, 1.0, 1.0) : CATransform3DMakeScale(0.0001, 0.0001, 0.0001)
348
+
349
+ }
350
+
351
+
352
+
353
+ @objc internal func switchChanged() {
354
+
355
+ switchChangeWithAnimation(true)
356
+
357
+ }
358
+
359
+
360
+
361
+ // MARK: - Animations
362
+
363
+ fileprivate func animateKeyPath(_ keyPath: String, fromValue from: CGFloat?, toValue to: CGFloat, timing timingFunction: String) -> CABasicAnimation {
364
+
365
+
366
+
367
+ let animation:CABasicAnimation = CABasicAnimation(keyPath: keyPath)
368
+
369
+
370
+
371
+ animation.fromValue = from
372
+
373
+ animation.toValue = to
374
+
375
+ animation.repeatCount = 1
376
+
377
+ animation.timingFunction = CAMediaTimingFunction(name: convertToCAMediaTimingFunctionName(timingFunction))
378
+
379
+ animation.isRemovedOnCompletion = false
380
+
381
+ animation.fillMode = CAMediaTimingFillMode.forwards
382
+
383
+ animation.duration = duration
384
+
385
+ animation.delegate = self
386
+
387
+
388
+
389
+ return animation
390
+
391
+ }
392
+
393
+
394
+
395
+ fileprivate func switchChangeWithAnimation(_ animation: Bool) {
396
+
397
+ guard let onTintColor = self.onTintColor else {
398
+
399
+ return
400
+
401
+ }
402
+
403
+
404
+
405
+ shape.fillColor = onTintColor.cgColor
406
+
407
+
408
+
409
+ if isOn {
410
+
411
+ let scaleAnimation:CABasicAnimation = animateKeyPath(Constants.scale,
412
+
413
+ fromValue: 0.01,
414
+
415
+ toValue: 1.0,
416
+
417
+ timing:convertFromCAMediaTimingFunctionName(CAMediaTimingFunctionName.easeIn));
418
+
419
+ if animation == false { scaleAnimation.duration = 0.0001 }
420
+
421
+
422
+
423
+ shape.add(scaleAnimation, forKey: Constants.up)
424
+
425
+ } else {
426
+
427
+ let scaleAnimation:CABasicAnimation = animateKeyPath(Constants.scale,
428
+
429
+ fromValue: 1.0,
430
+
431
+ toValue: 0.01,
432
+
433
+ timing:convertFromCAMediaTimingFunctionName(CAMediaTimingFunctionName.easeOut));
434
+
435
+ if animation == false { scaleAnimation.duration = 0.0001 }
436
+
437
+
438
+
439
+ shape.add(scaleAnimation, forKey: Constants.down)
440
+
441
+ }
442
+
443
+ }
444
+
445
+
446
+
447
+ //MARK: - CAAnimation Delegate
448
+
449
+ open func animationDidStart(_ anim: CAAnimation) {
450
+
451
+ parentView?.backgroundColor = defaultTintColor
452
+
453
+ animationDidStartClosure(isOn)
454
+
455
+ }
456
+
457
+
458
+
459
+ open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
460
+
461
+ if flag == true {
462
+
463
+ parentView?.backgroundColor = isOn == true ? onTintColor : defaultTintColor
464
+
465
+ }
466
+
467
+
468
+
469
+ animationDidStopClosure(isOn, flag)
470
+
471
+ }
472
+
473
+ }
474
+
475
+ ```