Ios 选中时,能否在UITableViewCell上设置高度更改动画?
我在iPhone应用程序中使用了Ios 选中时,能否在UITableViewCell上设置高度更改动画?,ios,cocoa-touch,uitableview,Ios,Cocoa Touch,Uitableview,我在iPhone应用程序中使用了UITableView,我有一个属于某个组的人的列表。我希望这样,当用户单击某个特定的人(从而选择该单元格)时,该单元格的高度会增加,以显示用于编辑该人属性的多个UI控件 这可能吗 获取所选行的索引。重新加载表格。在UITableViewDelegate的heightForRowAtIndexPath方法中,将所选行的高度设置为不同的高度,对于其他行,返回正常行高度。由于没有动画,因此重新加载数据不好 这就是我目前正在尝试的: NSArray* paths = [
UITableView
,我有一个属于某个组的人的列表。我希望这样,当用户单击某个特定的人(从而选择该单元格)时,该单元格的高度会增加,以显示用于编辑该人属性的多个UI控件
这可能吗 获取所选行的索引。重新加载表格。在UITableViewDelegate的heightForRowAtIndexPath方法中,将所选行的高度设置为不同的高度,对于其他行,返回正常行高度。由于没有动画,因此重新加载数据不好 这就是我目前正在尝试的:
NSArray* paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
它几乎可以正常工作。几乎。我在增加单元格的高度,有时在替换单元格时,表格视图中会出现一些“小问题”,好像表格视图中的某些滚动位置被保留了一样,新单元格(表格中的第一个单元格)的偏移量太高,scrollview会反弹以重新定位它。我刚刚通过一些小技巧解决了这个问题:
static int s_CellHeight = 30;
static int s_CellHeightEditing = 60;
- (void)onTimer {
cellHeight++;
[tableView reloadData];
if (cellHeight < s_CellHeightEditing)
heightAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(onTimer) userInfo:nil repeats:NO] retain];
}
- (CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (isInEdit) {
return cellHeight;
}
cellHeight = s_CellHeight;
return s_CellHeight;
}
static int s_CellHeight=30;
静态int s_CellHeightEditing=60;
-(void)onTimer{
cellHeight++;
[tableView重新加载数据];
if(单元高度
当我需要扩展单元格高度时,我设置了
isInEdit=YES
并调用该方法[self-onTimer]
,它会使单元格生长动画化,直到达到s_CellHeightEditing值:-)我找到了一个非常简单的解决方案,作为我正在处理的UITableView
的副作用
将单元格高度存储在一个变量中,该变量通常通过tableView:heightForRowAtIndexPath:
报告原始高度,然后当您想要设置高度更改的动画时,只需更改变量的值并调用此
[tableView beginUpdates];
[tableView endUpdates];
您会发现它没有完全重新加载,但足以让UITableView
知道它必须重新绘制单元格,获取单元格的新高度值。。。。你猜怎么着?它为您设置更改的动画。好极了
我在我的博客上有更详细的解释和完整的代码示例 我喜欢西蒙·李的答案。我实际上没有尝试这种方法,但它看起来会改变列表中所有单元格的大小。我只是希望改变一下被窃听的手机。我有点像西蒙,但有点不同。这将在选定单元格时更改其外观。而且它确实有生气。只是另一种方法 创建一个int以保存当前选定单元格索引的值:
int currentSelection;
然后:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int row = [indexPath row];
selectedNumber = row;
[tableView beginUpdates];
[tableView endUpdates];
}
然后:
我相信您可以在tableView:cellForRowAtIndexPath:中进行类似的更改,以更改单元格的类型,甚至加载单元格的xib文件
这样,currentSelection将从0开始。如果不希望列表的第一个单元格(索引0处)在默认情况下看起来是选中的,则需要进行调整。添加一个属性以跟踪选中的单元格
@property (nonatomic) int currentSelection;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
int rowHeight;
if ([indexPath row] == self.currentSelection) {
rowHeight = self.newCellHeight;
} else rowHeight = 57.0f;
return rowHeight;
}
将其设置为(例如)viewDidLoad
中的sentinel值,以确保UITableView
在“正常”位置启动
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//sentinel
self.currentSelection = -1;
}
在heightforrowatinexpath
中,可以为所选单元格设置所需的高度
@property (nonatomic) int currentSelection;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
int rowHeight;
if ([indexPath row] == self.currentSelection) {
rowHeight = self.newCellHeight;
} else rowHeight = 57.0f;
return rowHeight;
}
在didselectrowatinexpath
中,保存当前选择并保存动态高度(如果需要)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// do things with your cell here
// set selection
self.currentSelection = indexPath.row;
// save height for full text label
self.newCellHeight = cell.titleLbl.frame.size.height + cell.descriptionLbl.frame.size.height + 10;
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
}
在didDeceloseRowatineXpath
中,将选择索引设置回sentinel值,并将单元格动画设置回正常形式
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
// do things with your cell here
// sentinel
self.currentSelection = -1;
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
}
我不知道连续调用BeginUpdate/endUpdates的所有内容是什么,您可以使用
-[UITableView reloadRowsAtIndexPaths:withAnimation:
试试这是用来展开索引行的:
@property (nonatomic) NSIndexPath *expandIndexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
if ([indexPath isEqual:self.expandedIndexPath])
return 100;
return 44;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *modifiedRows = [NSMutableArray array];
if ([indexPath isEqual:self.expandIndexPath]) {
[modifiedRows addObject:self.expandIndexPath];
self.expandIndexPath = nil;
} else {
if (self.expandedIndexPath)
[modifiedRows addObject:self.expandIndexPath];
self.expandIndexPath = indexPath;
[modifiedRows addObject:indexPath];
}
// This will animate updating the row sizes
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];
// Preserve the deselection animation (if desired)
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ViewControllerCellReuseIdentifier];
cell.textLabel.text = [NSString stringWithFormat:@"I'm cell %ld:%ld", (long)indexPath.section, (long)indexPath.row];
return cell;
}
我用
重新加载rowsatindexpaths
解决了这个问题
我在didSelectRowAtIndexPath
中保存所选单元格的indexath,并在最后调用reloadRowsAtIndexPaths
(您可以发送NSMutableArray以获取要重新加载的元素列表)
在heightforrowatinexpath
中,您可以检查indexath是否在expandindexath单元格和send height的列表中
您可以检查以下基本示例:
这是一个简单的解决方案
如果有帮助,我会添加一种代码
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath
{
if ([indexPath isEqual:_expandIndexPath])
return 80;
return 40;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Celda";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[cell.textLabel setText:@"wopwop"];
return cell;
}
#pragma mark -
#pragma mark Tableview Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *modifiedRows = [NSMutableArray array];
// Deselect cell
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
_expandIndexPath = indexPath;
[modifiedRows addObject:indexPath];
// This will animate updating the row sizes
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
只是一个像我这样的人在自定义单元格上搜索添加“更多细节”的便条
[tableView beginUpdates];
[tableView endUpdates];
做了出色的工作,但别忘了“裁剪”单元视图。
从界面生成器中选择单元格->内容视图->从属性检查器中选择“剪辑子视图”这是我的自定义
UITableView
子类的代码,它在表格单元格中展开UITextView
,而无需重新加载(并丢失键盘焦点):
-(无效)textViewDidChange:(UITextView*)textView{
CGFloat textHeight=[textView SIZETATTFITS:CGSizeMake(self.width,MAXFLOAT)].height;
//如果文字高度发生变化,请检查
if(self.previousTextHeight!=textHeight&&self.previousTextHeight>0){
[自我开始更新];
//计算高差
CGFloat差值=文本高度-self.previousTextHeight;
//更新当前编辑单元格的高度
CGRect editingCellFrame=self.editingCell.frame;
editingCellFrame.size.height+=差异;
self.editingCell.frame=editingCellFrame;
//更新UITableView内容大小
self.contentSize=CGSizeMake(self.contentSize.width、self.contentSize.height+差值);
//如果单元格位于表格末尾,请滚动至底部
如果
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//This is the bit I changed, so that if tapped once on the cell,
//cell is expanded. If tapped again on the same cell,
//cell is collapsed.
if (self.currentSelection==indexPath.row) {
self.currentSelection = -1;
}else{
self.currentSelection = indexPath.row;
}
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
// MARK: - Variables
var isCcBccSelected = false // To toggle Bcc.
// MARK: UITableViewDelegate
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
// Hide the Bcc Text Field , until CC gets focused in didSelectRowAtIndexPath()
if self.cellTypes[indexPath.row] == CellType.Bcc {
if (isCcBccSelected) {
return 44
} else {
return 0
}
}
return 44.0
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
// To Get the Focus of CC, so that we can expand Bcc
if self.cellTypes[indexPath.row] == CellType.Cc {
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? RecipientTableViewCell {
if cell.tag == 1 {
cell.recipientTypeLabel.text = "Cc:"
cell.recipientTextField.userInteractionEnabled = true
cell.recipientTextField.becomeFirstResponder()
isCcBccSelected = true
tableView.beginUpdates()
tableView.endUpdates()
}
}
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[UIView animateWithDuration:.6
delay:0
usingSpringWithDamping:UIViewAnimationOptionBeginFromCurrentState
initialSpringVelocity:0
options:UIViewAnimationOptionBeginFromCurrentState animations:^{
cellindex = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
[violatedTableView beginUpdates];
[violatedTableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationAutomatic];
[violatedTableView endUpdates];
}
completion:^(BOOL finished) {
}];
}
BOOL flag;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
flag = !flag;
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES == flag ? 20 : 40;
}
var cellIsSelected: IndexPath?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
cellIsSelected = cellIsSelected == indexPath ? nil : indexPath
tableView.beginUpdates()
tableView.endUpdates()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if cellIsSelected == indexPath {
return 250
}
return 65
}
tableView.beginUpdates()
tableView.endUpdates()
tableView.performBatchUpdates(nil, completion: nil)
tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()