2011年12月4日日曜日

Resizeしたい

■ごく単純なこと(そして落とし穴)■

現在開発中のiPhoneアプリはTableViewにカスタマイズしたCellを置いてそこにdatabase.comから取ってきたデータを表示するだけのごく単純なものなのです。ええごく単純。

要件としてはorientation(画面の向き)に応じてcellの幅を変える必要があるぐらい。Autoresizingを使えばほんと簡単。

あと表示するデータが可変長文字列なので、cellの高さを変える必要があります。これも単純な話で、以下のコードをview controllerに書いてやればおk

- (CGFloat)tableView:(UITableView *)tableView 
     heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyCell *cell = (MyCell *)[self tableView:self.tableView
                       cellForRowAtIndexPath:indexPath];
    
    float width = cell.status.frame.size.width;
    CGSize bounds = CGSizeMake(width, self.tableView.frame.size.height);
    
    CGSize size = [cell.status.text sizeWithFont: cell.status.font 
                               constrainedToSize: bounds 
                                   lineBreakMode: cell.status.lineBreakMode];
    
    return MAX(size.height, ConstMinCellHeight);
}

なのですが…。このboundsがくせ者でした。当然、当然cell上に置いたUILabelの幅を使います。このLabelにもautoresizingを設定してますから、iPhoneを横向きにすると当然リサイズされます。しかし…boundsに入ってくるwidth、つまりUILabelのサイズは初期設定値のままでリサイズ後のwidthを返してくれません。


■毎度おなじみ試行錯誤地獄■

そこから約4時間ほど試行錯誤を繰り返しました。覚えている範囲で列挙すると:

  • とりあえずautoresizingのモードをあれこれ試す
  • 友人のアドバイスに従いboundsへのkey value notificationを使用
  • UILabelのサブクラスを作ってsetBounds/setFrame/drawRectなどをオーバーライド

で、最終的にわかったことは、「cellの中に置いたLabelの幅がわかるのは、tableViewのheightForRowAtIndexPathが呼ばれた後」ってことでした。

描画の仕組みから考えて、そんなことはないと思うのですが…現状でそれを知る方法が見つかりませんでした。とほほ。


■美しくない妥協案■

というわけで、deviceOrientationDidChangeでiPhoneの向きが変わったことを検出したら、そこで定数からラベル幅を算出する、という方法にしました…。一応、デバイスの規定値が変わってもそのまま動くようにはしてあるけど…どうも美しくないっす。

問題は、この方法は最初からわかっていたということで…「美しくないから」という理由だけで4時間試行錯誤してしまったのはどーなの?というあたり。まぁ時間単価で仕事しているわけじゃないから良いんだけど…困ったもんだ。

まぁ、あれだ、4時間の試行錯誤でいろいろ分かったこともあったから、そのうちそれらが花開く日も来るだろう、ということで…。

0 件のコメント:

コメントを投稿