0
回答
实现类似Android Grid效果的列表视图
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   

ios里的UITableView,功能是很强大的。但是没有Android类似Grid的效果。比如类似解决ListView滚动卡的问题。因为UITableView的每行只支持显示一个视图。如果细粒度的比如类似gallery的效果,就需要自己解决了。

最近写的一个类似效果的原型:

imageimage

主要解决了:

  • 如何生成grid的样式
  • 图片的阴影效果

实现grid效果有两个办法:

  1. 自己编程实现,这次我就是自己实现的
  2. 使用第三方库实现,这次没有用,主要是时间太紧,怕陷进去再有质量问题,影响工期,等有时间了再好好看看。

这里提到的第三方库是AQGridView。项目首页在这里:http://www.oschina.net/p/aqgridview

使用它生成视图的效果:

imageimage

看起来还是不错的。见这里:http://quatermain.tumblr.com/post/528737778/aqgridview-lives-for-my-ipad-dev-camp-hackathon,是作者的博客。

首先说一下实现grid的做法。

创建一个UIView:

@interface CdGridView : UIView <UITableViewDelegate,UITableViewDataSource>{ 
    UITableView *_tableView; 
    NSArray *_cdInfos; 
    int _columnSize; 
}

封装了table view,以及一个数组(数据模型),另外,每行显示的列数。

重载了该UIView的init方法:

- (id)initWithFrame:(CGRect)frame columnSize:(int)columnSize cdInfos:(NSArray *)cdInfos{ 
    
    self = [super initWithFrame:frame]; 
    if (self) { 
        _tableView=[[UITableView alloc] initWithFrame:frame]; 
        _tableView.dataSource=self; 
        _tableView.delegate=self; 
        [_tableView setSeparatorStyle:UITableViewCellEditingStyleNone];//设置取消列表的分割线 
        _tableView.allowsSelection=NO;//设置不允许选择列表条目 
        [self addSubview:_tableView]; 
        
        _columnSize=columnSize;//设置列数 
        _cdInfos=cdInfos; 
    } 
    return self; 
}

这里通过table view属性取消了列表分割线,以及禁用了选择列表条目。

另外几个方法:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *simpleTableIdentifier=@"SimpleTableIdentifier"; 
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; 
    
    if(cell==nil){ 
        cell=[[[CdGridCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                reuseIdentifier:simpleTableIdentifier 
                                        columnSize:_columnSize] 
              autorelease]; 
    } 
    
    for (int i=0; i<_columnSize; i++) { 
        UIView *rowView=[cell.contentView.subviews objectAtIndex:0]; 
        UIView *imageContainerView=[rowView.subviews objectAtIndex:i]; 
        UIImageView *imageView=[imageContainerView.subviews objectAtIndex:0]; 
        
        if ([indexPath row]*_columnSize+i<[_cdInfos count]) { 
            CdInfo *cdInfo=[_cdInfos objectAtIndex:[indexPath row]*_columnSize+i]; 
            imageView.image=[UIImage imageNamed:cdInfo.coverPhotoPath]; 
            imageView.layer.shadowOpacity = 1.0; 
        }else { 
            imageView.image=nil; 
            imageView.layer.shadowOpacity = 0; 
        }        
    } 
    
    if ([[tableView indexPathsForVisibleRows] count]>0) {//刚创建的时候table view是空的 
        int _firstIndex=[[[tableView indexPathsForVisibleRows] objectAtIndex:0] row]*_columnSize; 
        NSNumber *currentFirstRecordIndex=[NSNumber numberWithInt:_firstIndex]; 
        NSDictionary *params=[[NSDictionary alloc] initWithObjectsAndKeys:currentFirstRecordIndex,@"currentFirstRecord",nil]; 
        [[NSNotificationCenter defaultCenter] postNotificationName:@"current.first.record" object:self userInfo:params]; 
        //目前不是很准,当移动到第一行的时候,first index还是第二行的首记录 
    } 
    
    return cell; 
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 
    NSInteger numberOfRows=ceil([_cdInfos count]*1.0/_columnSize); 
    return numberOfRows; 
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 
    return WIDTH/_columnSize; 
}

-(void)setFistVisibleRecord:(int)recordIndex{ 
    [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:recordIndex/_columnSize inSection:0] 
                      atScrollPosition:UITableViewScrollPositionTop animated:NO]; 
}

用来实现table view要求的delegate,以及辅助方法。最后一个setFistVisibleRecord:方法,是用于设置列表显示的首记录。有时候我们需要显示比如从第17个记录开始,这个方法可以帮助将第17个记录所在行显示在页面的第一行上。

往下,说一下阴影效果的实现,其实就是在原有的UIImageView下面再显示一个半透明阴影的矩形框,矩形框的边缘是圆弧的,这样看起来比较自然。

可通过类似下面的代码来实现:

imageView.layer.shadowColor=[UIColor darkGrayColor].CGColor; 
imageView.layer.shadowOffset = CGSizeMake(MARGIN-2, MARGIN-2); 
imageView.layer.shadowOpacity = 0.8; 
imageView.layer.shadowRadius = 3.0; 
imageView.layer.shadowPath = [UIBezierPath bezierPathWithRect:imageView.bounds].CGPath;

这里用到了贝塞尔曲线来设置阴影的path,否则性能比较差。

看下这个,就知道阴影的效果了:

image

这是屏蔽了设置UIImage后的样子,即没有设置图片,只有阴影的样子。

原文转自:http://marshal.easymorse.com/archives/4142

举报
无鸯
发帖于6年前 0回/962阅
顶部