BRFlabbyTable
グニャグニャと動くUItableViewです。(リンク先参照)
有機的な動きはSkypeなどでも取り入れられています。
フラットデザインとの相性も良く、見栄えも良いのでこれを自在に使えたらカッコイイですよね!
BRFlabbyTableはApache licenceの元で利用することが出来ます。
折角OSSなので、どのような仕組みなのか見て行きましょう。
今回はReleaseバージョンの1.0.0を利用しています。
BRMainViewController
まずはサンプルを開いて、メインのViewControllerを見てみましょう。
ここでBRFlabbyTableの使い方や構造がわかります。
まずはdelegateから。
ここで登場するdelegateは3つ
UITableViewDelegate UITableViewDataSource BRFlabbyTableManagerDelegate
です。
UITableViewDelegate
とUITableViewDataSource
は、別段解説する必要は無いと思います。
一点、
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
でUITableViewCellではなく、BRFlabbyTableViewCellを返している部分に注目してください。
つまり、BRFlabbyTableは独自のtableViewなのではなく、UITableViewCellによる実装で作られているということです。
そして、BRFlabbyTableManagerDelegate
ですが、ここでは
- (UIColor *)flabbyTableManager:(BRFlabbyTableManager *)tableManager flabbyColorForIndexPath:(NSIndexPath *)indexPath
というメソッドだけがあります。
ここでは、特定IndexPathの背景色を返します。
以上でViewController部分の説明は終わりです。
カッコイイ見た目のわりにはUITableViewの使い方を崩さずに実装でき、既存のプロジェクトのUITableView部分を入れ替えれば実装出来るという親和性の高いOSSですね。
次にいよいよソースを見て行きましょう。
BRflabbyTableのソース
BRflabbyTableの構造は大きく分けて3つ
BRFlabbyTableManager BRFlabbyTableViewCell NSIndexPath+BRFlabbyTable
です。
BRFlabbyTableViewCell
このCellはUITableViewCellを継承しており、BRFlabbyTableManagerで指定された通りに描画を行います。
その為、drawrectがソースの大半を占めています。
drawrectでの動作は大きく分けて2つ
_flabbyHighlightState == BRFlabbyHighlightStateCellTouched || !_isFlabby || (fabs(_verticalVelocity) < 1.0 && _flabbyHighlightState == BRFlabbyHighlightStateNone)
の時の動作、これは一言でいえば「静止時の動作」です。
ごちゃごちゃ条件がついていますが、しきい値やタップのステートの条件になります。
ここでしているのは簡単で
CGContextSetFillColorWithColor(ctx, [_flabbyColor CGColor]);
CGContextFillRect(ctx, rect);
と、ただCellを塗っているだけです。
もう片方は先ほどの条件をelseした部分、つまり指を乗せたりスクロールしたりして有機的な動きをしているのを描画している部分です。
先ほど同様Cell全体を塗った上で3つの分岐をしています。
switch (_flabbyHighlightState) {
case BRFlabbyHighlightStateCellAboveTouched:
controlPointX1 = _touchXLocationInCell + x;
controlPointX2 = _touchXLocationInCell + x;
controlPointX3 = x + (w/2 + x) + (w - (w/2 + x))/2;
controlPointX4 = (x + (w/2 + x))/2;
controlPointY1 = HIGHLIGHT_Y_CONTROL_POINT;
controlPointY2 = y+h+controlYOffset;
CGContextSetFillColorWithColor(ctx, [_flabbyColorAbove CGColor]);
CGContextFillRect(ctx, CGRectMake(x, y, w, h/2));
break;
case BRFlabbyHighlightStateCellBelowTouched:
controlPointX1 = (x + (w/2 + x))/2;
controlPointX2 = x + (w/2 + x) + (w - (w/2 + x))/2;
controlPointX3 = _touchXLocationInCell + x;
controlPointX4 = _touchXLocationInCell + x;
controlPointY1 = controlYOffset;
controlPointY2 = y+h-HIGHLIGHT_Y_CONTROL_POINT;
CGContextSetFillColorWithColor(ctx, [_flabbyColorBelow CGColor]);
CGContextFillRect(ctx, CGRectMake(x, y+h/2, w, h/2));
break;
default:
controlPointX1 = (x + (w/2 + x))/2;
controlPointX2 = x + (w/2 + x) + (w - (w/2 + x))/2;
controlPointX3 = controlPointX2;
controlPointX4 = controlPointX1;
controlPointY1 = y+controlYOffset;
controlPointY2 = y+h+controlYOffset;
break;
}
この分岐はそれぞれ
このように指を置いているCellを中心に上下のセルの指定をしています。
ここで勘の良い人は気が付くと思いますが、このBRflabbyTableは目の錯覚が利用されているわけです。
そう、中央のセルは決して上下にはみ出しているわけではなく上下のセルではみ出した部分を描画しているわけです。
黄色と青の部分が上下のセルで描画されている部分です。
スクロールの際は、方向に合わせてすべてBRFlabbyHighlightStateCellAboveTouchedかBRFlabbyHighlightStateCellBelowTouchedにすればよいわけです。
描画はX1,X2,X3,X4とY1,Y2の組み合わせ4点を元に
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, x, y);
CGPathAddCurveToPoint(path, nil, controlPointX1, controlPointY1, controlPointX2, controlPointY1, x+w, y);
CGPathAddLineToPoint(path, nil, x+w, y+h);
CGPathAddCurveToPoint(path, nil, controlPointX3, controlPointY2, controlPointX4, controlPointY2, x, y+h);
CGPathCloseSubpath(path);
CGContextAddPath(ctx, path);
CGContextSetFillColorWithColor(ctx, [_flabbyColor CGColor]);
CGContextFillPath(ctx);
CGPathRelease(path);
このようなコードでカーブを描いています。
それぞれの点を描画すると以下のような位置になります。
上下のカーブをそれぞれ2点で描いているわけです。
というわけで、BRflabbyTableの有機的なUITableViewCellは目の錯覚を利用しセルがはみ出ているように見せているというトリックでした。
また利用している描画関数もカーブ関数ぐらいなので中身を見てみると以外にも(良い意味で)シンプルな構造だったというわけです。
もっと興味のある方はBRFlabbyTableManager
やNSIndexPath+BRFlabbyTable
も覗いてみるといいかもしれません。
NSIndexPath+BRFlabbyTable
では前と後ろの色を取得する部分、BRFlabbyTableManager
ではタップ位置を取得する部分を見ることが出来ます。
いじょ