UI界面相关方法

发表于 - 10 分钟   |   --

该文档用于记录iOS端常用的界面方法。

1.状态栏UIStatusBar相关设置

1.1 设置状态栏字体颜色

设置更改时需要调用:

setNeedsStatusBarAppearanceUpdate()

调用该方法后,在以下方法里更改状态栏的样式:

override var preferredStatusBarStyle: UIStatusBarStyle {
    if <##> {
        return .lightContent
    } else {
        return .default
    }
}

1.2设置状态栏颜色

//设置状态栏颜色
- (void)setStatusBarBackgroundColor:(UIColor *)color {
    UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
    if ([statusBar respondsToSelector:@selector(setBackgroundColor:)]) {
        statusBar.backgroundColor = color;
    }
}


2.UINavigation及UITabbar相关方法

2.1 设置push进子界面的同时隐藏底部UITabbar

		override func pushViewController(_ viewController: UIViewController, animated: Bool) {
        if (viewControllers.count > 0) {// 当非根控制器隐藏底部tabbar
            viewController.hidesBottomBarWhenPushed = true;
            
            viewController.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named:"back"), style: .plain, target: self, action: #selector(back))
            
        }
        super.pushViewController(viewController, animated: animated)
    }

2.2 设置UINavigationBar上按钮的文字颜色

全局设置:

UINavigationBar.appearance().tintColor = UIColor.orange

单独某页面设置:

navigationItem.rightBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:UIColor.primary], for:.normal)
navigationItem.rightBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:UIColor.primary], for:.highlighted)

2.3 设置UITabBarItem上的文字颜色

UITabBarItem.appearance().setTitleTextAttributes(
            [NSAttributedString.Key.foregroundColor:UIColor.primary], for:.selected)


3.滚动视图相关设置

3.1 设置UITableView分隔线(下划线)

tableView.tableFooterView = UIView(frame: CGRect.zero)
tableview.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
tableview.separatorColor = UIColor.line_grey

3.2 UITableView及UICollectionView的点击事件穿透设置方法

//点击事件穿透,不响应tableView的点击事件
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let view = super.hitTest(point, with: event)
    if let bool1 = (view?.superview?.isKind(of: UITableViewCell.self)), let bool2 = view?.isKind(of: UITableView.self), bool1 || bool2 {
				return self
    }
    return view
}


4.UITextView

4.1 UITextView设置超链接,点击可响应及其相关方法

ViewDidLoad:

//The description for the phone call.
let tipStr = "一串内容。"
let popStr = "内容后面可点击的文字"
let contentStr = tipStr + popStr
let range = NSRange(location: tipStr.count, length: popStr.count)
let contentAttrStr = NSMutableAttributedString(string: contentStr)
contentAttrStr.addAttributes([NSAttributedString.Key.link : "pop://"], range: range)

phoneCallContentTv.isEditable = false
phoneCallContentTv.delegate = self
phoneCallContentTv.attributedText = contentAttrStr
phoneCallContentTv.font = UIFont.systemFont(ofSize: 12)
phoneCallContentTv.textContainerInset = UIEdgeInsets.zero
phoneCallContentTv.tintColor = UIColor.primary
headBoard.addSubview(phoneCallContentTv)

extension:

extension PhoneCallReminderController:UITextViewDelegate {
    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
        if URL.description == "pop://" {
            showDetails()
            return false
        }
        return true
    }
}

4.2 禁止UITextView被选中(复制粘贴全选)

//禁止textView选中
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    phoneCallContentTv.resignFirstResponder()
    return super.canPerformAction(action, withSender: sender)
}


5.UIView界面相关方法

5.1 UIView的部分圆角设置

/**
 按钮的圆角设置

 @param view view类控件
 @param rectCorner UIRectCorner要切除的圆角
 @param borderColor 边框颜色
 @param borderWidth 边框宽度
 @param viewColor view类控件颜色
 */
- (void)setupRoundedCornersWithView:(UIView *)view cutCorners:(UIRectCorner)rectCorner borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth viewColor:(UIColor *)viewColor {
    
    CAShapeLayer *mask=[CAShapeLayer layer];
    UIBezierPath * path= [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:rectCorner cornerRadii:CGSizeMake(9,9)];
    mask.path=path.CGPath;
    mask.frame=view.bounds;
    
    CAShapeLayer *borderLayer=[CAShapeLayer layer];
    borderLayer.path=path.CGPath;
    borderLayer.fillColor = [UIColor clearColor].CGColor;
    borderLayer.strokeColor = borderColor.CGColor;
    borderLayer.lineWidth = borderWidth;
    borderLayer.frame = view.bounds;
    view.layer.mask = mask;
    [view.layer addSublayer:borderLayer];
}


