Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

TODOリストを表示する #1

Open
ginrou opened this issue Mar 19, 2015 · 1 comment
Open

TODOリストを表示する #1

ginrou opened this issue Mar 19, 2015 · 1 comment

Comments

@ginrou
Copy link
Contributor

ginrou commented Mar 19, 2015

TODOアプリを作ってみようシリーズの第一回目の演習課題のTODOです

内容

UITableViewを利用して、TODOリストを表示します。TODOはコード内にハードコードしたものを用いて、追�加などは行いません。

目的

UITableViewの使い方を理解する。以下のクラスの関係や基本的な使い方を学習することを目的としています。

  • UITableViewDelegate
  • UITableViewDataSource
  • UITableViewCell

また UITableViewCellをサブクラス化してカスタマイズも行います

アプリの仕様

以下のTODOをUITableViewを利用して表示します。
長いTODOも折り返して、全文が表示されるようにしてください。
(一部TODOらしくないTODOもあるのはそのサンプルです)

NSArray *todo = @[@"牛乳を買ってくる",
                  @"ビールを飲む",
                  @"家賃の振り込み",
                  @"洗剤を買い足す",
                  @"Macのアップデート",
                  @"ルンバの充電",
                  @"結婚式の招待状に返信する",
                  @"犬の散歩",
                  @"雨ニモマケズ 風ニモマケズ 雪ニモ夏ノ暑サニモマケヌ 丈夫ナカラダヲモチ 慾ハナク 決シテ瞋ラズ イツモシヅカニワラッテヰル 一日ニ玄米四合ト 味噌ト少シノ野菜ヲタベ アラユルコトヲ ジブンヲカンジョウニ入レズニ ヨクミキキシワカリ ソシテワスレズ",
                  @"ビールを飲む"
                  ];

またTODOを表示するセルは以下のレギュレーションに従ってください.
2015-03-25 1 38 24 pm

動作イメージ

2015-03-19 9 11 07 pm

実装のステップ

tableViewを表示する 6974b40

UITableViewをメインのViewControllerの上に配置し、Autolayoutを設定します。
Autolayoutのpinの仕方は任意ですが、上下左右のマージンを0にするのがベターです。
さらにViewControllerのプロパティとして追加します。

セルを表示する cac9ebf

  • プロパティとして todo を追加
  • TableViewで利用するセルを登録 (クラスはUITableViewCellを利用)
  • tableViewのdataSourceとしてselfを指定
  • UITableViewDataSourceプロトコルに準拠し、プロトコルのメソッドを実装
    • tableView:numberOfRowsInSection: はtodoの個数を返します
    • tableView:cellForRowAtIndexPath は表示したいセルを返します

カスタムセルの追加 1bd803f a97f4cf

TodoTableViewCellという名前で新しいクラスを追加(xibも同時に作る)
カスタムセルの実装

  • xib上にUILabelを置いて、制約を貼る (とりあえず上下左右にpin)
  • レギュレーションを反映する
  • xib上で、UILabelのLinesを0にする
  • xib上のUILabelをソース上から参照できるようにプロパティを作りIBOutletで接続 (todoLabelという名前)
  • 登録するセルをUITableViewCellからTodoTableViewCellに変更
    • registerNibを使う
    • importを忘れない
  • cellForRowAtIndexPath でdequeするセルの結果をUITableViewCellからTodoTableViewCellに変更
  • todoLabel.textに値を入れる

高さの制御 dc8911b

  • UITableViewはセルの中身よりも先に高さを計算して返す必要がある
    heightForRowAtIndexPathが全部のセルに対して呼ばれ、cellForRowAtIndexPathが表示のタイミングで呼ばれる
  • 高さ計算計算用のセルを予め作っておき、そこでレイアウトさせて高さを算出する

※ iOS8以降の場合はAutolayoutを正しく設定することで自動的に高さを計算してくれる。iOS7以前もサポートする場合は、この高さの計算を行うメソッドを実装する必要があります。

ViewControllerがUITableViewDelegateに準拠するようにして、tableview.delegate = selfにする

プロパティに高さ計算用のセル(offscreenCell)を追加
@interface 
// 中略
@property (strong, nonatomic) TodoTableViewCell *offscreenCell;
// 中略
@end

// viewDidLoadなどの中で
self.offscreenCell = [nib instantiateWithOwner:nil options:nil][0];
offscreenCellのサイズを決定

tableViewがレイアウトされたタイミング(viewDidLayoutSubviews)でセルの横幅が決まる。
ここでoffscreenCellのサイズを決定する。(xibのサイズのままだと画面サイズが変わったときに対応できない)

この時ラベルに preferredMaxLayoutWidth を設定する。これをしないと複数行の表示が正しく行われない

高さを計算する

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath で各セルの高さを計算して返す

手順としては

  • セルにテキストを代入
  • セルにレイアウトを実行させる
  • セルのサイズから高さを求めて返す

その他情報

参照する教材

スタートするブランチ

start
※ Main.storyboard の initial view controller を指定し忘れたので、指定してください 😓

ここまでの完成品のブランチ

show-todo

@ginrou
Copy link
Contributor Author

ginrou commented Mar 26, 2015

Autolayoutのレンダリングを用いない場合は、以下のように表示するコンテンツのサイズを逐一計算します。

NSString *todo = self.todo[indexPath.row];
CGFloat maxWidth = CGRectGetWidth(tableView.bounds) - 8 - 8; // 8はラベルとセルの間の左右のマージン
CGSize maxSize = CGSizeMake(maxWidth, CGFLOAT_MAX);
NSDictionary *attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:17.0]};
CGRect rect = [todo boundingRectWithSize:maxSize
                                 options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:attribute
                                 context:nil];

CGFloat todoHeight = ceil(CGRectGetHeight(rect)); // rectの高さは小数点で返り、切り捨てると描画されない
CGFloat contentViewHeight = todoHeight + 8 + 8; // 8 はラベルとセルの間の上下のマージン
return contentViewHeight + 1; // contentViewとcellの間に1pxのマージンがあるので追加

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant