【Swift】UIButtonを一回転させるアニメーション【改】

以前書いた記事「【Swift】UIButtonを一回転させるアニメーション」では、iOS8以上では一回転していましたが、iOS7では変な挙動をしていました。

今回やっとiOS7環境でも動くように改善しました。

iOS8以降でもこちらを利用した方が断然良いと思います!

 

以前のコード

まずは以前のコードのどこを書き換えるかです。

override func viewDidLoad() {
        super.viewDidLoad()
        BtnFunc()
}
func BtnFunc(){
        let Btn = UIButton()
        let Image = UIImage(named:"image.png")! as UIImage
        Btn.frame = CGRectMake(0,0,61,53)
        Btn.layer.position = CGPoint(x:self.view.bounds.width * 4.0 / 5.0,y:450.0)
        Btn.setImage(Image,forState:.Normal)
        Btn.addTarget(self,action:"BtnAnimation:",forControlEvents:.TouchUpInside)
        view.addSubview(Btn)
}    
func BtnAnimation(sender:UIButton){

/**************この部分をがっつり削除しましょう!
        // 初期化.
        sender.transform = CGAffineTransformMakeRotation(0)
        
        // radianで回転角度を指定(180度).
        let angle:CGFloat = CGFloat(M_PI)
        
        // アニメーションの秒数を設定(1秒).
        UIView.animateWithDuration(1.0,
            
            animations: { () -> Void in
                
                // 回転用のアフィン行列を生成.
                sender.transform = CGAffineTransformMakeRotation(angle)
                sender.transform = CGAffineTransformIdentity
            },
            completion: { (Bool) -> Void in
        })
*/
    }

 

アニメーションの部分をがっつり変えちゃいます。

代わりにこのようなコードを書きます

let rotationAnimation = CABasicAnimation(keyPath:"transform.rotation.z")
rotationAnimation.toValue = CGFloat(M_PI / 180) * 360
rotationAnimation.duration = 0.8
rotationAnimation.repeatCount = 1
sender.layer.addAnimation(rotationAnimation, forKey: "rotationAnimation")

 

これでiOS7でもちゃんと動くようになりました!わーい

 

少し解説・・・

animateWithDuration: animations:ではなくCABasicAnimationを用いる

animateWithDuration:animationsでは360度回転って意外と難しいです。簡単にできそうなのに全然できずにイライラしていましたが、CABasicAnimationを用いると簡単に360度回転することができました。

 

まず回転アニメーションを用いることを宣言

//CABasicAnimationのtransform.rotation.zを使うよ
let rotationAnimation = CABasicAnimation(keyPath:"transform.rotation.z")

ここでkeyPathを自分で設定するもんだと思ってたら違いました(照)

ちゃんと用意されているのでないと動かないので注意です。

 

次に回転角度を決めます

//回転角度
rotationAnimation.toValue = CGFloat(M_PI / 180) * 360

この値は、プラスのときは時計周り、マイナスのときは反時計回りに回ります。

 

次にアニメーションにかかる時間です

//回転にかかる時間
rotationAnimation.duration = 0.8

 

リピートする回数は今回は1回転のみにしたいので1にしておきます。

//リピートする回数
rotationAnimation.repeatCount = 1
//無限に繰り返す場合は
rotationAnimation.repeatCount = MAXFLOAT

 

最後にアニメーションさせたいものにaddAnimationします。

//ここでのsenderはUIButtonになります
sender.layer.addAnimation(rotationAnimation, forKey: nil)

//viewやlabelでも出来ます。
view.layer.addAnimation(rotationAnimation,forKey:"viewRotate")

//アニメーションを削除するときとかにKeyを使います
view.layer.removeAnimationForKey("viewRotate")

 

 

こんな感じです。

 

全体のコード

override func viewDidLoad() {
        super.viewDidLoad()
        BtnFunc()
}
func BtnFunc(){
        let Btn = UIButton()
        let Image = UIImage(named:"image.png")! as UIImage
        Btn.frame = CGRectMake(0,0,61,53)
        Btn.layer.position = CGPoint(x:self.view.bounds.width * 4.0 / 5.0,y:450.0)
        Btn.setImage(Image,forState:.Normal)
        Btn.addTarget(self,action:"BtnAnimation:",forControlEvents:.TouchUpInside)
        view.addSubview(Btn)
}    
func BtnAnimation(sender:UIButton){
        let rotationAnimation = CABasicAnimation(keyPath:"transform.rotation.z")
        rotationAnimation.toValue = CGFloat(M_PI / 180) * 360
        rotationAnimation.duration = 0.8
        rotationAnimation.repeatCount = 1
        sender.layer.addAnimation(rotationAnimation, forKey: "rotationAnimation")
    }

 

 

2018/04/14追記 Swift4に対応しました。
置き換えただけ〜〜〜

                

Comments...

コメントは認証制です。詳しくは下記の注意をお読みください。お気軽にコメントお願いします!

Write a Comment

コメント時の注意

「Twitter」「Facebook」「Google+」「WordPress」のいずれかのアカウントをお持ちの方は各アカウントと連携することでコメントできます。 コメントしたことはSNSに流れませんので、アカウントをお持ちの方はこちらの方法でコメントを投稿して下さると嬉しいです。 アカウントをお持ちでない方はメールアドレスで投稿することができます。 初回コメント時は承認後に表示されます。

Related Memo...

UINavigationController + UIScrollView の組み合わせで使っている時に謎の余白ができる時

UINavigationController + UIScrollView の組み合わせで使っていて、UIScrollView 上に AutoLayout で上下左右0で View を設置しているのに、30px程度上にずれてしまうとき。

`navigationController.navigationBar.isTranslucent = false` にすると直るかもしれない。

ScrollView上のコンテンツとNavigationBarの重なっているところが透過していたら多分これで直せるはず。

通常のターゲットではちゃんと動いているのに、iOSSnapshotTestCase を用いたテストでだけこの対応が必要なのよくわからないけれど。。。

iOS

記事を書くほどでもないけれどメモっておきたいこと

テスト投稿。

例えばiphone7 の画面サイズ

750 × 1334
半分375 × 667

iOS

UITableView.RowAnimation の .none はアニメーションするよ

UITableView.RowAnimation の .none はアニメーションがnoneなわけじゃなく、デフォルトの設定を使うよという意味らしい。

The inserted or deleted rows use the default animations.

なのでアニメーションしちゃう。今更の気づき。

 

iOS
more