6.UIImage方法

6.1 图片染色

将图片染成想要的颜色,适合带有透明度的png图片。

以下为UIImage的类扩展:

.h文件:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIImage (ChangeColor)

-(UIImage*)imageWithColor:(UIColor*)color;

- (UIImage *)originalImageWithColor:(UIColor *)color;

@end

NS_ASSUME_NONNULL_END

.m文件:

#import "UIImage+ChangeColor.h"

@implementation UIImage (ChangeColor)

//绘图
-(UIImage*)imageWithColor:(UIColor*)color
{
    //获取画布
    UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);
    //画笔沾取颜色
    [color setFill];
    
    CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height);
    UIRectFill(bounds);
    //绘制一次
    [self drawInRect:bounds blendMode:kCGBlendModeOverlay alpha:1.0f];
    //再绘制一次
    [self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f];
    //获取图片
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

- (UIImage *)originalImageWithColor:(UIColor *)color {
    UIImage *img = [self imageWithColor:color];
    img = [img imageWithRenderingMode:(UIImageRenderingModeAlwaysOriginal)];
    return img;
}

@end

当对作为tabbar的图标做染色时发现图片被显示成系统默认的蓝色了,此时可以调用以下方法对图片做进一层封装,调用时使用以下方法即可:

- (UIImage *)originalImageWithColor:(UIColor *)color {
    UIImage *img = [self imageWithColor:color];
    img = [img imageWithRenderingMode:(UIImageRenderingModeAlwaysOriginal)];
    return img;
}

使用方式:

UIImage *image= [UIImage imageNamed:@"tab_home_selected"];
image = [image imageWithColor:[UIColor redColor]];

参考文章:iOS改变图片的颜色

6.2 更改图片中的特定颜色

有时候如果要根据主题或者主色调对图片进行更改时,可调用以下方法,将一定范围内的颜色更改成指定的颜色。

以下为UIImage的类扩展:

.h文件:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIImage (Rander)

- (UIImage *)translatePixelColorByTargetNearBlackColor:(UIColor *)nearBlackColor nearWhiteColor:(UIColor *)nearWhiteColor transColor:(UIColor *)transColor;

- (UIImage *)translatePixelColorByTargetNearBlackColorHex:(UInt32)nearBlackRGB nearWhiteColorHex:(UInt32)nearWhiteRGB transColorHex:(UInt32)transRGB;

- (UIImage *)translatePixelColorByTargetNearBlackColorRGBA:(UInt32)nearBlackRGBA nearWhiteColorRGBA:(UInt32)nearWhiteRGBA transColorRGBA:(UInt32)transRGBA inRect:(CGRect)rect;

@end

NS_ASSUME_NONNULL_END

.m文件

#import "UIImage+Rander.h"
#import "UIColor+RGB.h"

@implementation UIImage (Rander)

- (UIImage *)translatePixelColorByTargetNearBlackColor:(UIColor *)nearBlackColor
                                        nearWhiteColor:(UIColor *)nearWhiteColor
                                            transColor:(UIColor *)transColor {
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
    return [self translatePixelColorByTargetNearBlackColor:nearBlackColor nearWhiteColor:nearWhiteColor transColor:transColor inRect:rect];
}

- (UIImage *)translatePixelColorByTargetNearBlackColor:(UIColor *)nearBlackColor
                                        nearWhiteColor:(UIColor *)nearWhiteColor
                                            transColor:(UIColor *)transColor
                                                inRect:(CGRect)rect {
    // UIColor 转 RGBA
    UInt32 nearBlackRGBA = nearBlackColor.RGBA;
    UInt32 nearWhiteRGBA = nearWhiteColor.RGBA;
    UInt32 transRGBA = transColor.RGBA;

    return [self translatePixelColorByTargetNearBlackColorRGBA:nearBlackRGBA nearWhiteColorRGBA:nearWhiteRGBA transColorRGBA:transRGBA inRect:rect];
}


- (UIImage *)translatePixelColorByTargetNearBlackColorHex:(UInt32)nearBlackRGB
                                        nearWhiteColorHex:(UInt32)nearWhiteRGB
                                            transColorHex:(UInt32)transRGB {
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
    return [self translatePixelColorByTargetNearBlackColorHex:nearBlackRGB nearWhiteColorHex:nearWhiteRGB transColorHex:transRGB inRect:rect];
}


