自定义控件专题总结


iPhone中自定义控件实现步骤
objective-c中是所有对象间的交互是如何实现的? (面试题)
答:记住,在Objective-C中所有对象间的交互都是通过指针实现的。
objective-c中是如何实现线程同步的?    (面试题)

线程同步和线程异步有什么区别?
打个比方,如果你在等一个人,
同步的时候,你会一直等到她来了之后才做其他事情,这个过程除了等待你啥都不会做,
异步的时候,你一边在等,可能一边玩游戏或者是看报纸什么的,一直到她到来,你的等待状态才会结束
在实现上,同步的过程会阻塞进程的所有其他操作,将同步转换为异步的最常见方法则是
将会阻塞进程的等待操作放入到一个新的进程中,同时为该等待操作添加一个监视器,在检测到等待操作完成的时候结束等待的进程。


1、在系统控件上进行功能扩充的自定义控件
2、是完全重写控件,包括自定义控件的触发事件,例子如:自定义Button

具体的实现
例如:自定义Button ,可以采用两种实现方案。
1、有响应事件,直接继承UIButton的自定义控件。
2、从UIVIew继承,然后实现点击事件和其他一些属性。无响应事件,继承自UIView的自定义控件。一个自定义类,从UIView继承

自定义initwithframe(frame,images,title,)
三个uiimage,highlight,normal和disable,
一个uilabel,显示文本.
在touch里面实现点击事件,

iPhone控件自定义控件开发:重绘还是组合
iPhone开发当中处于需求经常需要一些自定义控件。当然,处于成本和质量的考虑,请优先选择系统控件。当真正需要开发自定义控件的时候,通常又会有两种选择:重绘或者组合。重绘就是重写控件的绘制函数,在该函数中绘制期望的效果。而组合就是通过不同控件的搭配形成满足需求的控件。当然,根据自定义控件需求的不一样,有的适合用重绘,有的则是适合用组合,有时则是两种实现都适用。比如星级控件是项目中比较经常用到的但是系统没有提供的一种控件。对于这个一个控件我们又是要如何选择呢?

重绘实现:

@interface StarRating:UIView{    
    int numberStars;    
    int rating;
}
@property int numberStars;
@property int rating;
- (id)initWithNumberOfStars:(int)numStars;
- (id)initWithNumberOfStars:(int)numStars initialRating:(int)initialRating;
@end
@implementation StarRating
- (void)drawRect:(CGRect)rect {    
    UIImage *onImage = [UIImage imageNamed:@"on.png"];    
    UIImage *offImage = [UIImage imageNamed:@"off.png"];    
    for (int i=1; i<=[self numberStars]; i++)    {        
        UIImage *img = (i <= [self rating]) ? onImage : offImage;        
        CGPoint imagePoint;        
        imagePoint.x = BTN_WIDTH * (i-1);        
        imagePoint.y = 0.0f;        
        [img drawAtPoint:imagePoint];    
    }
}
@end


其中描绘部分是根据星级rating进行图片选择,星级以下的用on.png,星级以上的off.png。
组合实现:

@interface StarRating: UIControl {
    NSMutableArray            *starArray;
    NSInteger                     numberStars;
    NSInteger                     rating;
}
-(id)initWithFrame:(CGRect)frame andStars:(NSInteger)inNumStars;
@end
@implementation StarRating
-(id)initWithFrame:(CGRect)frame andStars:(int)inNumStars {   
    if (self = [super initWithFrame:frame])    
    {        
        approxMode = InterpolationMode_Half;        
        starNum = inNumStars;       
        [self prepareStars:starNum frame:frame];    
    }   
    return self;
}
-(void)setRating:(int)aRating{   
    rating= aRating;   
    [self fillStars];
}
- (void) prepareStars: (int)aStarNum frame: (CGRect)frame {
    starArray = [[NSMutableArray alloc] initWithCapacity:aStarNum];
    float width = frame.size.width/aStarNum;
    float height = frame.size.height;
    for(int i=0; i < aStarNum; i++) {
        UIImageView * star = [[UIImageView alloc] initWithFrame:CGRectMake(0+(i*width), 0, width, height)];
        [starArray addObject:star];
        [self addSubview:star];
        [star release];
    }
}
- (void)fillStars{    
    UIImage *onImage = [UIImage imageNamed:@"on.png"];    
    UIImage *offImage = [UIImage imageNamed:@"off.png"];    
    for (int i=1; i<=[self numberStars]; i++)    {           
       UIImage *img = (i <= [self rating]) ? onImage : offImage;   
       UIImageView *star = (UIImageView *)[self subViewAtIndex:i]; 
    [star setImage:img];
    }
}


