Swift de 脳トレアプリ 第1章

ボケが始まったのか、最近忘れ物・忘れ事が増えてきました←
本格的に脳トレをしないとと思い始めている日々でございます…
そんなわけで!(どんなわけで)
今回はSwift de 脳トレアプリシリーズでございます!
第1章 目次
- 前置き
- タイトル画面を作っていこう
前置き
前回の序章を投稿した後にXcodeのアップデートをしたので、改めて以下の開発環境で進めていきます。
- MacOS High Sierra 10.13.6
- Swift 4.2.1
- Xcode 10.1
バージョンは随時更新していきますので、以降は本シリーズのGitHubのREADMEをご確認ください!
また、あくまでSwift4の書き方が伝わったらいいなーと思いこのシリーズを進めていきますので、
なるべくXcodeのStoryboardはなるべく使わない方向でいきます。
デザインや機能がダサくなるかもしれませんが、そこはお手柔らかに見ていただけると幸いです。
え、決してハードルを下げてるわけでは←
さて前置きが長くなりましたが、早速第1章の本編といきましょう!
タイトル画面を作っていこう
さて、アプリといえばタイトル画面。
アプリの顔とも言えますから、初回にはもってこいですね。
というわけで作っていきましょう。
以下は画面の完成イメージ図です。
あぁデザインがひどすぎる←
この素人デザインは決して真似しないでください←
学ぶならこちらの記事を参考にしてください!!(切実に
→ 0から1を生む為に〜design編〜|タイトルロゴの作成
…気を取り直して。
このイメージ通りにViewController
から要素を配置していきます。
// class TitleViewController
override func viewDidLoad()
{
super.viewDidLoad()
// write here
}
UIViewController
にあるライフサイクルメソッドのviewDidLoad()内に描画する処理を書いていきます。
ちなみにこのライフサイクルは、メソッド名の通りviewのloadが終わった後に実行されます。
文字を配置
では早速、タイトルと画面下の文字を配置しましょう。
前回の序章では使いませんでしたが、正確なレイアウトをするためにAutoLayout
を使用していきます。
まずそれぞれのUILabel
の基本情報をプロパティに定義しておきます。
// class TitleViewController
let titleLabel: UILabel = {
let label = UILabel()
label.text = "Brain Training"
label.textAlignment = .center
label.textColor = UIColor.black
label.font = UIFont.systemFont(ofSize: 24.0, weight: .bold)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let navigateLabel: UILabel = {
let label = UILabel()
label.text = "TAP TO START"
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 20.0, weight: .bold)
// ColorAsset (iOS 11.0 以上対応)
label.textColor = UIColor(named: "textGray")
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
テキストとフォントサイズ、色の設定ですね。
navigateLabelだけ色の指定にiOS11.0から対応になったColorAsset
を使用してみました。
設定方法はXcodeからでも、jsonファイルでも可能です!
XcodeからのColorAssetの設定方法は以下を参考にしてください。
→ [iOS 11][Xcode 9][新機能] Asset Catalogで色を定義できるようになりました | DevelopersIO
translatesAutoresizingMaskIntoConstraints
はAutoLayoutを使う上で必ずfalseにする必要があるので忘れずに!←よく忘れる人が言ってます
次にAutoLayoutの設定とviewにUILabelを追加していきます。
// class TitleViewController
override func viewDidLoad()
{
// 省略
// タイトル
view.addSubview(titleLabel)
var xConstraint = NSLayoutConstraint(item: titleLabel, attribute: .centerX, relatedBy: .equal,
toItem: view, attribute: .centerX, multiplier: 1,
constant: 0)
var yConstraint = NSLayoutConstraint(item: titleLabel, attribute: .centerY, relatedBy: .equal,
toItem: view, attribute: .centerY, multiplier: 1,
constant: 0)
NSLayoutConstraint.activate([xConstraint, yConstraint])
// 画面下の文字
view.addSubview(navigateLabel)
xConstraint = NSLayoutConstraint(item: navigateLabel, attribute: .centerX, relatedBy: .equal,
toItem: view, attribute: .centerX, multiplier: 1, constant: 0)
yConstraint = NSLayoutConstraint(item: navigateLabel, attribute: .bottom, relatedBy: .equal,
toItem: view, attribute: .bottom, multiplier: 1, constant: -40)
NSLayoutConstraint.activate([xConstraint, yConstraint])
}
viewにaddSubview
で要素追加、AutoLayoutにはNSLayoutConstraintを使います。
タイトルは画面中央に配置するため、viewのcenterX
とcenterY
と一致するように指定しています。
画面下の文字は同じようにviewのcenterX
と、viewの下bottom
から40離れた位置に来るように指定しました。
これで文字の配置は完了です!
画像を配置
続いてタイトル文字の後ろの画像を配置します。
使用する画像は予めproject名/Assets.xcassets
に追加しているものとします。
Xcodeからの追加方法は以下を参考にしてください。
→ Xcodeの概要:画像を追加する
こちらもUILabelと同じように基本情報をプロパティに定義します。
// class TitleViewController
let logoBrainImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "logo_brain"))
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
UIImageView
にどの画像を使うか指定しているだけですね。単純!
こちらにもAutoLayoutを入れましょう。
// class TitleViewController
override func viewDidLoad()
{
// 省略
let widthConstraint = NSLayoutConstraint(item: logoBrainImageView, attribute: .width,
relatedBy: .equal, toItem: nil,
attribute: .notAnAttribute, multiplier: 1.0,
constant: 210)
let heightConstraint = NSLayoutConstraint(item: logoBrainImageView, attribute: .height,
relatedBy: .equal, toItem: nil,
attribute: .notAnAttribute, multiplier: 1.0,
constant: 188.5)
let xConstraint = NSLayoutConstraint(item: logoBrainImageView, attribute: .centerX,
relatedBy: .equal, toItem: view, attribute: .centerX,
multiplier: 1, constant: 0)
let yConstraint = NSLayoutConstraint(item: logoBrainImageView, attribute: .centerY,
relatedBy: .equal, toItem: view, attribute: .centerY,
multiplier: 1, constant: 0)
NSLayoutConstraint.activate([widthConstraint, heightConstraint, xConstraint, yConstraint])
}
配置自体は画面中央ということでcenterXとcenterYの指定はタイトルの文字と同じですが、画像はサイズの指定も必要です。
今回はデザインに合わせるということで、width
とheight
に直接指定しました。
これで画像の配置も完了です!
背景グラデーションを配置
次は背景の放射状のグラデーション。
画像を用いてもいいのですが、CALayerでも再現できます。
CALayerはUIViewではできない細かい描画で色々と便利です。
ちょっとここの処理は初心者の方には難しく感じてしまうかもしれませんが、ざっくり噛み砕いて説明していきます。
描画するdrawメソッドをoverrideしたいので、CALayerを継承した専用のクラスを作りました。
→ コード全文はこちらから
ありがたいことに、描画用クラスCGContextにdrawRadialGradient()という放射グラデーション作成専用のメソッドが用意されていますのでそちらを使いましょう。
以下は描画処理の抜粋です。
// class GradientLayer
override func draw(in ctx: CGContext)
{
ctx.saveGState()
let colorSpace = CGColorSpaceCreateDeviceRGB()
let locations: [CGFloat] = [0.0, 1.0]
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray,
locations: locations)
let center = CGPoint(x: bounds.width / 2.0, y: bounds.height / 2.0)
let radius = min(bounds.width + 100, bounds.height + 100)
ctx.drawRadialGradient(gradient!, startCenter: center, startRadius: 0.0, endCenter: center,
endRadius: radius, options: CGGradientDrawingOptions(rawValue: 0))
ctx.restoreGState()
}
先ほどのメソッドに描きたいグラデーションのパラメータを指定してやるだけです。
今回は2色しか使用しないのでcolors
には白とグレー。
各色のグラデーションの位置locations
には0と1、つまりグラデーションの開始と終了位置だけ指定しました。
あとは円形がはみ出すようにしたいので、radius
に幅と高さにそれぞれ100上乗せしています。
画面のタッチイベント
タイトル画面といえば、画面をタップした後に次の画面に進む。
というのが一般的ですね。
次の画面はまだありませんが、どこに処理を書くかだけ用意してしまいましょう。
と言っても非常に単純です。
UIViewControllerにタッチ終了時に実行されるtouchesEndedメソッドがあるので、そこに次の画面への遷移処理を書くだけです。
// class TitleViewController
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)
{
// ここに次の画面への遷移処理を書く
print("route to next")
}
完成
これで置きたい要素はすべてですね。
シュミレータで動かしてみましょう!
ちょっと遊びで文字に影、画像にアニメーションをつけてみました!
というわけで続きは次章へ!!
おまけ
Xcodeでアプリのアイコン設定をしました。といってもAssetsに設定するだけなので簡単です。
設定方法は以下を参考にしてください。
→ (初心者向け)Swift3.0で初アプリ – アイコンを登録してみる – Qiita
ちなみにシュミレータのHOMEだとこのような感じに表示されます。
最後に
今回はまだ内容量の少ないタイトル画面の作成でしたので、割とシンプルだったでしょうか。
要素を配置するだけなら割とコード量も少なく、思ったままに書けますね。
時間の都合とテクニックの問題から、説明を割愛してしまった箇所がありますが、
そちらはまた別の章あるいは番外編でご紹介できたらなと思います!
いやーそれにしても素人デザインを公開してしまったことが精神的ダメージです←
(くれぐれもデザインだけは参考になさらぬように)
次章予告
- トップ画面を作っていこう (1)
参考
- UIKitのView表示ライフサイクルを理解する – Qiita
- UILabel – UIKit | Apple Developer Documentation
- ios – How to add constraints programmatically using Swift – Stack Overflow
- UIImageView – UIKit | Apple Developer Documentation
- iOS – iosアプリ 背景の放射状グラデーション|teratail
- ios – Animate UIImage in UIImageView Up & Down (Like it’s hovering) Loop – Stack Overflow
Swift de 脳トレアプリシリーズはGitHubに公開しています!