はじめに
ライブラリ(Koloda)を使用し、Tinder風のUIを作成しました
スワイプできるカードをコードで書いており、何か別の場面でも活かせることができるのではないかと考えたため共有します
なるべくコピペでビルドすることができるようにしましたので、是非試してみてください
誰かのお役に立てれば幸いです
完成図
準備
下記の記事を参考にライブラリのインストール、koladaViewを準拠したviewの作成まで行ってください
またviewcontrollerに、imageが入った配列(imageArray)を用意したください
private let imageArray = ["", "", ""]
自分で作成したのはこんな感じ
画像内にあるKolodaViewに関しては、横幅が端末の0.96倍、この横幅に対して高さを1.2倍に設定し
上下左右中央に配置しています
@IBOutlet weak var kolodaView: KolodaView!
ここからスワイプできるカードを作成していきます
コード
viewcontrollerにライブラリをimport
import Koloda
delegate, datasourceを忘れずに
override func viewDidLoad() {
super.viewDidLoad()
kolodaView.delegate = self
kolodaView.dataSource = self
}
Tinder風のカードの作成
※コピペで作成できます!
extension ViewController: KolodaViewDataSource {
// 表示内容
func koloda(_ koloda: Koloda.KolodaView, viewForCardAt index: Int) -> UIView {
// cardView 全体のview
let userCardView = UIView(frame: koloda.bounds)
userCardView.layer.cornerRadius = 8
userCardView.clipsToBounds = true
userCardView.contentMode = .scaleAspectFill
// subview 相手の情報を表示するview
let subView = UIView(frame: CGRect(x: 0, y: userCardView.frame.height * 0.72,
width: userCardView.frame.width, height: userCardView.frame.height * 0.28))
subView.backgroundColor = .black.withAlphaComponent(0.1)
let imageView = UIImageView(frame: koloda.bounds)
imageView.image = UIImage(named: imageArray[index])
imageView.backgroundColor = .white
imageView.contentMode = UIView.ContentMode.center
// 名前・年齢を表示するStackView
let infoStackView = UIStackView()
let stackWidth:CGFloat = subView.frame.width * 0.7
let stackHeight:CGFloat = subView.frame.height / 2
// infoStackViewの大きさを決める
let rect: CGRect = CGRect(x: 0, y: 0, width: stackWidth, height: stackHeight)
// stackviewの位置を決定(名前、年齢、地域)
infoStackView.frame = rect
infoStackView.center = CGPoint(x: subView.frame.width / 2, y: userCardView.frame.height * 0.76)
infoStackView.backgroundColor = .clear
infoStackView.distribution = .fillEqually
infoStackView.alignment = .fill
infoStackView.spacing = 2.0
// 名前ラベルの設定
let nameStringLabel = UILabel()
nameStringLabel.text = "相手の名前"
nameStringLabel.textAlignment = .right
nameStringLabel.textColor = .white
nameStringLabel.backgroundColor = .clear
nameStringLabel.frame = CGRect(x: 0, y: 0, width: infoStackView.frame.width / 2, height: infoStackView.frame.height)
nameStringLabel.font = UIFont.boldSystemFont(ofSize: 23)
infoStackView.addArrangedSubview(nameStringLabel)
// 地域、年齢ラベル
let ageRegionLabel = UILabel()
ageRegionLabel.text = " 30歳・東京都"
ageRegionLabel.textAlignment = .left
ageRegionLabel.textColor = .white
ageRegionLabel.backgroundColor = .clear
ageRegionLabel.frame = CGRect(x: 0, y: 0, width: infoStackView.frame.width / 2, height: infoStackView.frame.height)
ageRegionLabel.font = UIFont.systemFont(ofSize: 16, weight: .medium)
infoStackView.addArrangedSubview(ageRegionLabel)
// ユーザーのstatusを表示するStackView
let userStatusStackView = UIStackView()
let statusStackWidth:CGFloat = subView.frame.width * 0.8
let statusStackHeight:CGFloat = subView.frame.height * 0.3
let statusRect: CGRect = CGRect(x: 0, y: 0, width: statusStackWidth, height: statusStackHeight)
// stackviewの位置を決定
userStatusStackView.frame = statusRect
userStatusStackView.center = CGPoint(x: userCardView.frame.width / 2, y: userCardView.frame.height * 0.86)
userStatusStackView.backgroundColor = .clear
userStatusStackView.distribution = .fillEqually
userStatusStackView.alignment = .fill
userStatusStackView.spacing = 5
// 趣味ラベル
let hobbyLabel = UILabel()
hobbyLabel.text = "サッカー"
hobbyLabel.textAlignment = .center
hobbyLabel.textColor = .white
hobbyLabel.backgroundColor = .systemPink
hobbyLabel.frame = CGRect(x: 0, y: 0,
width: userStatusStackView.frame.width / 3.3,
height: userStatusStackView.frame.height)
hobbyLabel.font = UIFont.systemFont(ofSize: 16, weight: .medium)
hobbyLabel.layer.cornerRadius = 20
hobbyLabel.clipsToBounds = true
userStatusStackView.addArrangedSubview(hobbyLabel)
// 性格のラベル
let personalityLabel = UILabel()
personalityLabel.text = "穏やか"
personalityLabel.textAlignment = .center
personalityLabel.textColor = .white
personalityLabel.backgroundColor = .systemPink
personalityLabel.frame = CGRect(x: 0, y: 0,
width: userStatusStackView.frame.width / 3.3,
height: userStatusStackView.frame.height)
personalityLabel.font = UIFont.systemFont(ofSize: 16, weight: .medium)
personalityLabel.layer.cornerRadius = 20
personalityLabel.clipsToBounds = true
userStatusStackView.addArrangedSubview(personalityLabel)
// スタイルラベル
let bodyStyleLabel = UILabel()
bodyStyleLabel.text = "スリム"
bodyStyleLabel.textAlignment = .center
bodyStyleLabel.textColor = .white
bodyStyleLabel.backgroundColor = .systemPink
bodyStyleLabel.frame = CGRect(x: 0, y: 0, width: userStatusStackView.frame.width / 3.3,
height: userStatusStackView.frame.height)
bodyStyleLabel.font = UIFont.systemFont(ofSize: 16, weight: .medium)
bodyStyleLabel.layer.cornerRadius = 20
bodyStyleLabel.clipsToBounds = true
userStatusStackView.addArrangedSubview(bodyStyleLabel)
// viewを描画する
userCardView.addSubview(imageView)
userCardView.addSubview(subView)
userCardView.addSubview(infoStackView)
userCardView.addSubview(userStatusStackView)
return userCardView
}
func kolodaNumberOfCards(_ koloda: KolodaView) -> Int {
imageArray.count
}
}
解説
UIViewの作成方法
userCardView を最初に定義しています
ここに後々作成していくStackViewなどをaddSubViewしていきます
// cardView 全体のview
let userCardView = UIView(frame: koloda.bounds)
userCardView.layer.cornerRadius = 8
userCardView.clipsToBounds = true
userCardView.contentMode = .scaleAspectFill
subViewには相手の情報を表示します
// subview 相手の情報を表示するview
let subView = UIView(frame: CGRect(x: 0, y: userCardView.frame.height * 0.72,
width: userCardView.frame.width, height: userCardView.frame.height * 0.28))
subView.backgroundColor = .black.withAlphaComponent(0.1)
y: userCardView.frame.height * 0.72
height: userCardView.frame.height * 0.28
subViewをuserCardViewのheightの0.72の地点から、0.28分の大きさのviewと定義することができています
StackViewの作成方法
// ユーザーのstatusを表示するStackView
let userStatusStackView = UIStackView()
let statusStackWidth:CGFloat = subView.frame.width * 0.8
let statusStackHeight:CGFloat = subView.frame.height * 0.3
let statusRect: CGRect = CGRect(x: 0, y: 0, width: statusStackWidth, height: statusStackHeight)
// stackviewの位置を決定
userStatusStackView.frame = statusRect
userStatusStackView.center = CGPoint(x: userCardView.frame.width / 2, y: userCardView.frame.height * 0.86)
userStatusStackView.backgroundColor = .clear
userStatusStackView.distribution = .fillEqually
userStatusStackView.alignment = .fill
userStatusStackView.spacing = 5
下記の部分で大きさを決定し、後述の.centerで位置を確定させています。
let userStatusStackView = UIStackView()
let statusStackWidth:CGFloat = subView.frame.width * 0.8
let statusStackHeight:CGFloat = subView.frame.height * 0.3
let statusRect: CGRect = CGRect(x: 0, y: 0, width: statusStackWidth, height: statusStackHeight)
userStatusStackView.center = CGPoint(x: userCardView.frame.width / 2, y: userCardView.frame.height * 0.86)
ここにLabelであったり、自分の好きなパーツを入れてください!
自分がハマったポイント
- 作成したviewが表示されているのか、どこの位置にあるかわからない → backgroundColorに派手な色を入れるとわかりやすい
- StackViewは、addArrangedSubviewじゃないと反映されない
- コードで部品を作成する際は、必ず.frameを定義しないといけないこと
- 最後実際にaddSubViewする際は、階層が下のものから描画させるようにしないと、表示されない場合があること
最後に
codeでviewを描画するのは初めてでしたが、かなり勉強になりました。
次はautoLayoutを使ってコードでviewを書いてみたいと思います。
また、処理が冗長すぎるので、リファクタリングした際は、加筆していきたいです。
弊社では、経験の有無を問わず採用を行っています。
興味のある方は是非カジュアル面談しましょう!