其中是预先创建五个UIImageView的子控件,然后根据星级rating进行子控件的图片属性设定。

对比:
1 重绘方案只有自身一个控件,而组合实现则是包含五个子控件。资源和效率上重绘的方案会比较有优势。
2 重绘需要处理描绘,而组合则是由子控件负责描绘。因此从描绘处理上,组合方案比较简单
3 需求变更时,重绘方案可能需要修改描绘代码,而组合方案在设计合理的情况下是可以轻松替换子控件的类型。

iPhone中自绘实现步骤
1. 继承@interface MyView : UIView {
2. 实现- (void)drawRect:(CGRect)rect
3. 调用addSubView把新生成的view加入进来显示


addSubView[window addSubview:viewController.view]; 

4.示例代码
- (void)drawRect:(CGRect)rect { 
    // create the bitmap context 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(nil,100,100,8,400, colorSpace,kCGImageAlphaPremultipliedLast); 
    CFRelease(colorSpace); 
    //    create an arrow image 
    // set the fill color 
    CGColorRef fillColor = [[UIColor blackColor] CGColor]; 
    CGContextSetFillColor(context, CGColorGetComponents(fillColor)); 
    
    CGContextBeginPath(context); 
    CGContextMoveToPoint(context, 8.0f, 13.0f); 
    CGContextAddLineToPoint(context, 24.0f, 4.0f); 
    CGContextAddLineToPoint(context, 24.0f, 22.0f); 
    CGContextClosePath(context); 
    CGContextFillPath(context); 
    CGContextSelectFont ( context, "Arial", 10.f, kCGEncodingMacRoman ); 
    CGContextSetRGBFillColor ( context, 0.0f, 0.0f, 0.f, 1.f ); 
    CGContextSetShouldAntialias ( context, 0 );    
    CGContextShowText(context, "hh", 2); 
    
    // convert the context into a CGImageRef 
    CGImageRef image = CGBitmapContextCreateImage(context); 
    CGContextRelease(context); 
    
    UIImage* image2 = [UIImage imageWithCGImage:image]; 
    [image2 drawInRect:CGRectMake(0, 0, 120, 160)]; 
    
    NSString* myStr = @"中文"; 
    UIFont* font = [UIFont systemFontOfSize:12.0]; 
    [myStr drawInRect: CGRectMake(160, 240, 100, 130) withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentCenter]; 


自定义控件 iphone/ipad
1,最常见的就是button,也是最简单的,苹果已经封装好了,只需要设置它的type为custom,然后设置其background就可以了;
2,segemented control,可以在xib里面对应的segement中设置其image就可以,不过有点需要注意的是假设你所有图片的宽度可能为70,那么你segemented control的宽度必须稍微短点,66即可。我以前在实践的时候,按照其本身宽度来设置,中间相连部分就会很难看;
3,navigation bar自定义也是十分常见,我所用的方法是定义一个imageview,然后insertSubview到第0层。不过用这种方法有点不好的是会把系统navigation bar本身的标题,按钮盖住。所以我们有的时候需要重新自定义标题,按钮,然后addsubview到bar上面,具体可以参考我下面给的demo;
4,search bar自定义,最开始的时候以为是不能定义,后来在qq音乐里看到很漂亮的search bar,开始研究。类似与导航栏,这次我们需要insertSubview到第1层,imageview的宽度最好设为search bar默认的高度44。接下来我们还可以自定义它上面的按钮,我们打印出它的子视图,找到按钮的那一层,取出按钮,然后重新在定义。
5,还有一个常见的需要自定义的,tableViewCell。自定义cell的方法其实很多,我就主要讲我常用的方法,先添加一个xib文件,里面只有一个tableviewcell,这个xib文件对应的主类应该是你需要自定义的那个类,在cell里面自定义图片和label,设置对应的tag为1和2。在那个主类里面定义uitableviewcell,并关联到刚才的xib文件。
6,tabbarcontroller也是可以自定义的,我所讲的是自己实践过成功过的方法,重写一个tabbarcontroller类文件,主要是隐藏tababr。接下来是在app文件里面定义一个viewcontroller,把刚才tabbarcontroller的类文件insert到第0层就可以了。具体可以参考我以前的demo。
今天就先讲一个滑动scrollview以及分页效果,在xib里面画好scrollview后,我们在.m文件初始化图片数据。
稍微解释下,两个循环是将图片添加到scrollview上面,其中ImageViewForScrollView是我自定义的imageview,用来处理图片的点击事件。里面比较关键的是如何设置每张图片的位置,不要忘记设置scrollview的contentSize,必须和实际内容的宽度一致,还要大于scrollview的宽度,不然是滑不动的。图片下面部分添加一个分页控制器,那么如何去控制分页呢

在绝大部分IOS应用的开发过程中,都不会使用IB, 使用代码自定义界面控件尤其重要。  本文就介绍下如何用代码自定义BUTTON控件。

UIButton *pBtn=[UIButton buttonWithType:UIButtonTypeRoundedRect];   //使用这个类方法来初始化button对象
[pBtn setTitle:@"MyButton" forState:UIControlStateNormal];  
[pBtn setFrame:CGRectMake(10, 20, 80, 30)];  
[pView addSubview:pBtn];   
//添加按键响应:
[pBtn addTarget:self action:@selector(buttonTest:)forControlEvents:UIControlEventTouchUpInside];

- (void)buttonTest:(id)sender
{
NSLog(@"button test");
}

自定义按钮2
UIButton *Btn;
CGRect frame;       
Btn = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; //按钮的类型      
[Btn setImage:[UIImage imageNamed:@“aaa.png”] forState:UIControlStateNormal];//设置按钮图片  
Btn.tag = 10;  
frame.size.width = 59;  //设置按钮的宽度  
frame.size.height = 59;   //设置按钮的高度   
frame.origin.x =150;   //设置按钮的位置    
frame.origin.y =260;    
[Btn setFrame:frame];     
[Btn setBackgroundColor:[UIColor clearColor]];     
[Btn addTarget:self action:@selector(btnPressed:)forControlEvents:UIControlEventTouchUpInside];  //按钮的单击事件   
[self.view addSubview:Btn];      
[Btn release];

-(void)btnPressed:(id)sender
 {
     //在这里实现按钮的单击事件
}

用代码生成了TextField控件和Button控件,如何添加触发事件?
UITextField *textField=[[UITextField alloc] init];//添加事件
[textField addTarget:selfaction:@selector(valueChanged:)forControlEvents:UIControlEventValueChanged];//当textField内容改变时会触发
-(void)valueChanged:(id)sender {     
   //....处理文本改变时 statement
} 

在代码中将创建的button控件,后置(send to back)
[self.view sendSubviewToBack:button]; 

button控件用代码设置Custom属性。
UIImage *buttonUpImage = [UIImageimageNamed:@"button_up.png"];
UIImage *buttonDownImage =[UIImage imageNamed:@"button_down.png"];
//创建按钮,并设置类型。
UIButton *button = [UIButtonbuttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0.0,0.0, buttonUpImage.size.width, buttonUpImage.size.height);
[buttonsetBackgroundImage:buttonUpImageforState:UIControlStateNormal];
[buttonsetBackgroundImage:buttonDownImageforState:UIControlStateHighlighted];
[button setTitle:@"Tap"forState:UIControlStateNormal];
[button addTarget:selfaction:@selector(buttonTapped:)forControlEvents:UIControlEventTouchUpInside]; //用代码实现控件的触发事件
[button addTarget:self action:@selector(buttonTapped:)forcontrolEvents:UIControlEventTouchUpInside]

buttonTapped这个是你对button的UIControlEventTouchUpInside事件自定义响应函数。

From http://www.cocoachina.com/bbs/read.php?tid=49128&page=1

你可能感兴趣的:(Objective-C)