`
jsntghf
  • 浏览: 2544755 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

自定义多行多列视图

    博客分类:
  • iOS
阅读更多

DataGridComponent.h

 

#import <Foundation/Foundation.h>

/**
 * DataGrid数据源
 */
@interface DataGridComponentDataSource : NSObject {
	/**
	 * 标题列表
	 */
	NSMutableArray *titles;
	
	/**
	 * 数据体
	 */
	NSMutableArray *data;
	
	/**
	 * 列宽
	 */
	NSMutableArray *columnWidth;
}

@property (retain) NSMutableArray *titles;
@property (retain) NSMutableArray *data;
@property (retain) NSMutableArray *columnWidth;

@end

@interface DataGridScrollView : UIScrollView {
	id dataGridComponent;
}

@property (assign) id dataGridComponent;

@end

/**
 * 数据列表组件,支持上下与左右滑动
 */
@interface DataGridComponent : UIView<UIScrollViewDelegate> {	
	//左下列视图
	DataGridScrollView *vLeft;
	
	//右下列视图
	DataGridScrollView *vRight;
	
	//右下列内容
	UIView *vRightContent;
	
	//左下列内容
	UIView *vLeftContent;
	
	//右上标题
	UIView *vTopRight;
	
	//左上标题
	UIView *vTopLeft;
	
	//列表数据源
	DataGridComponentDataSource *dataSource;
	
	//内容总高度
	float contentHeight;
	
	//内容总宽度
	float contentWidth;
	
	//单元格默认高度
	float cellHeight;
	
	//单元格默认宽度
	float cellWidth;	
}

@property (readonly) DataGridScrollView *vRight;
@property (readonly) DataGridScrollView *vLeft;
@property (readonly) float cellHeight;
@property (retain) DataGridComponentDataSource *dataSource;

/**
 * 用指定显示区域与数据源初始化对象
 */
- (id)initWithFrame:(CGRect)aRect data:(DataGridComponentDataSource *)aDataSource;

@end

 

DataGridComponent.m

 

#import "DataGridComponent.h"

@implementation DataGridScrollView

@synthesize dataGridComponent;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
	UITouch *t = [touches anyObject];
	if([t tapCount] == 1){
		DataGridComponent *d = (DataGridComponent *)dataGridComponent;
		int idx = [t locationInView:self].y / d.cellHeight;
		[UIView beginAnimations:nil context:nil];
		[UIView setAnimationDuration:0.65];
		for(int i = 0;i < [d.dataSource.titles count];i++) {
			UILabel *l = (UILabel *)[dataGridComponent viewWithTag:idx * d.cellHeight + i + 1000];
			l.alpha = .5;
		}
		for(int i = 0;i < [d.dataSource.titles count];i++) {
			UILabel *l = (UILabel *)[dataGridComponent viewWithTag:idx * d.cellHeight + i + 1000];
			l.alpha = 1.0;
		}		
		[UIView commitAnimations];
	}
}

@end

@implementation DataGridComponentDataSource

@synthesize titles, data, columnWidth;

@end

@interface DataGridComponent(Private)

/**
 * 初始化各子视图
 */
- (void)layoutSubView:(CGRect)aRect;

/**
 * 用数据项填充数据
 */
- (void)fillData;

@end

@implementation DataGridComponent

@synthesize dataSource, cellHeight, vRight, vLeft;

- (id)initWithFrame:(CGRect)aRect data:(DataGridComponentDataSource*)aDataSource {
	self = [super initWithFrame:aRect];
	if(self != nil){				
		self.clipsToBounds = YES;
		self.backgroundColor = [UIColor grayColor];
		self.dataSource = aDataSource;
        
		//初始显示视图及Cell的长宽高
		contentWidth = .0;
		cellHeight = 70.0;
		cellWidth = [[dataSource.columnWidth objectAtIndex:0] intValue];
		for(int i = 1;i < [dataSource.columnWidth count];i++)
			contentWidth += [[dataSource.columnWidth objectAtIndex:i] intValue];
		contentHeight = [dataSource.data count] * cellHeight;		
		contentWidth = contentWidth + [[dataSource.columnWidth objectAtIndex:0] intValue]  < aRect.size.width ? aRect.size.width : contentWidth;
        
		//初始化各视图
		[self layoutSubView:aRect];
		
		//填充数据
		[self fillData];
	}
	return self;
}

- (void)layoutSubView:(CGRect)aRect {
	vLeftContent = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 60, contentHeight)];
	vRightContent = [[UIView alloc] initWithFrame:CGRectMake(0, 0, aRect.size.width - cellWidth, contentHeight)];
	
	vLeftContent.opaque = YES;
	vRightContent.opaque = YES;
	
	//初始化各视图
	vTopLeft = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cellWidth, cellHeight)];
	vLeft = [[DataGridScrollView alloc] initWithFrame:CGRectMake(0, cellHeight, aRect.size.width, aRect.size.height - cellHeight)];
	vRight = [[DataGridScrollView alloc] initWithFrame:CGRectMake(cellWidth, 0, aRect.size.width - cellWidth, contentHeight)];
	vTopRight = [[UIView alloc] initWithFrame:CGRectMake(cellWidth, 0, aRect.size.width - cellWidth, cellHeight)];
	
	vLeft.dataGridComponent = self;
	vRight.dataGridComponent = self;
	
	vLeft.opaque = YES;
	vRight.opaque = YES;
	vTopLeft.opaque = YES;
	vTopRight.opaque = YES;
	
	//设置ScrollView的显示内容
	vLeft.contentSize = CGSizeMake(aRect.size.width, contentHeight);
	vRight.contentSize = CGSizeMake(contentWidth, aRect.size.height - cellHeight);
	
	//设置ScrollView参数
	vRight.delegate = self;
	
	vTopRight.backgroundColor = [UIColor grayColor];		
	vRight.backgroundColor = [UIColor grayColor];
	vTopLeft.backgroundColor = [UIColor colorWithRed:.7 green:.7 blue:.7 alpha:1];
	
	//添加各视图
	[vRight addSubview:vRightContent];
	[vLeft addSubview:vLeftContent];
	[vLeft addSubview:vRight];
	[self addSubview:vTopLeft];
	[self addSubview:vLeft];
	
	[vLeft bringSubviewToFront:vRight];
	[self addSubview:vTopRight];
	[self bringSubviewToFront:vTopRight];	
}

- (void)fillData {
	float columnOffset = 0.0;
    
	//填充标题数据
	for(int column = 0;column < [dataSource.titles count];column++){
		float columnWidth = [[dataSource.columnWidth objectAtIndex:column] floatValue];
		UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(columnOffset, 0, columnWidth - 1, cellHeight)];
		l.font = [UIFont systemFontOfSize:12.0f];
		l.text = [dataSource.titles objectAtIndex:column];
		l.backgroundColor = [UIColor grayColor];
		l.textColor = [UIColor whiteColor];
		l.textAlignment = UITextAlignmentCenter;
        
		if( 0 == column) {
			[vTopLeft addSubview:l];
		} else {	
			[vTopRight addSubview:l];
			columnOffset += columnWidth;
		}
		[l release];
	}	
    
	//填充数据内容	
	for(int i = 0;i < [dataSource.data count];i++){		
		NSArray *rowData = [dataSource.data objectAtIndex:i];
		columnOffset = 0.0;
		
		for(int column = 0;column < [rowData count];column++){
			float columnWidth = [[dataSource.columnWidth objectAtIndex:column] floatValue];;
			UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(columnOffset, i * cellHeight, columnWidth, cellHeight - 1)];
			l.font = [UIFont systemFontOfSize:12.0f];
			l.text = [rowData objectAtIndex:column];
			l.textAlignment = UITextAlignmentCenter;
			l.tag = i * cellHeight + column + 1000;
			if(i % 2 == 0)
				l.backgroundColor = [UIColor whiteColor];
			
			if(0 == column) {
				l.frame = CGRectMake(columnOffset, i * cellHeight, columnWidth - 1 , cellHeight - 1 );
				[vLeftContent addSubview:l];
			} else {	
				[vRightContent addSubview:l];
				columnOffset += columnWidth;
			}
			[l release];
		}
	}	
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {	
	vTopRight.frame = CGRectMake(cellWidth, 0, vRight.contentSize.width, vTopRight.frame.size.height);
	vTopRight.bounds = CGRectMake(scrollView.contentOffset.x, 0, vTopRight.frame.size.width, vTopRight.frame.size.height);
	vTopRight.clipsToBounds = YES;	
	vRightContent.frame = CGRectMake(0, 0, vRight.contentSize.width, contentHeight);
	[self addSubview:vTopRight];
	vRight.frame = CGRectMake(cellWidth, 0, self.frame.size.width - cellWidth, vLeft.contentSize.height); 
	[vLeft addSubview:scrollView];	
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
	scrollView.frame = CGRectMake(cellWidth, 0, scrollView.frame.size.width, self.frame.size.height);
	vRightContent.frame = CGRectMake(0, cellHeight - vLeft.contentOffset.y, vRight.contentSize.width, contentHeight);	
	vTopRight.frame = CGRectMake(0, 0, vRight.contentSize.width, vTopRight.frame.size.height);
	vTopRight.bounds = CGRectMake(0, 0, vRight.contentSize.width, vTopRight.frame.size.height);
	[scrollView addSubview:vTopRight];
	[self addSubview:scrollView];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
	if(!decelerate)
		[self scrollViewDidEndDecelerating:scrollView];
}

- (void) dealloc {
	[vLeft release];
	[vRight release];
	[vRightContent release];
	[vLeftContent release];
	[vTopLeft release];
	[vTopRight release];
	[super dealloc];
}

@end

 

使用示例:

 

- (void)viewDidLoad {	
	DataGridComponentDataSource *ds = [[DataGridComponentDataSource alloc] init];	
	ds.columnWidth = [NSArray arrayWithObjects:@"40", @"70", @"70", @"70", @"70", @"70", @"70", nil];
	ds.titles = [NSArray arrayWithObjects:@"节次", @"周一", @"周二", @"周三", @"周四", @"周五", @"周六", nil];
	ds.data = [NSArray arrayWithObjects:
               [NSArray arrayWithObjects:@"1", @"", @"英语", @"", @"计算机",@"", @""], 
               [NSArray arrayWithObjects:@"2", @"", @"英语", @"国际时事", @"计算机", @"", @""], 
               [NSArray arrayWithObjects:@"3", @"", @"英语", @"", @"计算机", @"", @""], 
               [NSArray arrayWithObjects:@"4", @"国际时事", @"", @"", @"计算机", @"", @""], 
               [NSArray arrayWithObjects:@"5", @"", @"", @"国际时事", @"", @"", @"国际时事"], nil];
	DataGridComponent *grid = [[DataGridComponent alloc] initWithFrame:CGRectMake(0, 0, 320, 500) data:ds];
	[ds release];
	[self.view addSubview:grid];
	[grid release];
    [super viewDidLoad];
}

 

示例图:


分享到:
评论
2 楼 jsntghf 2014-12-17  
paopeter1111 写道
請問自動換行語法,謝謝!!

参考:http://eric-gao.iteye.com/blog/1298816
1 楼 paopeter1111 2014-12-16  
請問自動換行語法,謝謝!!

相关推荐

    Android 多行多列CheckBox

    综上,实现"Android 多行多列CheckBox"需要理解Android布局系统,熟练掌握RecyclerView的使用,以及自定义Adapter和数据绑定。通过合理的布局设计和事件处理,可以创建出满足需求的用户界面。在实际开发中,可以根据...

    实现多行多列单选框(自定义控件)

    总之,实现多行多列单选框需要对Android UI框架有深入的理解,涉及到视图绘制、事件处理、布局管理等多个方面。通过这样的自定义控件,我们可以为用户提供更加符合项目需求的交互体验。如果你正在寻找如何实现这一...

    RadioButton实现多行多列单选

    在本场景中,我们讨论的主题是如何利用`RadioButton`在布局中实现多行多列的单选效果。这个功能在创建例如设置界面、问卷调查或者选项列表时非常常见。 `RadioButton`属于`RadioGroup`的一部分,`RadioGroup`是一个...

    GridView从后台获取数据实现多行多列

    本教程将详细讲解如何自定义GridView,从后台获取数据,并实现多行多列的效果,以及如何获取TextView中的文本内容。 首先,我们需要了解GridView的基本使用。GridView继承自ViewGroup,它会根据指定的列数自动排列...

    listview多行多列单选

    "listview多行多列单选"指的是在一个ListView中实现每一行可以被选择,同时支持多列展示的特性。这种功能通常应用于如通讯录、菜单列表等场景,用户可以逐个选择列表中的项。以下是对这个主题的详细讲解: 1. **...

    GridLayout + BaseQuickAdapter网格多行多列

    `GridLayout`默认会平分每一行和每一列的空间,所以要实现多行多列,只需在`GridLayout`中设置合适的子视图大小。对于`BaseQuickAdapter`,每个数据项的视图大小会在`convert`方法中根据数据模型动态设定。 通过...

    QTableWidget QTableView 自定义复杂表头(多行表头,表头合并) 、冻结、固定特定的行

    例如,你可以创建多个`QTableWidgetItem`并设置它们的文本和字体,然后利用`setHorizontalHeaderItem`和`setVerticalHeaderItem`方法将这些自定义项插入到表头。如果需要合并表头,可以通过调整`QHeaderView`的大小...

    QT表头支持多列显示,功能强大

    在QT中,QTableView、QTableWidget等组件提供了表格展示的功能,其中“QT表头支持多列显示”这一特性,使得开发者能够创建更为复杂的表格布局,以满足各种数据展示的需求。 在QT中实现多列表头并不复杂,主要是通过...

    RecyclerView显示不同item

    这通常涉及到自定义适配器和视图holder的实现。 首先,RecyclerView的工作原理是通过Adapter来将数据集与视图进行绑定。当需要显示不同的item时,我们需要创建一个继承自RecyclerView.Adapter的自定义适配器。在这...

    Android-RecyclerView优雅的实现多条目布局

    本篇文章将深入探讨如何优雅地在RecyclerView中实现多条目布局,使得UI设计更加灵活多样。 首先,了解RecyclerView的基础架构。RecyclerView由LayoutManager、Adapter和ViewHolder三部分组成。LayoutManager负责...

    MarkTableView

    这个组件的核心特点包括多行多列的布局、复选框(checkBox)功能、自定义行列尺寸以及下拉刷新和上拉加载功能。 1. **多行多列**:在标准的UITableView中,通常每一行只显示一个cell,而MarkTableView支持在一个...

    Android编程实现多列显示的下拉列表框Spinner功能示例

    这种方式的好处在于可以自定义视图布局,以满足多列显示的需求。在实现过程中,主要涉及以下步骤: 1. 创建一个LinearLayout布局作为基础视图。这可以通过LayoutInflater从XML布局文件中加载。在本例中,布局文件为...

    自定义多列表格

    本案例“自定义多列表格”通过开源项目ASFTableView,提供了一种实现多列、带标题行且支持多行内容显示的表格视图。下面将详细阐述ASFTableView的核心特点和实现原理。 ASFTableView是一个基于Swift或Objective-C...

    winform datagridview 实现不同行相同列的合并

    `DataGridView`控件基于.NET Framework中的`System.Windows.Forms.DataGridView`类,它是一个自定义的表格视图,可以通过编程或设计时配置来显示数据源中的数据。默认情况下,它按照单元格(Cell)的方式呈现数据,...

    Oracle多行记录合并

    例如,如果你有多个视图或表,每个都有一部分数据,可以使用这些操作将它们组合在一起。 3. **`CONNECT BY` 和 `PRIOR`:** 这是一种更复杂的方法,通常用于构建层次结构数据,但也可以用于特定情况下的多行合并。...

    WPF多表头技术的实现,支持多行表头

    标题提到的"支持多行表头"是指在DataGrid的列头区域创建多层标题,每层标题可能跨越一列或多列。这种功能对于清晰地展示多层次的数据关系至关重要。在WPF中,这通常是通过自定义DataGridTemplateColumn或利用...

    ios-表格视图,自定义UICollectionView实现.zip

    在`UITableView`中,单元格通常是单行单列的,而`UICollectionView`可以实现多行多列,甚至非规则布局,如网格、瀑布流等。 瀑布流(Waterfall Flow)布局是一种流行的设计模式,常见于电商应用,其特点是每个...

    Android-MultiColumnsPicker多列选择器支持设置页数设置自定义adapter

    本篇文章将深入探讨`Android-MultiColumnsPicker`,一个支持多列、可定制adapter且能设置页面数的高级选择器。这个库提供了一种灵活的方式来实现横向或纵向布局的多列选择功能,极大地丰富了开发者的设计选项。 `...

    用GridView做棋盘编写的象棋代码

    2. **创建自定义适配器**:继承`BaseAdapter`或`ArrayAdapter`,重写其中的`getCount()`,`getItem()`,`getItemId()`和`getView()`方法,以便为每个棋子位置生成对应的View。 3. **设置GridView**:在XML布局文件...

    微信小程序uniapp日历组件,可以自定义文案,可以上下滑动选择日期

    日历视图通常会以一个月为单位进行展示,包括日期格子、星期列等元素。用户可以通过手势或按钮进行月份切换,上滑代表向前翻月,下滑则向后翻月。 3. **自定义文案**:为了让日历更具个性化,开发者可以为特定日期...

Global site tag (gtag.js) - Google Analytics