最近看到很多人问一个问题,就是自定义了一个视图,视图测试的时候是可以正常使用的,但是加到工程里面去不响应点击。
其实这个问题的本质就是响应者链,你的视图控件没有被加进响应者链里,那是必然不会响应的。
至于不会被加进响应者链的情况通常是以下的情况:
1.视图本身的userInteractionEnabled为NO。这个属性是view的一个基本属性,你自定义的视图都会继承这个属性,如果你设置了这个属性为NO,或者你的父视图这个属性为NO(比如UIImage,默认情况下userInteractionEnabled=NO)。那么你的视图不会被加进响应者链也是必然的现象了。
2.你可能会说我设置了userInteractionEnabled=YES啊,这就是第二个经常出现的错误了,你确认那一句执行了么?
通常对于一个自定义的view,载入的方式有两种:
1.alloc-init的方式,这个是通过调用视图的initWithFrame函数或者init函数获得一个视图实例。
2.loadNibNamed或者xib的方式,这个方式并不会调用init和initWithFrame函数,而是调用awakeFromNib函数,换句话说,你如果在init函数中设置了userInteractionEnabled=YES,但是你是通过xib的方式来加载视图的时候,那么这句是不会执行的,是无效的。你的视图依然不会响应。
关于awakeFromNib只是增加的一个类目,让你在使用loadNibNamed的过程中可以做一些事情,和viewdidload是不同的。详细如下:
awakeFromNib
当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的awakeFromNib函数来响应这个消息,执行一些必要的操作。
也就是说只有通过.nib文件创建view对象时才会执行awakeFromNib 。
一般的,当IB加载的时候,我们会通过调用自定义对象的awakeFromNib函数,来对界面进行补充。
选择的时机:当你需要写一个UIView的子类并且想在load nib的时候做一些初始化工作的时候很有用。bundle在load nib后会给每个view对象发送一个awakeFromNib消息。
viewDidLoad
当view对象被加载到内存时就会执行viewDidLoad,所以不管是通过.nib文件还是以代码的方式创建对象都会执行viewDidLoad。
UI设计给出了设计图,界面却是不错,看着霸气十足,可是里面的控件,都需要自定义,没有一个不需要折腾的,也罢,就一直在折腾了。折腾中遇到一个问题,UISlder的完全自定义,完全摒弃原生态的东西,开始有点无厘头,慢慢页折腾出来了,今天给出一些关键代码和demo,只是简单的实现,很多功能有待发掘。
首先看一下UI给出的效果图:
网上有一种自定义UISlider的方法,但是最后放弃了,因为依然没有达到所需,也是比人才疏学浅。
下面就是我自定义的类UISlider的部分代码:
1、首先我声明了一个继承子UIView的类,因为我觉的使用UIView页绘制更加快捷。
// // Slider.h // SliderPro // // Created by Yongchao Zhang on 12-9-13. // Copyright (c) 2012年 Yongchao Zhang. All rights reserved. // #import <UIKit/UIKit.h> @protocol SliderDelegate; @interface Slider : UIView{ //放置时间 UIImageView *popView; //箭头 UIImageView *tagView; UILabel *currentLabel; UILabel *totalLabel; NSString *currentStr; NSString *totalStr; float minValue, maxValue; float currentValue; float percent; UIImageView *bottomView; UIImageView *topView; } @property (nonatomic,readwrite) float minValue, maxValue, currentValue; @property (nonatomic,strong) UILabel *currentLabel,*totalLabel; @property (nonatomic,strong) NSString *currentStr,*totalStr; @property (nonatomic,unsafe_unretained)id<SliderDelegate> delegate; @end @protocol SliderDelegate <NSObject> -(void)scrollBegin:(Slider *)sender; -(void)scroll:(Slider *)sender; -(void)scrollDone:(Slider*)sender; @end
2、在实现的时候,需要掌握三种情况的计算,最左边、最右边、中间位置。因为那个小箭头是需要实时的移动的,不同的位置小箭头的上面所谓的时间view移动的不同。
// // Slider.m // SliderPro // // Created by Yongchao Zhang on 12-9-13. // Copyright (c) 2012年 Yongchao Zhang. All rights reserved. // #import "Slider.h" #import <QuartzCore/QuartzCore.h> @implementation Slider @synthesize currentValue,maxValue,minValue; @synthesize currentLabel,totalLabel; @synthesize currentStr,totalStr; @synthesize delegate; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code minValue = 0; maxValue = 1; currentValue = 0; self.backgroundColor = [UIColor redColor]; self.userInteractionEnabled = YES; } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code //上半部分整体 popView= [[UIImageView alloc] init]; popView.userInteractionEnabled = NO; // [popView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"timeBack.png"]]]; [popView setImage:[UIImage imageNamed:@"timeBack.png"]]; [self addSubview:popView]; //时间部分 UIView *timeView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, popView.frame.size.width, self.frame.size.height/2 - 20)]; [timeView setBackgroundColor:[UIColor greenColor]]; currentLabel = [[UILabel alloc]init]; [currentLabel setBackgroundColor:[UIColor blackColor]]; [currentLabel setTextColor:[UIColor whiteColor]]; [currentLabel setTextAlignment:UITextAlignmentLeft]; [timeView addSubview:currentLabel]; totalLabel = [[UILabel alloc]init]; [totalLabel setBackgroundColor:[UIColor greenColor]]; // [totalLabel setTextColor:UIColorFromRGB(0x73736f)]; [totalLabel setTextColor:[UIColor redColor]]; [totalLabel setTextAlignment:UITextAlignmentLeft]; [timeView addSubview:totalLabel]; [popView addSubview:timeView]; //箭头部分 tagView = [[UIImageView alloc] init]; tagView.userInteractionEnabled = NO; // [tagView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"tag.png"]]]; [tagView setImage:[UIImage imageNamed:@"tag.png"]]; [self addSubview:tagView]; //下半部分 UIImage *stetchLeftTrack = [UIImage imageNamed:@"done.png"] ; UIImage *stetchRightTrack = [UIImage imageNamed:@"max.png"] ; bottomView= [[UIImageView alloc] initWithImage:stetchRightTrack]; [bottomView setFrame:CGRectMake(5, popView.frame.origin.y + popView.frame.size.height + tagView.frame.size.height+20 , self.frame.size.width-10, 6)]; CALayer *layers = [bottomView layer]; [layers setMasksToBounds:YES]; [layers setCornerRadius:4.0]; topView= [[UIImageView alloc] initWithImage:stetchLeftTrack]; [topView setFrame:CGRectMake(0, 0 , self.frame.size.width-10, 6)]; [bottomView addSubview:topView]; [self addSubview:bottomView]; } -(void)layoutSubviews{ [popView setFrame:CGRectMake(0, 0, 72, self.frame.size.height/2-18)]; [tagView setFrame:CGRectMake(0, popView.frame.origin.y + popView.frame.size.height-1, 6, 3)]; [currentLabel setFrame:CGRectMake(4, 2.0f, 30, 10)]; currentLabel.font=[UIFont systemFontOfSize:7.0f]; [totalLabel setFrame:CGRectMake(38, 2.0f, 30, 10)]; totalLabel.font=[UIFont systemFontOfSize:7.0f]; currentLabel.text = currentStr; totalLabel.text = totalStr; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch* touch = [touches anyObject]; CGPoint xy = [touch locationInView:self]; float pointX = xy.x-bottomView.frame.origin.x; if(pointX<0) pointX =0; if(pointX > bottomView.frame.size.width) pointX = bottomView.frame.size.width; percent = pointX / bottomView.frame.size.width; currentValue = percent *maxValue; [self updateProView:pointX]; [self.delegate scrollBegin:self]; } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch* touch = [touches anyObject]; CGPoint xy = [touch locationInView:self]; float pointX = xy.x-bottomView.frame.origin.x; if(pointX<0) pointX =0; if(pointX > bottomView.frame.size.width) pointX = bottomView.frame.size.width; percent = pointX / bottomView.frame.size.width; currentValue = percent *maxValue; [self updateProView:pointX]; [self.delegate scroll:self]; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch* touch = [touches anyObject]; CGPoint xy = [touch locationInView:self]; float pointX = xy.x-bottomView.frame.origin.x; if(pointX<0) pointX =0; if(pointX > bottomView.frame.size.width) pointX = bottomView.frame.size.width; percent = pointX / bottomView.frame.size.width; currentValue = percent *maxValue; [self updateProView:pointX]; [self.delegate scrollDone:self]; } -(void)updateProView:(float)_pointx{ CGRect rect = topView.frame; rect.size.width = _pointx; topView.frame = rect; float realX = _pointx + bottomView.frame.origin.x; CGRect popRect = popView.frame; popRect.origin.x = realX-popRect.size.width/2; if(realX < popRect.size.width/2){ popRect.origin.x = 0; } if(realX >self.frame.size.width - popRect.size.width/2){ popRect.origin.x = self .frame.size.width - popRect.size.width; } CGRect sanRect = tagView.frame; sanRect.origin.x = realX - sanRect.size.width/2; if(sanRect.origin.x < (bottomView.frame.origin.x - sanRect.size.width/2) ) sanRect.origin.x = bottomView.frame.origin.x - sanRect.size.width/2; if(sanRect.origin.x > (bottomView.frame.origin.x +bottomView.frame.size.width - sanRect.size.width/2)) sanRect.origin.x = bottomView.frame.origin.x +bottomView.frame.size.width - sanRect.size.width/2; tagView.frame = sanRect; popView.frame = popRect; } -(void)setMinValue:(float)_minValue{ minValue = _minValue; } -(void)setMaxValue:(float)_maxValue{ maxValue = _maxValue; } -(void)setCurrentValue:(float)_value{ currentValue = _value; percent = currentValue /maxValue; float pointX = percent * bottomView.frame.size.width; [self updateProView:pointX]; } @end注:代码比较乱,也难免有错误,毕竟只是为了验证思路而已。
最近项目中经常有文字放光效果的UI,特意在网路上找了下,开始是在code4app中找到一个,但是是不是的会出现不出现光晕的bug,在寻找找到了cocoachina会员hxy060799分享的GlowLabel,效果不错,特意写了注释贴出来,以防他日忘记。
1、新建一个基于UILabel的子类
2、在这个子类中定义red、green、blue三个颜色值变量和一个发光光晕范围变量size。
3、复写UILable的drawTextInRect方法,并使用CGContextRef来进行光晕效果绘制。
基本思路就是这样子了,下面是部分主要代码:
.h文件
//创建UILable的子类 GlowLable @interface GlowLabel : UILabel //定义颜色值全局变量和放大值全局变量 @property(assign,nonatomic)float redValue; @property(assign,nonatomic)float greenValue; @property(assign,nonatomic)float blueValue; @property(assign,nonatomic)float size; @end
.m文件
@implementation GlowLabel @synthesize redValue; @synthesize greenValue; @synthesize blueValue; @synthesize size; -(id) initWithFrame: (CGRect)frame { if ((self = [super initWithFrame:frame])) { //变量初始化 redValue = 0.0f; greenValue = 0.50f; blueValue = 1.0f; size=20.0f; } return self; } //重写UILable类的drawTextInRect方法 -(void) drawTextInRect: (CGRect)rect { //定义阴影区域 CGSize textShadowOffest = CGSizeMake(0, 0); //定义RGB颜色值 float textColorValues[] = {redValue, greenValue, blueValue, 1.0}; //获取绘制上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); //保存上下文状态 CGContextSaveGState(ctx); //为上下文设置阴影 CGContextSetShadow(ctx, textShadowOffest, size); //设置颜色类型 CGColorSpaceRef textColorSpace = CGColorSpaceCreateDeviceRGB(); //根据颜色类型和颜色值创建CGColorRef颜色 CGColorRef textColor = CGColorCreate(textColorSpace, textColorValues); //为上下文阴影设置颜色,阴影颜色,阴影大小 CGContextSetShadowWithColor(ctx, textShadowOffest, size, textColor); [super drawTextInRect:rect]; //释放 CGColorRelease(textColor); CGColorSpaceRelease(textColorSpace); //重启上下文 CGContextRestoreGState(ctx); } @end
最终效果: