とがみんブログ
大学院の中退を決断し、徹底的に自分と向き合い就職活動をする中で、心理学や脳科学に興味を持つ。挙げ句の果てに、この世界の仕組みにも興味を持つ。そんなとがみんの考えや経験を綴ったブログです。
swift

【Swift4】Tinder風UI(ユーザーインターフェース)の作成方法

どうも。とがみんです。

最近は、セブ島にあるプログラミングと英語の両方を勉強できるNexSeedという学校で、エンジニア留学卒業後、エンジニアインターンをしてます。

>エンジニア留学|NexSeeed

主に、Swiftを使ったiOSアプリコースのティーチングアシスタントをしていて、生徒が作りたいアプリを開発するにあたって、詰まりそうな機能や必要な機能を先回りして作ってはヒントをあげたり、授業として解説したりしています。

そんな中で、マッチングアプリでお馴染みの「TinderのUI」が結構人気で、その実装方法を考えたので、紹介しようと思います。

Tinder風のUIのデモ

以下が今回作成した、Tinder風のUIのデモです。スワイプした方向にカードが飛んでいき、スワイプする方向によって処理を変えることができます。リセットボタンを押すと、元に戻ります。

Tinder風UI実装の仕方

1.UIの配置について

画面には、2つのUIViewにそれぞれUIImageViewが追加されています。複数枚カードがあるように見えますが、「frontCard」と「backCard」の2枚だけです。

手前にある「frontCard」にのみ、画面をスワイプした時に処理を行う「Pan Gesture Recognitionnizer」がついています。

手前の「frontCard」のみが動き、「backCard」は静止したままで、スワイプされた時「frontCard」がどこかへ行ってしまうように見えますが、実際は行った後すぐに元の位置に戻っています。中の画像の情報のみが移動していく仕組みになっています。その処理について、詳しく考えていきます。

2.スワイプした時の処理について

スワイプした時に、スワイプした距離に応じて、x座標を動かし、画面の大きさに対して、スワイプした割合に応じて、カードを傾ける処理を書きます。

//手前のカードをスワイプした分だけ、横に動かし、動かした距離に応じて回転させる。
//「point.x」に0.1をかけているのは、スワイプした時に動きすぎないようにするため。

//スワイプした時にx座標だけ動かす。
swipeCard.center = CGPoint(x: swipeCard.center.x + point.x * 0.1,y:swipeCard.center.y)
//Max45度の傾き。スワイプした距離に応じて傾きを変える
swipeCard.transform = CGAffineTransform(rotationAngle: swipeDistanceX/(view.frame.width/2) * -0.785)

スワイプした時の処理に関しては、スワイプして指が離れた時点で、小さくスワイプしていた場合と、大きくスワイプした場合で分けます。

//スワイプの指が離れたときの処理.
if sender.state == UIGestureRecognizerState.ended{
    //処理を記入
    //左に大きく振れた時
    if swipeCard.center.x < self.screenWidth/5 {
        UIView.animate(withDuration: 0, animations: {

        })
    }
    //右に大きく振れた時
    else if swipeCard.center.x > self.screenWidth - self.screenWidth/5{
        UIView.animate(withDuration: 0, animations: {

        })
    }
    //小さく振れた時
    else {
        UIView.animate(withDuration: 0.2, animations: {

        })
    }
}

 

カードを小さくスワイプした時は、元の位置に戻します。

//小さく振れた時、カードを元の位置に戻す
swipeCard.center = CGPoint(x: self.cardCenter.x,y:self.cardCenter.y)
swipeCard.transform = .identity

 

カードを大きくスワイプした時は、以下の手順で処理を実装します。以下には左側にスワイプした時の処理しか書いていませんが、右側にスワイプした場合の処理も同様に実装することができます。

スワイプした方向にカードを飛ばす。

swipeCard.center = CGPoint(x: self.cardCenter.x + self.screenWidth,y:self.cardCenter.y)

 

飛ばしたカードの情報を保持する(処理する)。

self.leftInfo.append(self.imageList[self.cardNum])
print("左スワイプデータ:",self.leftInfo)

 

飛ばしたカードを透明にする。

swipeCard.alpha = 0

 

透明にした後、カードを元の位置に戻す。この時、「frontCard」と「backCard」の両方が画面に存在するが、「frontCard」は透明なので、「backCard」のみが見えている状態になります。

swipeCard.center = CGPoint(x: self.cardCenter.x,y:self.cardCenter.y)
swipeCard.transform = .identity

 

「frontCard」カードに、「backCard」の情報を入れます。同じデザインのカードが2枚ある状態で、手前は透明です。

self.frontCardImage.image = self.backCardImage.image

 

「frontCard」カードを見えるようにする。

swipeCard.alpha = 1

 

最後に「backCard」に次の要素の情報を入れます。この時、最後から2枚目の場合と最後のカードの場合は場合分が必要になります。「backCard」に入れる情報がなくなり、「Out of range」のエラーがでてしまうので。

//(1)カードが残り2枚になるまで
if self.cardNum &lt; self.imageCount - 2{
  self.cardNum += 1
  self.nextCard += 1
  self.backCardImage.image =   UIImage(named:self.imageList[self.nextCard])
//(2)カードが残り2枚の時
}else if self.cardNum == self.imageCount - 2{
  self.cardNum += 1
  self.backCard.alpha = 0
//カードが残り1枚の時
}else if self.cardNum == self.imageCount - 1{
  self.frontCard.alpha = 0
  print("カードがなくなりました。")
}
スポンサードリンク

3.リセットボタンについて

リセットボタンを押した後は、以下のように、初期値に戻せばリセット完了です。

rightInfo = []
leftInfo = []
cardNum = 0
nextCard = 1
frontCardImage.image = UIImage(named:imageList[cardNum])
backCardImage.image = UIImage(named:imageList[nextCard])
frontCard.alpha = 1
backCard.alpha = 1

GitHub

ソースコードは以下に挙げているので参考にしながら実装してみてください。

https://github.com/togamin/TinderUISample2.git

まとめ

TinderのUIを実装しました。実装の際は結構頭を使うので、プログラミングの良い練習になるかと思います。

また、下記がインターンをしているNexSeedという「プログラミング×英語」の勉強ができるセブにある学校です。

起業志向の人や、フリーランスを目指す人等、意識の高い人が多く、自分も良い刺激をもらっています。

留学を考えているけど、英語だけじゃ物足りないと感じる人、起業やフリーランスとして働くことを見据えている人は是非見てみてください!

 

スポンサードリンク