2011-01-19 8 views
44

コーナーにページ番号を表示するドキュメントビューを作成しました。ページ番号は半透明の背景色を持つユーラベルで、コーナー半径はのviewlayerというプロパティを使用しています。私はUIScrollViewの上にこれを配置しました。しかし、これによりスクロールがぎくしゃくします。 cornerRadiusを削除した場合、パフォーマンスは良好です。私はこれについて何かできることはありますか?よりよい解決策は何でしょうか?パフォーマンスの問題がなく、UIWebViewで達成されたようです。UILabelレイヤーcornerRadiusがパフォーマンスに悪影響を与える

答えて

142

スクロールのソリューションは非常に簡単です再生回数:

最大の問題は、masksToBounds層オプションからです。これはパフォーマンスを大幅に向上させるように見えますが、ラベルには丸みのある角に背景色を隠すためにONが必要なようです。だから、これを回避するには、ラベルのレイヤーの背景色を代わりに設定し、masksToBoundsをオフにする必要があります。

第2の問題は、デフォルトの動作では、可能な限りいつでもビューを再描画することです。スクロールするビューで静的またはゆっくり変化するアイテムではまったく必要ありません。ここでは単にlayer.shouldRasterize = YESを設定します。これにより、CAはスクロールするときに(ハードウェアアクセラレーションを使用していると思われる)、迅速な描画のためにラスタライズされたバージョンのビューをCAにキャッシュすることができます。

レイヤーにアルファチャンネルがあることを確認する必要があります。それ以外の場合、ラスタライズは丸みのあるコーナーの描画に影響します。背景色にアルファが設定されているので問題は一度もありませんが、状況を確認する必要があります。ここで

がscollview上でうまく動作するように設定サンプルUILabelです:

UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(4, 4, 40.0, 24.0)]; 
lbl.font = [UIFont fontWithName:@"Helvetica" size:14.0]; 
lbl.textAlignment = UITextAlignmentRight; 
lbl.text = @"Hello World"; 
// Must set the label background to clear so the layer background shows 
lbl.backgroundColor = [UIColor clearColor];   
// Set UILabel.layer.backgroundColor not UILabel.backgroundColor otherwise the background is not masked to the rounded border. 
lbl.layer.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5].CGColor; 

lbl.layer.cornerRadius = 8; 
lbl.layer.borderColor = [UIColor blackColor].CGColor; 
lbl.layer.borderWidth = 1; 
// Huge change in performance by explicitly setting the below (even though default is supposedly NO) 
lbl.layer.masksToBounds = NO; 
// Performance improvement here depends on the size of your view 
lbl.layer.shouldRasterize = YES; 
lbl.layer.rasterizationScale = [UIScreen mainScreen].scale; 
// self here is the child view in the scroll view 
[self addSubview:lbl]; 
[lbl release]; 

私はこのような景色を眺めながらiPadの1画面を埋め、まだスムーズにスクロールすることができます:)

+0

ありがとうございました。ありがとうございました。これは、丸い角を持つuitextfieldsのパフォーマンスの問題を解決するのに役立ちました。 – ChristophK

+1

ありがとうございます。私にとっても素晴らしい作品です。 – JHos

+4

BTW '.shouldRasterize = YES'を使用すると、UILabelの内容が網膜デバイスで汚れて見えます。 – bioffe

3

私は丸い角を持つカスタムでUILabelと同様の問題がありました。円滑なパフォーマンスを得るために、丸みを帯びたイメージを使ってこれを回避する画像を作成しました(see)。

thisまたはthisなどの他の投稿がたくさんあります。

6

サイドバーの「関連する」ポストを見た後、私は自分のイメージを作成することに決めました。 UIViewをサブクラス化し、背景に丸みを帯びた背景の画像とinitの標準テキストラベルを追加しました。背景画像を作成するには、CG描画関数を使用して伸縮可能な画像を作成します。丸みを帯びた角およびまたは背景色と影付きのラベル、またはビューの場合

// create background image 
    CGFloat radius = frame.size.height/2; 
    CGFloat imgSize = (radius*2)+1; // 1 pixel for stretching 
    UIGraphicsBeginImageContext(CGSizeMake(imgSize, imgSize)); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGContextSetAlpha(context, 0.5f); 
    CGContextSetLineWidth(context, 0); 
    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); 

    CGFloat minx = 0; 
    CGFloat midx = imgSize/2; 
    CGFloat maxx = imgSize; 
    CGFloat miny = 0; 
    CGFloat midy = imgSize/2; 
    CGFloat maxy = imgSize; 

    CGContextMoveToPoint(context, minx, midy); 
    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
    CGContextClosePath(context); 
    CGContextDrawPath(context, kCGPathFillStroke); 

    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    UIImage *stretchImage = [viewImage stretchableImageWithLeftCapWidth:radius topCapHeight:radius]; 

    UIImageView *stretch = [[UIImageView alloc] initWithImage:stretchImage]; 
    stretch.frame = self.bounds; 
    stretch.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth); 
    [self addSubview:stretch]; 
    [self sendSubviewToBack:stretch]; 
    [stretch release]; 
8

私はこれにつまずきました1つも。 cornerRadius(UIButtonとUIImageView用)が私のアプリのパフォーマンスを殺していました。私は、UIButtonを背景画像で囲む実用的な解決策がないことを知ったので、私自身のコード一筆書きメソッドを作成しなければなりませんでした。 SecondはUIImageViewに丸みのある角と境界線を追加します。コードはそれ自体のことを話すと思います。

+(void)setBackgroundImage:(UIImage*)image forButton:(UIButton*)button withCornerRadius:(float)cornerRadius borderColor:(CGColorRef)borderColor andBorderWith:(float)borderWidth 
{ 
    UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:button.frame]; 
    UIGraphicsBeginImageContextWithOptions(tempImageView.bounds.size, NO, 1.0); 
    [[UIBezierPath bezierPathWithRoundedRect:tempImageView.bounds 
           cornerRadius:cornerRadius] addClip]; 
    [image drawInRect:tempImageView.bounds]; 
    tempImageView.image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    [button setBackgroundImage:tempImageView.image forState:UIControlStateNormal]; 
    button.layer.shouldRasterize = YES; 
    button.layer.borderColor = borderColor; 
    button.layer.borderWidth = borderWidth; 
    button.layer.cornerRadius = cornerRadius; 
} 

+(void)makeRoundedCornersForImageView:(UIImageView*)imgV withCornerRadius:(float)cornerRadius borderColor:(CGColorRef)borderColor andBorderWith:(float)borderWidth 
{ 
    UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:imgV.frame]; 
    UIGraphicsBeginImageContextWithOptions(tempImageView.bounds.size, NO, 1.0); 
    [[UIBezierPath bezierPathWithRoundedRect:tempImageView.bounds 
           cornerRadius:cornerRadius] addClip]; 
    [imgV.image drawInRect:tempImageView.bounds]; 
    tempImageView.image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    imgV.image = tempImageView.image; 
    imgV.layer.shouldRasterize = YES; 
    imgV.layer.borderColor = borderColor; 
    imgV.layer.borderWidth = borderWidth; 
    imgV.layer.cornerRadius = cornerRadius; 
} 
+0

非常に良い、これは私を助けます。 – ZYiOS

+0

ImageViewが機能せず、画像がクリップされません。 – Blacky