21

UIView上書きで何かを描画する習慣があります

- (void)drawRect:(CGRect)rect

これは問題なく動作し、Retina スクリーンで鮮明な結果が得られます。

ただし、今は、図面の基になっているプロパティをアニメーション化できるようにしたいと考えています。アニメート可能なプロパティの作成は でのみ可能のようですCALayer。そのため、 で描画を行う代わりにUIView、カスタムCALayerサブクラスを作成し、内部で描画を行います。

- (void) drawInContext:(CGContextRef)ctx

drawRectこの関数では、 customの関数で使用したのとほぼ同じ描画コードを使用しますUIView

結果は同じように見えますが、網膜の解像度ではなく、ピクセル化されています (大きな正方形のピクセル)。

私が入れたら

self.contentsScale = [UIScreen mainScreen].scale;

私のdrawInContext実装の最初に、ピクセル化された結果の代わりに、ぼやけた結果が得られます(レンダリングがまだ非網膜解像度で実行され、その後網膜解像度にアップスケールされているかのように)。

で鋭い網膜パスをレンダリングする正しい方法はCALayers drawInContext何ですか?

ここにいくつかのスクリーンショットがあります(青い線は問題のカスタム図面の一部です。黄色の部分は単なるイメージです)

カスタム UIView の内部に描画drawRect:

ここに画像の説明を入力

カスタム CALayer 内に描画drawInContext:

ここに画像の説明を入力

最初drawInContextに設定して、カスタム CALayer 内に描画します。self.contentScale

ここに画像の説明を入力

完全を期すために、(の簡略化されたバージョンの) 描画コードを次に示します。

//if drawing inside custom UIView sublcass:
- (void)drawRect:(CGRect)rect
{
    CGContextRef currenctContext = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];

    CGContextSetLineWidth(currenctContext, _lineWidth);
    CGContextSetLineJoin(currenctContext,kCGLineJoinRound);

    CGContextMoveToPoint(currenctContext,x1, y1);
    CGContextAddLineToPoint(currenctContext,x2, y2);
    CGContextStrokePath(currenctContext);
}

//if drawing inside custom CALayer subclass:
- (void) drawInContext:(CGContextRef)ctx {
{
    //self.contentsScale = [UIScreen mainScreen].scale;

    CGContextRef currenctContext = ctx;
    CGContextSetStrokeColorWithColor(currenctContext, [UIColor blackColor].CGColor);

    CGContextSetLineWidth(currenctContext, _lineWidth);
    CGContextSetLineJoin(currenctContext,kCGLineJoinRound);

    CGContextMoveToPoint(currenctContext,x1, y1);
    CGContextAddLineToPoint(currenctContext,x2, y2);
    CGContextStrokePath(currenctContext);
}

私が達成したいことを言い換えると、UIViewアプローチと同じ鮮明な網膜レンダリングを達成したいのですが、CALayer

4

3 に答える 3

17

問題はここでの contentScale である可能性が最も高いです。関数をオーバーライドしてこれをカスタム ビューに割り当てるlayerClassと、レイヤーのコンテンツ スケールがリセットされる可能性があることに注意してください。これが発生する他のいくつかの例があるかもしれません。安全を期すために、レイヤーがビューに追加された後にのみコンテンツ スケールを設定してください。

カスタム ビューの init メソッド中に、メイン画面のスケールをカスタム レイヤーに割り当ててみてください。Swift 3 では、次のようになります。

layer.contentsScale = UIScreen.mainScreen().scale

または、Swift 4 では:

layer.contentsScale = UIScreen.main.scale
于 2016-08-21T20:48:01.190 に答える
9

shouldRasterize = YESレイヤーで使用していますか?CALayer サブクラスで描画を試みrasterizationScaleますが、画面のスケールに設定します。

于 2015-02-06T13:43:07.173 に答える
3

スーパーレイヤーにレイヤーを追加した後。shouldRasterize を YES に設定し、contentsScale と resterizatioinScale をスクリーン スケールに設定します。

[self.progressView.layer addSublayer:self.progressLayer];
self.progressLayer.shouldRasterize = YES;
self.progressLayer.contentsScale = kScreenScale;
self.progressLayer.rasterizationScale = kScreenScale;

CABasicAnimation *animate = [CABasicAnimation animationWithKeyPath:@"progress"];// progress is a customized property of progressLayer
animate.duration = 1.5;
animate.beginTime = 0;
animate.fromValue = @0;
animate.toValue = @1;
animate.fillMode = kCAFillModeForwards;
animate.removedOnCompletion = NO;
animate.repeatCount = HUGE_VALF;
[self.progressLayer addAnimation:animate forKey:@"progressAnimation"];
于 2016-10-13T06:46:15.757 に答える