iOS切圆角方法解决离屏渲染问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS切圆角方法解决离屏渲染问题相关的知识,希望对你有一定的参考价值。

参考技术A 1、UIView切圆角
UIView在切圆角的时候使用

会导致离屏渲染。

解决办法:不能使用masksToBounds,view.clipsToBounds;直接切圆角:

这是方法适用于切全圆角,如果是切指定圆角的时候就不行了;
增加切指定圆角的方法

使用改方法满足了切指定圆角的需求;但是又会导致离屏渲染问题;
这儿想到一个办法就是使用UIImageView替换UIView;或者是在底层插入UIImageView;
首先要设置一个UIImage根据背景设置

方法实现

之后再,具体实现见下面UIImageView切圆角方法;

2、UIView增加阴影效果:

会导致离屏渲染。
解决办法:设置阴影路径可避免离屏渲染

实现上述方法就可以实现圆角+阴影效果

3、UIImageView切圆角
简便的方法

ios9.0之后加载png图片设置圆角不会导致离屏渲染;
但是如果在给UIImageView增加一个背景色就会导致离屏渲染;

最优的解决办法:通过给UIImageView加载的图片切圆角;
给图片切圆角之后重新赋值给UIImageView;如下

需要给定size时,如果使用的Masnory添加的预约,则需要立即更新之后才会生效

将持续优化方法,找到最适合的方法

解决圆角离屏渲染方案

最近看了大量的优化tableview方案,为了配合sd下载图片,并且解决圆角图片离屏渲染问题,于是利用category自己写了个处理圆角的方法,解决了离屏渲染问题(并不是非常高效,感觉只是降低了GPU的消耗,但是提升了CPU的消耗,但是好歹也算是能提高一点fps),我还是更推荐使用yyimage下载图片,里面封装了处理圆角图片方法。

下面是代码:

//
//  UIImageView+CornerRadius.m
//  test
//
//  Created by gkoudai_xsm on 16/4/11.
//  Copyright © 2016年 gkoudai_xsm. All rights reserved.
//
#import <objc/runtime.h>
#import "UIImageView+CornerRadius.h"

static NSString * const kIsRounding = @"kIsRounding";
static NSString * const kHadAddObserver = @"kHadAddObserver";
static NSString * const kProcessedImage = @"kProcessedImage";


@interface UIImageView ()

//在category里添加属性  自己实现get和set方法  objc_getAssociatedObject/objc_setAssociatedObject
@property (nonatomic ,assign)BOOL isRounding;
@property (nonatomic ,assign)BOOL hadAddObserver;

@end

@implementation UIImageView (CornerRadius)
//public method
- (instancetype)initWithRoundingRectImageView{
    self = [super init];
    if (self) {
        [self roundingRect];
    }
    return self;
}

- (void) roundingRect {
    
    self.isRounding = YES;
    if (!self.hadAddObserver) {
        //添加个kvo
        [self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
        
        self.hadAddObserver = YES;
    }
}

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    
    if ([keyPath isEqualToString:@"image"]) {
        UIImage *newImage = change[NSKeyValueChangeNewKey];
        if ([newImage isMemberOfClass:[NSNull class]]) { //判断是否为空
            return;
            
        } else if ([objc_getAssociatedObject(newImage, &kProcessedImage) intValue] == 1) {
            //新图 判断处理
            return;
        }
        if (self.isRounding) {
            
            [self roundingRectWithImage:newImage cornerRadius:self.frame.size.width/2];
        }
    }
}

#pragma mark - 处理图片
- (void)roundingRectWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius {
    
    CGSize size = self.bounds.size;
    CGFloat scale = [UIScreen mainScreen].scale;
    CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
    
    // //获得用来处理图片的图形上下文,设置no为不透明
    UIGraphicsBeginImageContextWithOptions(size, NO, scale);
    
    if (nil == UIGraphicsGetCurrentContext()) {
        return;
    }
    //针对某个角画圆形区域
    UIBezierPath *roundingPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:cornerRadii];
    // 添加裁剪
    [roundingPath addClip];
    // 边框线宽
    roundingPath.lineWidth = 0.1;
    
    [image drawInRect:self.bounds];
    // 开始画
    [roundingPath stroke];
    
    //从当前上下文中获取一个UIImage对象
    UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
    
    //关闭图形上下文
    UIGraphicsEndImageContext();
    
    //关联一个处理的图片
    objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    self.image = processedImage;
}

#pragma mark - Property

- (BOOL)hadAddObserver {
    
    return [objc_getAssociatedObject(self, &kHadAddObserver) boolValue];
}

- (void)setHadAddObserver:(BOOL)hadAddObserver {
    
    objc_setAssociatedObject(self, &kHadAddObserver, @(hadAddObserver), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (BOOL)isRounding {
    return [objc_getAssociatedObject(self, &kIsRounding) boolValue];
}

- (void)setIsRounding:(BOOL)isRounding {
    objc_setAssociatedObject(self, &kIsRounding, @(isRounding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

#pragma mark - dealloc
- (void)dealloc{
    
    if (self.hadAddObserver) {
        
        [self removeObserver:self forKeyPath:@"image"];
    }
    
}
@end

 

以上是关于iOS切圆角方法解决离屏渲染问题的主要内容,如果未能解决你的问题,请参考以下文章

iOS沉思录UIImage圆角矩形的‘离屏渲染’和‘在屏渲染’实现方法

iOS圆角的离屏渲染,你真的弄明白了吗

iOS 离屏渲染问题

iOS离屏渲染

iOS切圆角的几个方法

swift 给UIView添加圆角,避免离屏渲染