代码改变世界

9宫格视图的实现

2010-09-10 17:11  乱世文章  阅读(330)  评论(0编辑  收藏  举报


一、实现步骤
1、新建一个Window-based-application。
2、新建类 NinePCSViewController。
Interface部分:

@interface NinePCSViewController : UIViewController {
 NSMutableArray* icons;//9格按钮图片文件名
 NSString* bgImageFileName;//背景图文件名
 NSArray* buttons;//9个按钮
}
-(void)setButtons:(NSArray*)a;
-(void)setBgImageFileName:(NSString*)s;
-(void)setIcons:(NSArray*)arr;
@end

implementation部分中, loadView 方法很简单:
-(void)loadView{
 self.view=[[UIView alloc]initWithFrame:CGRectMake(0, 20, 320, 460)];
}
注意视图高度是460,并不是480,因为屏幕顶部有20个像素的高度会被信号栏占据。
代码的重心是3个setter方法。
bgImageFileName变量的setter方法会根据参数加载指定的背景图片:
@implementation NinePCSViewController
-(void)setBgImageFileName:(NSString *)s{
 bgImageFileName=s;
 UIImageView* bgView=[[UIImageView alloc]
       initWithFrame:self.view.frame];
 [bgView setImage:[UIImage imageNamed:s]];
 [bgView setUserInteractionEnabled:YES];//允许响应触摸事件
 self.view=bgView;
 [bgView release];
}
icons实际上是一个字符串数组,用它来指定9个格子内的按钮背景图标。同时,只要调用者对icons成员进行赋值,该setter方法自动生成9个按钮(当然,不一定是9个,看你的需要而定)并加载9张图片作为按钮背景图片:
-(void)setIcons:(NSArray*)arr{
 if(icons!=nil)//若pcs_image_name不为空,清除以前的内容
  [icons release];
 else
  icons=[[NSMutableArray array]retain];
 
 if (arr.count>=9) {//如果arr大于9个,只取前9个
  for (int i=0; i<9; i++) {
   [icons addObject:[arr objectAtIndex:i]];
  }
 }else{
  for (int i=0;i<arr.count;i++) {
   [icons addObject:[arr objectAtIndex:i]];
  }
 }
 NSMutableArray* array=[[NSMutableArray array]retain];
 UIButton *button;
 int i=0;
    for (NSString* icon in icons) {
  NSLog(@"%@",icon);
        CGRect frame;
        button = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
        [button setImage:[UIImage imageNamed:icon] forState:UIControlStateNormal];//设置按钮图片
        button.tag = i;
        //设置按钮坐标及大小
        frame.size.width = 60;
        frame.size.height = 75;
  //按钮横向间隔38,左边距32
        frame.origin.x = (i%3)*(59+38)+32;
  //按钮纵向间隔18,标题栏42,上边距38
        frame.origin.y = floor(i/3)*(75+18)+40+42;
        [button setFrame:frame];
       
        [button setBackgroundColor:[UIColor clearColor]];
  //为按钮增加事件方法
        [button addTarget:self action:@selector(btnPressed:)
   forControlEvents:UIControlEventTouchUpInside];
  [array addObject:button];
  [button release];
        i++;
    } 
 self.buttons=array;//调用 setButtons
}
buttons也是一个数组,不过其中存放的是9个按钮对象。当调用setIcons时,会自动调用setButtons,setButtons把没个按钮加载到视图中,因此程序员不应当显式调用该方法:
-(void)setButtons:(NSArray *)a{
 buttons=a;//这个不会调用 setButtons
 for (UIButton* b in a){
  [self.view addSubview:b];
 }
}
btnPressed是所有按钮共用的事件处理方法,这里只是简单的打印按钮的tag属性(用以识别各个按钮):
-(void)btnPressed:(id)sender{
 UIButton *b = (UIButton *)sender;
 NSLog(@"button %d is clicked!",b.tag);
}
3、使用 NinePCSViewController。
使用起来非常简单,构造一个 NinePCSViewController,然后设置它的两个属性 :
NinePCSViewController* root=[[NinePCSViewController alloc]init];
 root.bgImageFileName=@"bgImage.png";
 NSArray* a=[[NSArray alloc]initWithObjects:
    @"icon1.png",@"icon1.png",@"icon1.png",
    nil];
 root.icons=a;
看起来是这个样子的:
 
二、一些改进
1、9个按钮要想放到合适的位置并达到合适的效果也不是一件容易的事情,我们应该设置几个变量来控制按钮的位置和大小:
//9宫格上留白,左留白,按钮横向间距,按钮纵向间距,按钮宽/高
NSInteger topMargin,leftMargin,horizontalGap,verticalGap,buttonWidth,buttonHeight;
将这些变量声明为属性,并使用@synthesize。
同时修改setIcons中的布局代码,使用变量而不是固定值进行按钮的布局。
当然,我们还可以在初始化方法中给这些属性提供一些默认值,用户可以不进行任何改变就使用 NinePCSViewController 。
2、原有的事件处理逻辑还是过于简陋了,我们需要把他放到类的外部,这样业务逻辑的改变不需要改变类的代码。因此我们需要委托自定义协议。
定义新的协议NinePCSViewControllerDelegate。申明属性delegate。修改实现代码(具体过程请参考另一文档“下拉列表框实现”)。