困りごと
swiftのライブラリ:PaperSwitchをtableViewで使いたく、
tableViewにコードで実装するUISwitchをPaperSwitchにしたいと考えています。
*PaperSwitchについては最下段に記載しています
以下のコードではswitchが表示されず困っています。
どなたかご教授頂けると幸いです。
import UIKit import RAMPaperSwitch class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { override func viewDidLoad() { super.viewDidLoad() } // セル数の設定 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 5 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // セルを取得する tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel!.text = "test" //UISwitchをcellのアクセサリービューに追加する let switchView = UISwitch(frame: CGRect(x: (self.view.frame.width) / 2, y: (self.view.frame.height) / 2 , width: 50, height: 25)) as? RAMPaperSwitch cell.accessoryView = switchView //ティントカラーを指定 switchView?.onTintColor = UIColor.blue return cell } }
実行結果
as? RAMPaperSwitchを除くと表示される
コード内「let switchView = UISwitch(frame: CGRect(省略) / 2 , width: 50, height: 25)) as? RAMPaperSwitch」から「as? RAMPaperSwitch」を除くと以下のようにswitchが表示されますが、PaperSwitchは適用されない。(当たり前ですね)
事前に宣言してから使用
では、事前に宣言してはどうかと思い試しましたが、
let switchView: RAMPaperSwitch? switchView = UISwitch(frame: CGRect(x: (self.view.frame.width) / 2, y: (self.view.frame.height) / 2 , width: 50, height: 25)) cell.accessoryView = switchView
「Cannot assign value of type 'UISwitch' to type 'RAMPaperSwitch?'」と表示され
FIX候補として「Insert ' as! RAMPaperSwitch'」が表示されます。
その通りにして実行すると、エラーとなります。
let switchView: RAMPaperSwitch? switchView = UISwitch(frame: CGRect(x: (self.view.frame.width) / 2, y: (self.view.frame.height) / 2 , width: 50, height: 25)) as! RAMPaperSwitch cell.accessoryView = switchView
error
1Could not cast value of type 'UISwitch' (0x7fff898b23a0) to 'RAMPaperSwitch.RAMPaperSwitch' (0x110049c98).
RAMPaperSwitch classを編集(2020/1/18 05:30追記)
以下に記載のRAMPaperSwitch class内のUIViewであるが故に、
今回のcellでは表示できないのではないかと思い、UIView(3箇所)を全てUITableViewCellに変更し
実行しましたが、switchは表示されませんでした。
public required init(view: UIView?, color: UIColor?) { super.init(frame: CGRect.zero) onTintColor = color self.commonInit(view) }
その際、ここにエラーが出たのでsuperview as? UITableViewCellとしました
override open func awakeFromNib() { self.commonInit(parentView ?? superview) super.awakeFromNib() }
###PaperSwitch
PaperSwitch自体は本来storyboardで配置したswitchのclassをRAMPaperSwitchと
指定し、onTintColorを指定するだけで利用できると言う優れものです。
通常の使い方(view内)での作動は確認できております。
open class RAMPaperSwitch: UISwitch, CAAnimationDelegate { struct Constants { static let scale = "transform.scale" static let up = "scaleUp" static let down = "scaleDown" } /// The total duration of the animations, measured in seconds. Default 0.35 @IBInspectable open var duration: Double = 0.35 /// Closuer call when animation start open var animationDidStartClosure = {(onAnimation: Bool) -> Void in } /// Closuer call when animation finish open var animationDidStopClosure = {(onAnimation: Bool, finished: Bool) -> Void in } fileprivate var shape: CAShapeLayer! = CAShapeLayer() fileprivate var radius: CGFloat = 0.0 fileprivate var oldState = false fileprivate var defaultTintColor: UIColor? @IBOutlet open var parentView: UIView? { didSet { defaultTintColor = parentView?.backgroundColor } } // MARK: - Initialization /** Returns an initialized switch object. - parameter view: animatable view - parameter color: The color which fill view. - returns: An initialized UISwitch object. */ public required init(view: UIView?, color: UIColor?) { super.init(frame: CGRect.zero) onTintColor = color self.commonInit(view) } public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override open func awakeFromNib() { self.commonInit(parentView ?? superview) super.awakeFromNib() } // MARK: Helpers fileprivate func commonInit(_ parentView: UIView?) { guard let onTintColor = self.onTintColor else { fatalError("set tint color") } self.parentView = parentView defaultTintColor = parentView?.backgroundColor layer.borderWidth = 0.5 layer.borderColor = UIColor.white.cgColor layer.cornerRadius = frame.size.height / 2 shape.fillColor = onTintColor.cgColor shape.masksToBounds = true parentView?.layer.insertSublayer(shape, at: 0) parentView?.layer.masksToBounds = true showShapeIfNeed() addTarget(self, action: #selector(RAMPaperSwitch.switchChanged), for: UIControl.Event.valueChanged) } override open func layoutSubviews() { if let parentView = self.parentView { let x:CGFloat = max(center.x, parentView.frame.size.width - frame.midX) let y:CGFloat = max(center.y, parentView.frame.size.height - frame.midY) radius = sqrt(x*x + y*y) } let additional = parentView == superview ? CGPoint.zero : (superview?.frame.origin ?? CGPoint.zero) shape.frame = CGRect(x: center.x - radius + additional.x - 2, y: center.y - radius + additional.y, width: radius * 2, height: radius * 2) shape.anchorPoint = CGPoint(x: 0.5, y: 0.5) shape.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: radius * 2, height: radius * 2)).cgPath } // MARK: - Public open override func setOn(_ on: Bool, animated: Bool) { let changed:Bool = on != self.isOn super.setOn(on, animated: animated) if changed { switchChangeWithAnimation(animated) } } // MARK: - Private fileprivate func showShapeIfNeed() { shape.transform = isOn ? CATransform3DMakeScale(1.0, 1.0, 1.0) : CATransform3DMakeScale(0.0001, 0.0001, 0.0001) } @objc internal func switchChanged() { switchChangeWithAnimation(true) } // MARK: - Animations fileprivate func animateKeyPath(_ keyPath: String, fromValue from: CGFloat?, toValue to: CGFloat, timing timingFunction: String) -> CABasicAnimation { let animation:CABasicAnimation = CABasicAnimation(keyPath: keyPath) animation.fromValue = from animation.toValue = to animation.repeatCount = 1 animation.timingFunction = CAMediaTimingFunction(name: convertToCAMediaTimingFunctionName(timingFunction)) animation.isRemovedOnCompletion = false animation.fillMode = CAMediaTimingFillMode.forwards animation.duration = duration animation.delegate = self return animation } fileprivate func switchChangeWithAnimation(_ animation: Bool) { guard let onTintColor = self.onTintColor else { return } shape.fillColor = onTintColor.cgColor if isOn { let scaleAnimation:CABasicAnimation = animateKeyPath(Constants.scale, fromValue: 0.01, toValue: 1.0, timing:convertFromCAMediaTimingFunctionName(CAMediaTimingFunctionName.easeIn)); if animation == false { scaleAnimation.duration = 0.0001 } shape.add(scaleAnimation, forKey: Constants.up) } else { let scaleAnimation:CABasicAnimation = animateKeyPath(Constants.scale, fromValue: 1.0, toValue: 0.01, timing:convertFromCAMediaTimingFunctionName(CAMediaTimingFunctionName.easeOut)); if animation == false { scaleAnimation.duration = 0.0001 } shape.add(scaleAnimation, forKey: Constants.down) } } //MARK: - CAAnimation Delegate open func animationDidStart(_ anim: CAAnimation) { parentView?.backgroundColor = defaultTintColor animationDidStartClosure(isOn) } open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { if flag == true { parentView?.backgroundColor = isOn == true ? onTintColor : defaultTintColor } animationDidStopClosure(isOn, flag) } }
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/01/18 20:13
2020/01/19 01:48