- (UIImage *)translatePixelColorByTargetNearBlackColorHex:(UInt32)nearBlackRGB
                                        nearWhiteColorHex:(UInt32)nearWhiteRGB
                                            transColorHex:(UInt32)transRGB
                                                   inRect:(CGRect)rect {
    // RGB 转 RGBA
    UInt32 nearBlackRGBA = (nearBlackRGB << 8) + 0xFF;
    UInt32 nearWhiteRGBA = (nearWhiteRGB << 8) + 0xFF;
    UInt32 transRGBA = (transRGB << 8) + 0xFF;
    
    return [self translatePixelColorByTargetNearBlackColorRGBA:nearBlackRGBA nearWhiteColorRGBA:nearWhiteRGBA transColorRGBA:transRGBA inRect:rect];
}

/**
解释一下前两个参数的含义:
想象一个数轴,最左边是黑色(RGBX:0x000000FF),最右边是白色(0xFFFFFFFF),
nearBlackColor是靠近左边边界的色值,nearWhiteColor是靠近右边边界的色值,
它们中间则是需要被修改的色值范围
*/
- (UIImage *)translatePixelColorByTargetNearBlackColorRGBA:(UInt32)nearBlackRGBA
                                        nearWhiteColorRGBA:(UInt32)nearWhiteRGBA
                                            transColorRGBA:(UInt32)transRGBA
                                                   inRect:(CGRect)rect {
    // 第一步:判断传入的rect是否在图片的bounds内
    CGRect canvas = CGRectMake(0, 0, self.size.width, self.size.height);
    if (!CGRectContainsRect(canvas, rect)) {
        if (CGRectIntersectsRect(canvas, rect)) {
            rect = CGRectIntersection(canvas, rect);    // 取交集
        } else {
            return self;
        }
    }
    
    UIImage *transImage = nil;
    
    int imageWidth = self.size.width;
    int imageHeight = self.size.height;
    
    // 第二步:创建色彩空间、画布上下文,并将图片以bitmap(不含alpha通道)的方式画在画布上。
    size_t bytesPerRow = imageWidth * 4;
    uint32_t *rgbImageBuf = (uint32_t *)malloc(bytesPerRow * imageHeight);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,
                                                 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    
    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), self.CGImage);
    
    // 第三步:遍历并修改像素
    uint32_t *pCurPtr = rgbImageBuf;
    pCurPtr += (long)(rect.origin.y*imageWidth);    // 将指针移动到初始行的起始位置
    
    // 空间复杂度:O(rect.size.width * rect.size.height)
    for (int i = rect.origin.y; i < CGRectGetMaxY(rect); i++) {                     // row
        pCurPtr += (long)rect.origin.x;             // 将指针移动到当前行的起始列
        
        for (int j = rect.origin.x; j < CGRectGetMaxX(rect); j++, pCurPtr++) {      // column
            if (*pCurPtr < nearBlackRGBA || *pCurPtr > nearWhiteRGBA) { continue; }
            
            // 将图片转成想要的颜色
            uint8_t *ptr = (uint8_t *)pCurPtr;
            ptr[3] = (transRGBA >> 24) & 0xFF;              // R
            ptr[2] = (transRGBA >> 16) & 0xFF;              // G
            ptr[1] = (transRGBA >> 8)  & 0xFF;              // B
        }
        
        pCurPtr += (long)(imageWidth - CGRectGetMaxX(rect));    // 将指针移动到下一行的起始列
    }
    
    // 第四步:输出图片
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, providerReleaseDataCallback);
    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace,
                                        kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider,
                                        NULL, true, kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);
    transImage = [UIImage imageWithCGImage:imageRef];
    
    // end:清理空间
    CGImageRelease(imageRef);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    
    return transImage ? : self;
}

void providerReleaseDataCallback (void *info, const void *data, size_t size) {
    free((void*)data);
}

@end

该方法调用了UIColor的类扩展,以下是扩展内容

.h文件

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIColor (RGB)

- (UInt32)RGBA;

@end

NS_ASSUME_NONNULL_END

.m文件

#import "UIColor+RGB.h"

@implementation UIColor (RGB)

