web-dev-qa-db-ja.com

iOSでシャドウを実行する最速の方法は?

QuartzCore.layer.shadowのサックアップパフォーマンス。何かが変わるたびに再レンダリングする必要があるようで、すべてが遅れます。

Coregraphicsグラデーション(一方向の影の場合)-正しく表示されません。グラデーションが0.3アルファから0になると、停止するのを「見る」ことができる奇妙な効果があります。見た目も自然でもありません。ディザリングされていないかもしれませんが、コアグラフィックスのグラデーションはディザリングされていると聞いたと思います。変だ、わからない。

Coregraphicsシャドウ-設定時にレンダリングに時間がかかりますが、それ以外の場合は優れたパフォーマンスを発揮します。ビューが最初にシャドウをレンダリングする必要があるため、ビューが表示されるのを待っているのはその秒です。それが問題です。

だから私は何かが欠けているに違いない。正しく見え、レンダリング時間とパフォーマンスの両方で高速な別の方法はありますか?

36
Andrew

ShadowPathを追加すると、パフォーマンスが大幅に向上します。次の例では、ビューの側面にのみ影が必要であると想定しています。

CGPathRef path = [UIBezierPath bezierPathWithRect:view.bounds].CGPath;
[view.layer setShadowPath:path];

EDIT:デフォルトでは、CALayerはアニメーション中に影を描画します。次のコードを使用すると、影をビットマップとしてキャッシュし、再描画する代わりに再利用できます。

self.view.layer.shouldRasterize = YES;
// Don't forget the rasterization scale
// I spent days trying to figure out why retina display assets weren't working as expected
self.view.layer.rasterizationScale = [UIScreen mainScreen].scale;
105
aryaxt

[〜#〜]巨大な[〜#〜]パフォーマンスインパクトビューのレイヤーを使用して、丸い角やドロップシャドウを作成している人をよく見かけます。このようなもの:

[v.layer setCornerRadius:30.0f];
[v.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[v.layer setBorderWidth:1.5f];
[v.layer setShadowColor:[UIColor blackColor].CGColor];
[v.layer setShadowOpacity:0.8];
[v.layer setShadowRadius:3.0];
[v.layer setShadowOffset:CGSizeMake(2.0, 2.0)];
.....

これは、特にシャドウの場合、[〜#〜]巨大な[〜#〜]のパフォーマンスに影響を与えます。このようなビューをUITableView(または実際には動くもの)に配置すると、Android風のスクロールエクスペリエンスが作成されますが、これは望ましくありません。ビューをアニメートまたは移動する必要がある場合は、このような丸い角を作成したり、シャドウをドロップしたりしないでください。

コアグラフィックスに会う
少し異なる方法で同じ結果を達成する方法を示すために、単純なUIViewサブクラスを作成しました。 Core Graphicsを使用してビューを描画し、上記のコードとは対照的に、パフォーマンスに影響を与えません。

描画コードは次のとおりです。

- (void)drawRect:(CGRect)rect
{
   CGContextRef ref = UIGraphicsGetCurrentContext();

  /* We can only draw inside our view, so we need to inset the actual 'rounded content' */
  CGRect contentRect = CGRectInset(rect, _shadowRadius, _shadowRadius);

  /* Create the rounded path and fill it */
  UIBezierPath *roundedPath = [UIBezierPath bezierPathWithRoundedRect:contentRect cornerRadius:_cornerRadius];
  CGContextSetFillColorWithColor(ref, _fillColor.CGColor);
  CGContextSetShadowWithColor(ref, CGSizeMake(0.0, 0.0), _shadowRadius, _shadowColor.CGColor);
  [roundedPath fill];

  /* Draw a subtle white line at the top of the view */
  [roundedPath addClip];
  CGContextSetStrokeColorWithColor(ref, [UIColor colorWithWhite:1.0 alpha:0.6].CGColor);
  CGContextSetBlendMode(ref, kCGBlendModeOverlay);

  CGContextMoveToPoint(ref, CGRectGetMinX(contentRect), CGRectGetMinY(contentRect)+0.5);
  CGContextAddLineToPoint(ref, CGRectGetMaxX(contentRect),   CGRectGetMinY(contentRect)+0.5);
  CGContextStrokePath(ref);
 }

このブログを参照してください: http://damir.me/rounded-uiview-with-shadow-the-right-way

9
Omar Freewan