在日常iOS開(kāi)發(fā)中,系統(tǒng)提供的控件常常無(wú)法滿足業(yè)務(wù)功能蚁孔,這個(gè)時(shí)候需要我們實(shí)現(xiàn)一些自定義控件惋嚎。自定義控件能讓我們完全控制視圖的展示內(nèi)容以及交互操作另伍。本篇將介紹一些自定義控件的相關(guān)概念,探討自定義控件開(kāi)發(fā)的基本過(guò)程及技巧温艇。
在開(kāi)始之前我們先介紹一個(gè)類UIVew中贝,它在iOS APP中占有絕對(duì)重要的地位,因?yàn)閹缀跛械目丶际抢^承自UIView類蝎土。
UIView表示屏幕上的一個(gè)矩形區(qū)域誊涯,負(fù)責(zé)渲染區(qū)域內(nèi)的內(nèi)容蒜撮,并且響應(yīng)區(qū)域內(nèi)發(fā)生的觸摸事件段磨。
在UIView的內(nèi)部有一個(gè)CALayer,提供內(nèi)容的繪制和顯示砾隅,包括UIView的尺寸樣式债蜜。UIView的frame實(shí)際上返回的CALayer的frame寻定。
UIView繼承自UIResponder類狼速,它能接收并處理從系統(tǒng)傳來(lái)的事件,CALayer繼承自NSObject浅浮,它無(wú)法響應(yīng)事件捷枯。所以UIView與CALayer的最大區(qū)別在于:UIView能響應(yīng)事件专执,而CALayer不能淮捆。
效果圖:
//實(shí)現(xiàn)思路就是在一個(gè)view界面定制
#import <UIKit/UIKit.h>
@interface circleImageView : UIView
- (void)configeWithImage:(UIImage *)image;
@end
#import "circleImageView.h"
@interface circleImageView ()
{
UIImageView *_imageView;
}
@end
@implementation circleImageView
-(instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
_imageView.contentMode = UIViewContentModeScaleAspectFill;
_imageView.layer.masksToBounds = YES;
_imageView.layer.cornerRadius = frame.size.width/2;
[self addSubview:_imageView];
}
return self;
}
- (void)configeWithImage:(UIImage *)image {
_imageView.image = image;
}
在viewController界面設(shè)置view的位置大小
#import "ViewController.h"
#import "circleImageView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:@"haha.png"];
circleImageView * ImageView = [[circleImageView alloc] initWithFrame:CGRectMake(150, 180, 150, 150)];
[ImageView configeWithImage:image];
[self.view addSubview:ImageView];
}
進(jìn)度條
效果圖:
其實(shí)進(jìn)度條就是在view界面畫圖,想要了解一些關(guān)于畫圖的東西可以查看我的前幾篇文章
第一種進(jìn)度條:
在view界面,在.h文件,我們定義4個(gè)屬性攀痊,進(jìn)度桐腌,未過(guò)滑道時(shí)的背景顏色,走過(guò)滑道的背景顏色苟径,線條的寬度
#import <UIKit/UIKit.h>
@interface JJHCircleProgressView : UIView
//進(jìn)度
@property (nonatomic)CGFloat progress;
//未過(guò)滑道時(shí)的背景顏色案站,默認(rèn)是灰色
@property (nonatomic,strong)UIColor *trackBackgroundColor;
//走過(guò)滑道的背景顏色,默認(rèn)是黃色
@property (nonatomic,strong)UIColor *trackColor;
//線條的寬度 默認(rèn)是10
@property (nonatomic,assign)float lineWidth;
@end
在.m界面蟆盐,如果要是布局控件,必須在layoutSubviews這里面寫他的位置
#import "JJHCircleProgressView.h"
@interface JJHCircleProgressView ()
@property (strong, nonatomic) UILabel *progressLabel;
@end
@implementation JJHCircleProgressView
//可以在xib storyBoard 以及代碼中都可以實(shí)現(xiàn)
- (instancetype)init
{
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self commonInit];
}
return self;
}
//設(shè)置各種屬性遭殉,以及把label添加上
- (void)commonInit {
_lineWidth = 10.0;
_trackBackgroundColor = [UIColor grayColor];
_trackColor = [UIColor yellowColor];
}
//要是布局控件石挂,必須在這里面寫他的位置
- (void)layoutSubviews{
[super layoutSubviews];
UILabel *progressLabel = [[UILabel alloc] init];
progressLabel.textColor = [UIColor blackColor];
progressLabel.backgroundColor = [UIColor clearColor];
progressLabel.textAlignment = NSTextAlignmentCenter;
progressLabel.text = @"0.0%";
_progressLabel = progressLabel;
[self addSubview:_progressLabel];
CGFloat slideLength = self.bounds.size.width;
self.progressLabel.frame = CGRectMake(_lineWidth, _lineWidth, slideLength-2*_lineWidth, slideLength-2*_lineWidth);
}
//畫圖
- (void)drawRect:(CGRect)rect{
[super drawRect:rect];
//獲取圖形上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGFloat slideLength = self.bounds.size.width;
CGFloat centerX = slideLength/2;
CGFloat centerY = slideLength/2;
// x,y為圓點(diǎn)坐標(biāo),radius半徑险污,startAngle為開(kāi)始的弧度痹愚,endAngle為 結(jié)束的弧度,clockwise 0為順時(shí)針蛔糯,1為逆時(shí)針拯腮。
// CGContextAddArc(<#CGContextRef _Nullable c#>, <#CGFloat x#>, <#CGFloat y#>, <#CGFloat radius#>, <#CGFloat startAngle#>, <#CGFloat endAngle#>, <#int clockwise#>)
//添加背景軌道
CGContextAddArc(contextRef, centerX, centerY, (slideLength - _lineWidth)/2, 0, 2 * M_PI, 0);
//設(shè)置背景的寬度
CGContextSetLineWidth(contextRef, _lineWidth);
//設(shè)置背景顏色
[_trackBackgroundColor setStroke];
//繪制軌道
CGContextStrokePath(contextRef);
//繪制進(jìn)度顏色===================
//添加背景軌道
//角度
float endAngle = _progress * (2 * M_PI);
CGContextAddArc(contextRef, centerX, centerY, (slideLength - _lineWidth)/2, 0, endAngle, 0);
//設(shè)置背景的寬度
CGContextSetLineWidth(contextRef, _lineWidth);
//設(shè)置背景顏色
[_trackColor setStroke];
//繪制軌道
CGContextStrokePath(contextRef);
}
- (void)setProgress:(CGFloat)progress {
if (progress > 1 || progress < 0) return;
_progress = progress;
self.progressLabel.text = [NSString stringWithFormat:@"%.1f%%", progress*100];
// 標(biāo)記為需要重新繪制, 將會(huì)在下一個(gè)繪制循環(huán)中, 調(diào)用drawRect:方法重新繪制
[self setNeedsDisplay];
}
@end
第二種進(jìn)度條
在.h界面,我們定義4個(gè)屬性,進(jìn)度蚁飒,邊框線的顏色动壤,設(shè)置邊框線的寬度,里面填充的顏色 默認(rèn)是紅色
#import <UIKit/UIKit.h>
@interface JJHBreadProgressView : UIView
//進(jìn)度
@property (nonatomic)CGFloat progress;
//邊框線的顏色 默認(rèn)是灰色
@property (nonatomic)UIColor *lineColor;
//設(shè)置邊框線的寬度 默認(rèn)是10.0
@property (nonatomic)CGFloat lineWidth;
//里面填充的顏色 默認(rèn)是紅色
@property (nonatomic)UIColor *BreadClolor;
@end
在.m文件
#import "JJHBreadProgressView.h"
@implementation JJHBreadProgressView
//可以在xib storyBoard 以及代碼中都可以實(shí)現(xiàn)
- (instancetype)init
{
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit{
_lineColor = [UIColor grayColor];
_BreadClolor = [UIColor redColor];
_lineWidth = 2.0;
}
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
//獲取圖形上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGFloat slideLength = self.bounds.size.width;
CGFloat centerX = slideLength/2;
CGFloat centerY = slideLength/2;
// x,y為圓點(diǎn)坐標(biāo)飒箭,radius半徑狼电,startAngle為開(kāi)始的弧度,endAngle為 結(jié)束的弧度弦蹂,clockwise 0為順時(shí)針肩碟,1為逆時(shí)針。
// CGContextAddArc(<#CGContextRef _Nullable c#>, <#CGFloat x#>, <#CGFloat y#>, <#CGFloat radius#>, <#CGFloat startAngle#>, <#CGFloat endAngle#>, <#int clockwise#>)
//添加背景軌道
CGContextAddArc(contextRef, centerX, centerY, (slideLength - _lineWidth)/2, 0, 2 * M_PI, 0);
//設(shè)置背景的寬度
CGContextSetLineWidth(contextRef, _lineWidth);
//設(shè)置背景顏色
[_lineColor setStroke];
//繪制軌道
CGContextStrokePath(contextRef);
//===============劃填充物=============
CGContextMoveToPoint(contextRef, centerX, centerY);
//結(jié)束時(shí)的轉(zhuǎn)的弧度
float endBread = _progress * 2 * M_PI;
CGContextAddArc(contextRef, centerX, centerY, (slideLength-2*_lineWidth)/2, 0, endBread, 0);
CGContextSetFillColorWithColor(contextRef, _BreadClolor.CGColor);
CGContextFillPath(contextRef);
}
@end
iOS凸椿,小小白削祈,有空就寫一些小東西∧月肯定會(huì)有很多不足的地方髓抑,希望各位大神多多指教。优幸。吨拍。。