LoginSignup
6
5

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-10-03

はじめに

どうも、とがみんです。現在、セブ島にあるプログラミングと英語の両方を学ぶことができるNexSeedという学校でエンジニアインターンをしています。

留学していた時の記事はこちらです。

>NexSeedでのセブ島エンジニア留学を振り返ってみる。

主に、Swiftを使ったiOSアプリ開発コースのティーチングアシスタントをしていて、

今は生徒たちが、それぞれiOSアプリのアイデアを考えて、その開発を頑張っているところです。

自分は生徒たちが実装したい機能、実装にあたって詰まりそうな機能を先回りして実装し、ヒントを出したり、その機能の実装方法を授業として解説したりしています。

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

Tinder風のUIのデモ

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

Tinder風UI実装の仕方

1.UIの配置について

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

手前にある「frontCard」にのみ、「Pan Gesture Recognitionnizer」がついています。

Tinder01.jpg

手前の「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 < 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("カードがなくなりました。")
  }

Tinder02.jpg

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

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

最後に

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

是非実装してみてください。

また、個人ブログ「とがみんブログ」も運営しているので、よければチェックしてみてください。

就職活動、心理学、脳科学、量子力学、とがみんの経験等、変なこと書いてます。

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5