- (UInt32)RGBA {
    CGFloat red = 0;
    CGFloat green = 0;
    CGFloat blue = 0;
    CGFloat alpha = 0;
    
    BOOL succ = [self getRed:&red green:&green blue:&blue alpha:&alpha];
    
    UInt32 r = round(red*255);
    UInt32 g = round(green*255);
    UInt32 b = round(blue*255);
    UInt32 a = round(alpha*255);

    r = (r << 24);
    g = (g << 16);
    b = (b << 8);
    
    UInt32 rgba = r + g + b + a;
    return succ ? rgba : 0x00000000;
}

@end

参考文章:iOS修改图片颜色(修改像素色值)

6.3 生成二维码图片

生成二维码是iOS内置功能,直接调用iOS系统库即可:#import <CoreImage/CoreImage.h>

6.3.1 根据CIImage生成指定大小的UIImage

创建二维码滤镜后生成的二维码图片为CIImage类型,需根据该方法将其转换为指定大小的UIImage。

代码如下:

- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    //1.创建bitmap;
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    //2.保存bitmap到图片
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    return [UIImage imageWithCGImage:scaledImage];
}

6.3.2 生成二维码

方法如下:

- (void)setupQRCodeWithContent:(NSString *)content {
  	//创建二维码滤镜示例
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    [filter setDefaults];
  	//赋值
    NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
    [filter setValue:data forKeyPath:@"inputMessage"];
    // 生成二维码
    CIImage *outputImage = [filter outputImage];
    UIImage *qrImage = [self createNonInterpolatedUIImageFormCIImage:outputImage withSize:self.width_qr];
    self.qrImgv.image = qrImage;
}

6.3.3 生成中间带有图片的二维码图片

二维码也可以生成为中间带图片的二维码样式,该效果需要在生成二维码图片之后再对图片进行处理。

方法如下:

//开启图形上下文
UIGraphicsBeginImageContext(qrImage.size);
//将二维码的图片画入
[qrImage drawInRect:CGRectMake(0, 0, qrImage.size.width, qrImage.size.height)];
//添加中间图片
UIImage *centerImage = [UIImage imageNamed:@"imageName"];
CGFloat width_center = qrImage.size.width * 0.3;
CGFloat width_height = width_center;
CGFloat x_center = (qrImage.size.width - width_center) * 0.5;
CGFloat y_center = (qrImage.size.height - width_height) * 0.5;
[centerImage drawInRect:CGRectMake(x_center, y_center, width_center, width_height)];
//获取绘制好的图片
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
//关闭图像上下文
UIGraphicsEndImageContext();


7.视图边界方法

7.1 扩散动画效果

7.1.1 雷达扩散效果

- (void)addRadarAnimator
{
    if (spreadLayer != nil && spreadLayer.superlayer != nil) {
        [spreadLayer removeFromSuperlayer];
        spreadLayer = nil;
    }
    spreadLayer = [CALayer layer];
    CGFloat diameter = 180;//扩散的大小
    spreadLayer.bounds = CGRectMake(0,0, diameter, diameter);
    spreadLayer.cornerRadius = diameter/2; //设置圆角变为圆形
    spreadLayer.position = self.scanIcon.center;
    spreadLayer.backgroundColor = UIColorHex(0x8AC859).CGColor;
    [self.scanBgView.layer insertSublayer:spreadLayer below:_scanIcon.layer];//把扩散层放到头像按钮下面
    CAMediaTimingFunction * defaultCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
    CAAnimationGroup * animationGroup = [CAAnimationGroup animation];
    animationGroup.duration = 3;
    animationGroup.repeatCount = INFINITY;//重复无限次
    animationGroup.removedOnCompletion = NO;
    animationGroup.timingFunction = defaultCurve;
    //尺寸比例动画

    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.xy"];
    scaleAnimation.fromValue = @0.7;//开始的大小
    scaleAnimation.toValue = @1.0;//最后的大小
    scaleAnimation.duration = 3;//动画持续时间
    //透明度动画

    CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
    opacityAnimation.duration = 3;
    opacityAnimation.values = @[@0.4, @0.45,@0];//透明度值的设置
    opacityAnimation.keyTimes = @[@0, @0.2,@1];//关键帧
    opacityAnimation.removedOnCompletion = NO;
    animationGroup.animations = @[scaleAnimation, opacityAnimation];//添加到动画组

    [spreadLayer addAnimation:animationGroup forKey:@"pulse"];
}


Michael Lynx

Michael Lynx

三反昼夜

rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin pinterest medium vimeo stackoverflow reddit quora quora