UITableView 多个部分,带有 GUI 元素 UIButton、UISwitch 等
Posted
技术标签:
【中文标题】UITableView 多个部分,带有 GUI 元素 UIButton、UISwitch 等【英文标题】:UITableView multiple sections with GUI Elements UIButton, UISwitch, etc 【发布时间】:2011-10-25 20:52:43 【问题描述】:我已经在这个问题上绞尽脑汁了一天左右...我已经搜索了这个论坛以及谷歌和其他博客等。都无济于事。
我正在做的是创建一个包含多个部分的UITableView
,并且在每个部分中,每一行都有不同的 GUI 元素(即设置屏幕)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return 3;
我想要实现的只是每个部分在不同的单元格中都有不同的 GUI 元素。但是正如您在此屏幕截图中看到的那样:
最初一切都按原样显示,但在向上和向下滚动一次后,问题就开始了。元素开始四处移动,向上和向下滚动的次数越多/时间越长,元素移动的次数就越多。
!["UITableView 在部分和行中带有 GUI 元素。错误?故障?无知?"][2]
这是一个错误吗?毛刺?还是无知? (可能是后者)-我已经删除了除 GUI 代码之外的所有其他代码,如果它意味着任何我正在使用 NIB 创建UITableView
另外,这是我的cellForRowAtIndexPath
方法的代码。如果有人能指出我正确的方向或告诉我我做错了什么,我将永远感激不尽。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
// Set up the cell
// desired section
if(indexPath.section == 0)
//
// Load Settings
//
// button
UIButton * loadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
loadButton.frame = CGRectMake(0.0, 0.0, 300.0, 44.0);
[loadButton setTitle:@"Load Image" forState:UIControlStateNormal];
[loadButton setTitle:@"Load Image" forState:UIControlStateSelected];
[loadButton addTarget:self action:@selector(loadImage:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:loadButton];
else if(indexPath.section == 1)
//
// Mode Settings
//
if(indexPath.row == 0)
cell.text = [mode objectAtIndex:indexPath.row];
else if(indexPath.row == 1)
cell.text = [mode objectAtIndex:indexPath.row];
else if(indexPath.section == 2)
//
// Marker Settings
//
if(indexPath.row == 0)
// description text
cell.text = [marker objectAtIndex:indexPath.row];
// switch
UISwitch *markerSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = markerSwitch;
[markerSwitch setOn:YES animated:NO];
[markerSwitch addTarget:self action:@selector(markerToggle:) forControlEvents:UIControlEventValueChanged];
[markerSwitch release];
else if(indexPath.row == 1)
UISlider *markerGridSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
cell.accessoryView = markerGridSlider;
markerGridSlider.minimumValueImage = [UIImage imageNamed:@"size_icon_1x1.png"];
markerGridSlider.maximumValueImage = [UIImage imageNamed:@"size_icon_8x8.png"];
[markerGridSlider setMinimumValue:1.0];
[markerGridSlider setMaximumValue:8.0];
markerGridSlider.value = 8.0;
[markerGridSlider addTarget:self action:@selector(markerGrid:) forControlEvents:UIControlEventValueChanged];
[markerGridSlider release];
else if(indexPath.row == 2)
UISlider *markerSpacingSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
cell.accessoryView = markerSpacingSlider;
markerSpacingSlider.minimumValueImage = [UIImage imageNamed:@"spacing_icon_min.png"];
markerSpacingSlider.maximumValueImage = [UIImage imageNamed:@"spacing_icon_max.png"];
[markerSpacingSlider setMinimumValue:1.0];
[markerSpacingSlider setMaximumValue:(320.0/8.0)];
markerSpacingSlider.value = 1.0;
[markerSpacingSlider addTarget:self action:@selector(markerSpacing:) forControlEvents:UIControlEventValueChanged];
[markerSpacingSlider release];
return cell;
谢谢。
肯
非常感谢您的帮助。
也许我不明白你的意思,但我认为我已经正确地实施了你的建议。但是我仍然得到元素交换位置的故障,尽管现在经过大约 5 次以上的向上和向下滑动并且我的 UISwitch 现在被放置在左上角。
这是我更新的代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if([indexPath section] == 0)
//
// Load Settings
//
// button
UIButton *loadButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] autorelease];
loadButton.frame = CGRectMake(0.0, 0.0, 300.0, 44.0);
[loadButton addTarget:self action:@selector(loadImage:) forControlEvents:UIControlEventTouchUpInside];
[loadButton setTag:1000];
[cell.contentView addSubview:loadButton];
if([indexPath section] == 1)
//
// Mode Settings
//
if([indexPath row] == 0)
cell.text = [mode objectAtIndex:[indexPath row]];
if([indexPath row] == 1)
cell.text = [mode objectAtIndex:[indexPath row]];
if([indexPath section] == 2)
//
// Marker Settings
//
if([indexPath row] == 0)
// switch
UISwitch *markerSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[markerSwitch setOn:YES animated:NO];
[markerSwitch addTarget:self action:@selector(markerToggle:) forControlEvents:UIControlEventValueChanged];
[markerSwitch setTag:3000];
[cell.contentView addSubview:markerSwitch];
[markerSwitch release];
if([indexPath row] == 1)
// slider
UISlider *markerGridSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
markerGridSlider.minimumValueImage = [UIImage imageNamed:@"size_icon_1x1.png"];
markerGridSlider.maximumValueImage = [UIImage imageNamed:@"size_icon_8x8.png"];
[markerGridSlider setMinimumValue:1.0];
[markerGridSlider setMaximumValue:8.0];
[markerGridSlider setValue:8.0];
[markerGridSlider addTarget:self action:@selector(markerGrid:) forControlEvents:UIControlEventValueChanged];
[markerGridSlider setTag:3100];
[cell.contentView addSubview:markerGridSlider];
[markerGridSlider release];
if([indexPath row] == 2)
// slider
UISlider *markerSpacingSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
markerSpacingSlider.minimumValueImage = [UIImage imageNamed:@"spacing_icon_min.png"];
markerSpacingSlider.maximumValueImage = [UIImage imageNamed:@"spacing_icon_max.png"];
[markerSpacingSlider setMinimumValue:1.0];
[markerSpacingSlider setMaximumValue:(320.0/8.0)];
[markerSpacingSlider setValue:1.0];
[markerSpacingSlider addTarget:self action:@selector(markerSpacing:) forControlEvents:UIControlEventValueChanged];
[markerSpacingSlider setTag:3200];
[cell.contentView addSubview:markerSpacingSlider];
[markerSpacingSlider release];
// end cell == nil
// Load
UIButton *loadButton = (UIButton*)[cell.contentView viewWithTag:1000];
[loadButton setTitle:@"Load Image" forState:UIControlStateNormal];
[loadButton setTitle:@"Load Image" forState:UIControlStateSelected];
// Mode
// Marker
UISwitch *markerSwitch = (UISwitch*)[cell.contentView viewWithTag:3000];
UISlider *markerGridSlider = (UISlider*)[cell.contentView viewWithTag:3100];
UISlider *markerSpacingSlider = (UISlider*)[cell.contentView viewWithTag:3200];
return cell;
【问题讨论】:
【参考方案1】:ios 中绑定到 UITable 的所有单元格都是可重用。 这就是为什么您首先使用函数调用“dequeueReusableCellWithIdentifier”获取单元格的原因,该单元格可能不是零,指向之前加载的单元格。在您的情况下,即使单元格不为零,您也可以向其中添加子视图。当您上下滚动时,这将无限次发生。
这是一个小例子:
-(int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
return 2;
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString* CellIdentifier = @"Cell";
const NSInteger lblTag = 101;
const NSInteger btnTag = 102;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//First init the cells
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//Initialize subviews of cells only in this block.
if (indexPath.row == 0)
//Only the first cell on the top has a UILabel
UILabel *lbl = [[[UILabel alloc] initWithFrame:CGRectMake(5, 5, 100, 20)] autorelease];
lbl.tag = lblTag;
[cell.contentView addSubview:lbl];
else if (indexPath.row == 1)
//Only the 2nd cell has a UIButton
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(5, 5, 60, 20);
btn.tag = btnTag;
[cell.contentView addSubview:btn];
//Modify your cells here
if (indexPath.row == 0)
//Only the first cell on the top has a UILabel
UILabel *lbl = (UILabel*)[cell.contentView viewWithTag:lblTag];
//Do stuff with our label
lbl.text = [NSString stringWithFormat:@"%d",indexPath.row];
else if (indexPath.row == 1)
//Only the 2nd cell has a UIButton
UIButton *btn = (UIButton*)[cell.contentView viewWithTag:btnTag];
//Do stuff with our button
[btn setTitle:[NSString stringWithFormat:@"%d",indexPath.row] forState:UIControlStateNormal];
return cell;
在您的非常特定情况下,您会这样写-
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
if (section == 0)
return 1;
else if (section == 1)
return 2;
else if (section == 2)
return 3;
else
return 0;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
const NSInteger
sec0BtnTag = 101,
markerSwitchTag = 102,
markerGridSliderTag = 103,
markerSpacingSliderTag = 104;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if([indexPath section] == 0)
//
// Load Settings
//
// button
UIButton *loadButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] autorelease];
loadButton.frame = CGRectMake(0.0, 0.0, 300.0, 44.0);
[loadButton addTarget:self action:@selector(loadImage:) forControlEvents:UIControlEventTouchUpInside];
[loadButton setTag:sec0BtnTag];
[cell.contentView addSubview:loadButton];
else if([indexPath section] == 2)
//
// Marker Settings
//
if([indexPath row] == 0)
// switch
UISwitch *markerSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[markerSwitch setOn:YES animated:NO];
[markerSwitch addTarget:self action:@selector(markerToggle:) forControlEvents:UIControlEventValueChanged];
[markerSwitch setTag:markerSwitchTag];
[cell.contentView addSubview:markerSwitch];
[markerSwitch release];
else if([indexPath row] == 1)
// slider
UISlider *markerGridSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
markerGridSlider.minimumValueImage = [UIImage imageNamed:@"size_icon_1x1.png"];
markerGridSlider.maximumValueImage = [UIImage imageNamed:@"size_icon_8x8.png"];
[markerGridSlider setMinimumValue:1.0];
[markerGridSlider setMaximumValue:8.0];
[markerGridSlider setValue:8.0];
[markerGridSlider addTarget:self action:@selector(markerGrid:) forControlEvents:UIControlEventValueChanged];
[markerGridSlider setTag:markerGridSliderTag];
[cell.contentView addSubview:markerGridSlider];
[markerGridSlider release];
else if([indexPath row] == 2)
// slider
UISlider *markerSpacingSlider = [[UISlider alloc] initWithFrame:CGRectMake(0.0, 10.0, 284, 10.0)];
markerSpacingSlider.minimumValueImage = [UIImage imageNamed:@"spacing_icon_min.png"];
markerSpacingSlider.maximumValueImage = [UIImage imageNamed:@"spacing_icon_max.png"];
[markerSpacingSlider setMinimumValue:1.0];
[markerSpacingSlider setMaximumValue:(320.0/8.0)];
[markerSpacingSlider setValue:1.0];
[markerSpacingSlider addTarget:self action:@selector(markerSpacing:) forControlEvents:UIControlEventValueChanged];
[markerSpacingSlider setTag:markerSpacingSliderTag];
[cell.contentView addSubview:markerSpacingSlider];
[markerSpacingSlider release];
// end cell == nil
//Load specific cell row values
if([indexPath section] == 0)
//
// Load Settings
//
// button
UIButton *loadButton = (UIButton*)[cell.contentView viewWithTag:sec0BtnTag];
[loadButton setTitle:@"Load Image" forState:UIControlStateNormal];
[loadButton setTitle:@"Load Image" forState:UIControlStateSelected];
//do other stuff with the button here according to the specific row & section
if([indexPath section] == 1)
//
// Mode Settings
//
if([indexPath row] == 0)
cell.text = [mode objectAtIndex:[indexPath row]];
if([indexPath row] == 1)
cell.text = [mode objectAtIndex:[indexPath row]];
if([indexPath section] == 2)
//
// Marker Settings
//
if([indexPath row] == 0)
// switch
UISwitch *markerSwitch = (UISwitch*)[cell.contentView viewWithTag:markerSwitchTag];
//do stuff with the switch here according to the specific row & section
if([indexPath row] == 1)
// slider
UISlider *markerGridSlider = (UISlider*)[cell.contentView viewWithTag:markerGridSliderTag];
//do stuff with the slider here according to the specific row & section
if([indexPath row] == 2)
// slider
UISlider *markerSpacingSlider = (UISlider*)[cell.contentView viewWithTag:markerSpacingSliderTag];
//do stuff with the slider here according to the specific row & section
return cell;
【讨论】:
好的。我可能不完全理解你的意思。虽然我认为我已经实施了你的建议。大约需要 5 次以上的 UP 和 DOWN 才能恢复故障,但它仍然存在。 修改了我的答案。请参阅包含的示例。【参考方案2】:为每个部分更改 static NSString *CellIdentifier = @"Cell";,例如:
NSString *CellIdentifier; if(indexPath.section==0) CellIdentifier= @"Cell"; elseif(indexPath.section==2) CellIdentifier=@"Cell2";
【讨论】:
以上是关于UITableView 多个部分,带有 GUI 元素 UIButton、UISwitch 等的主要内容,如果未能解决你的问题,请参考以下文章
带有 NSFetchedResultsController 的 UITableView 为没有对象的部分保留标题
UIScrollview有一个大视图,还是带有多个视图的UITableview?
无论如何创建一个带有一个通用页脚的 UITableView 吗?