iOS 7-如何在表格视图中显示日期选择器?


121

在WWDC 2013视频中,Apple建议在iOS 7的表格视图中就位显示选择器。如何在表格视图单元格之间插入视图并为其设置动画?

像这样,通过Apple日历应用程序:

就地日期选择器


这是哪个WWDC视频?我试图了解为什么这是特定于iOS7的,以及是否有原因无法在早期版本中做到这一点。
Clafou 2014年

4
找到了它,它是“ iOS用户界面设计的新增功能”(感谢ASCIIwwdc)。理由是旧样式看起来不是内联的,而新样式看起来确实是内联的。
Clafou 2014年

Answers:


102

在iOS7中,Apple发布了示例代码DateCell

在此处输入图片说明

演示表格单元格中日期对象的格式化显示以及如何使用UIDatePicker编辑这些值。作为此表的委托,该示例使用方法“ didSelectRowAtIndexPath”打开UIDatePicker控件。

对于iOS 6.x和更早版本,UIViewAnimation用于在屏幕上和屏幕外上下滑动UIDatePicker。对于iOS 7.x,将UIDatePicker内联添加到表格视图中。

UIDatePicker的操作方法将直接设置自定义表单元格的NSDate属性。此外,此示例演示如何使用NSDateFormatter类来实现自定义单元格的日期格式外观。

在此处输入图片说明

您可以在此处下载示例代码:DateCell


苹果的代码有问题。看看你是否想让你的静态的tableView我的回答如下
亚伦Bratcher

1
@AaronBratcher我只是在我的答案中引入了Datecell,而您从没想到会得到想要的确切代码。您必须根据需要进行修改和更改。您的解决方案也不错,但请记住,您永远无法从所需的其他代码中获得确切的结果。
Nitin Gohel 2013年

3
最可怕的示例代码。他们可以对何时创建代码完成的方法一些建议做
Anirudha Agashe

2
哇,Apple代码很棒。。。可以说,重点放在表格视图效果上。我希望在这个示例项目中不会有人从他们的代码中得到启发:s
Daniel

84

您可以使用下面我以前给出的答案或使用斯威夫特我这个新类做,使这个任务很多简单和清晰:https://github.com/AaronBratcher/TableViewHelper


我发现Apple提供的代码在两种方面存在问题:

  • 您不能拥有静态tableView,因为它们正在使用tableView:cellForRowAtIndexPath方法
  • 如果最后一个日期选择器单元格下面没有其他行,则代码崩溃

对于静态单元格表​​,我在日期显示单元格下面定义我的日期选择器单元格,并有一个标志来标识是否正在编辑它。如果是,则返回适当的像元高度,否则返回零的像元高度。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0 && indexPath.row == 2) { // this is my picker cell
        if (editingStartTime) {
            return 219;
        } else {
            return 0;
        }
    } else {
        return self.tableView.rowHeight;
    }
}

单击显示日期的行时,我更改了标志并执行了更新动画以显示选择器。

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0 && indexPath.row == 1) { // this is my date cell above the picker cell
        editingStartTime = !editingStartTime;
        [UIView animateWithDuration:.4 animations:^{
            [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:2 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView reloadData];
        }];
    }
}

如果同一表中有多个日期/时间选择器,则在单击时相应地设置标志,然后重新加载适当的行。我发现我可以保留我的静态表,使用更少的代码,并且更容易理解正在发生的事情。


这对我有用,除了UITableView中似乎有一个错误。在我的方法中正确返回了行高,但是实际上它切换了我想要的相反高度。如果我将行重新加载两次,它会起作用。(我没有使用tableView reloadData,因为我不想重新加载整个东西)。另外,动画块不是必需的,它似乎可以自己制作动画。
克里斯·加勒特

是否有人使用该示例创建文本选择器?如果是这样,怎么办?谢谢
TheGeezer

1
您是要显示一行,以便用户可以输入文本而不是选择日期?如果是这样,代码是相同的。只是显示的行的内容不同。
亚伦·布拉彻

22
iOS7.1中存在一个错误,该错误会显示超出单元格范围的对象-例如高度为0且拾取器位于其中的对象。解决方案是获取单元的出口并设置cell.clipsToBounds = YES;
EmilDo

1
@Dunken-上面有投票表决的评论中描述了一种解决方案:stackoverflow.com/questions/18973573/…即使该行的高度为零,默认情况下也不裁剪内容,因此您可以在下一行。
克里斯·诺莱特

18

使用情节提要和静态表格,我可以使用以下代码获得相同的结果。这是一个很好的解决方案,因为如果您有许多形状奇怪的单元格,或者想让多个单元格动态显示/隐藏,那么此代码仍然可以使用。

@interface StaticTableViewController: UITableViewController

@property (weak, nonatomic) IBOutlet UITableViewCell *dateTitleCell; // cell that will open the date picker. This is linked from the story board
@property (nonatomic, assign, getter = isDateOpen) BOOL dateOpen;

@end


@implementation StaticTableViewController

-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    // This is the index path of the date picker cell in the static table
    if (indexPath.section == 1 && indexPath.row == 1 && !self.isDateOpen){
        return 0;
    }
    return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
    [tableView beginUpdates];
    if (cell == self.dateTitleCell){
        self.dateOpen = !self.isDateOpen;
    }
    [tableView reloadData];
    [self.tableView endUpdates];
}

这里还有其他东西吗?单元格的高度没有变化:)
DevC

2
从iOS 7.1开始,您还必须在“属性”检查器中选择“剪辑到SubViews”-这就是我所缺少的:)
DevC 2014年

另外,“ self.dateOpen =!self.isDateOpen;”行 应该在开始时阅读“ self.isDateOpen =“,而不是“ self.dateOpen =”
彼得·约翰逊

2
[tableView reloadData];不需要调用。当前,它会禁用行选择,但是最好取消选择这样的行:[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
Barry Haanstra 2014年

我有怪异的动画效果,例如“打开”之后日期单元格将为空白,但是使用begin和endupdates解决了这一问题。现在很顺利。谢谢datinc!
nh32rg 2015年

5

我已经从Apple取得了DateCell的源,并删除了故事板文件。

如果您想要一个没有情节提要的人,请查看:https : //github.com/ajaygautam/DateCellWithoutStoryboard


谢谢@Ajay,我使用了您修改后的代码,并希望替换UIDatePickerUIPickerView。我尝试了一些事情,并且能够pickerView在每个单元格上显示,但是并没有随每个单元格进行更新。我已经在这里发布了我的问题和代码。请看一下,如果您可以向我建议解决方案,那将非常好。
Mughees Musaddiq 2014年

我看到了您的问题……它的信息太多了,并没有真正解释太多。也许您可以上传代码/将其压缩到某个地方,以便我看看。我可以调试它-如果我可以运行代码...
Ajay Gautam 2014年

谢谢,我设法以某种方式代替UIDatePickerUIPickerView但有一些错误。1.当您打开UIPickerView并滚动表格时,它会崩溃。2. UILabel当将值分配给顶部行的“详细信息”标签时,它将自动将值分配给表底部的“详细信息”。这是我的代码
Mughees Musaddiq 2014年

您能找到testProject吗?
Mughees Musaddiq

抱歉,我有点忙。还需要帮助吗?
Ajay Gautam 2014年

5

关于此的最佳教程之一是iOS 7嵌入式UIDatePicker –第2部分。基本上,这里我使用静态表视图单元格并实现一些其他方法。我为此使用Xamarin和C#:

你必须活跃 Clip Subviews

设置高度:

public override float GetHeightForRow (UITableView tableView, NSIndexPath indexPath)
{
    if (indexPath.Row == 4) {
        return (datePickerIsShowing) ? 206f : 0.0f;
    }

    return base.GetHeightForRow(tableView,indexPath);
}

比一个类变量: private bool datePickerIsShowing = false;

显示日期选择器:

private void showDatePickerCell(){
    datePickerIsShowing = true;
    this.TableView.BeginUpdates ();
    this.TableView.EndUpdates ();
    this.datePicker.Hidden = false;
    this.datePicker.Alpha = 0.0f;

    UIView.Animate (0.25, animation:
        () => {
            this.datePicker.Alpha = 1.0f;
        }
    );
} 

隐藏日期选择器:

private void hideDatePickerCell(){
    datePickerIsShowing = false;
    this.TableView.BeginUpdates ();
    this.TableView.EndUpdates ();

    UIView.Animate (0.25,
        animation: () => {
            this.datePicker.Alpha = 0.0f;
        },
        completion: () => {
            this.datePicker.Hidden = true;
        }
    );
} 

并调用此函数:

public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
    if (indexPath.Row == 3) {
        if (datePickerIsShowing) {
            hideDatePickerCell ();
        } else {
            showDatePickerCell ();
        }
    }

    this.TableView.DeselectRow (indexPath, true);
}

2
如果您不赞成,也许可以解释为什么要不赞成。除了发布网站链接之外,我还提供了一些代码。就我而言,它是C#。不知道这是怎么回事。
测试

3

我制作了自己的自定义视图控制器,以简化在表视图中内联添加内联选择器的过程。您只需对其进行子类化,并遵循一些简单的规则,即可处理日期选择器演示文稿。

您可以在这里找到它以及演示如何使用它的示例项目:https : //github.com/ale84/ALEInlineDatePickerViewController


3

我在苹果的datecell示例中发现了一个缺陷的答案,在该示例中,您必须在最后一个datecell下方一行,否则会出现错误。在CellForRowAtIndexPath方法中,将ItemData行替换为

NSArray *itemsArray = [self.dataArray objectAtIndex:indexPath.section];
NSDictionary *itemData = nil;

if(![indexPath isEqual:self.datePickerIndexPath])
    itemData = [itemsArray objectAtIndex:modelRow];

替换示例代码之后,我现在可以显示显示一个datePicker单元,而其下面没有单元格。

我刚刚加入了stackoverflow,所以如果这是在错误的地方或其他地方,我深表歉意。


3

除了与多个部分一起使用时,Aaron Bratcher的答案都有效。动画有点断断续续,并且没有很好地使下一部分滑落。为了解决这个问题,我遍历了下一组部分,并将行向下转换为与日期选择器高度相同的数量。

我将didSelectRowAtIndexPath编辑为:

// Return Data to delegate: either way is fine, although passing back the object may be more efficient
// [_delegate imageSelected:currentRecord.image withTitle:currentRecord.title withCreator:currentRecord.creator];
// [_delegate animalSelected:currentRecord];
if (indexPath.section == 1 && indexPath.row == 0) { // this is my date cell above the picker cell
    editingStartTime = !editingStartTime;
    [UIView animateWithDuration:.4 animations:^{
        int height = 0;
        if (editingStartTime) {
            height = 162;
        }
        UITableViewCell* temp = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
        [temp setFrame:CGRectMake(temp.frame.origin.x, temp.frame.origin.y, temp.frame.size.width, height)];
        for (int x = 2; x < [tableView numberOfSections]; x++) {
            for (int y = 0; y < [tableView numberOfRowsInSection:x]; y++) {
                UITableViewCell* temp = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:y inSection:x]];
                int y_coord = temp.frame.origin.y-162;
                if (editingStartTime) {
                    y_coord = temp.frame.origin.y+162;
                }
                [temp setFrame:CGRectMake(temp.frame.origin.x, y_coord, temp.frame.size.width, temp.frame.size.height)];
            }
        }
    }completion:^(BOOL finished){
        [self.tableView reloadData];
    }];
}

谢谢@Timmahh,我也发现该节的动画也很不稳定。我在第一个Swift应用程序中成功使用了您的解决方案!我发现cellForRowAtIndexPath返回nil,但单元格不在屏幕上。为了避免这种情况,我添加了一个包含所有单元格的IB出口集合,该集合位于选择器单元格之后,并使用新的y_coord遍历它们。但是,这似乎不太灵活,因为当我添加新单元格时,我必须保持集合的最新状态。
2014年

你是对的。实际上,我已经解决了该问题,但是堆栈溢出不允许我编辑放置在此处的代码。
蒂莫西·洛根

3

除了以前的答案,

我同时尝试了@datinc和@Aaron Bratcher解决方案,两者都很好用,但是动画在分组的静态tableView中不是那么干净。

在玩了一点之后,我得到了这段代码,它对我来说很干净而且很不错-

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0 && indexPath.row == 1)
    {
        if (self.isPickerOpened)
        {
            return 162;
        }
        else
        {
            return 0;
        }
    }
    else
    {
        return [super tableView:tableView heightForRowAtIndexPath:indexPath];
    }
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0 && indexPath.row == 0) {
        [tableView beginUpdates];
        self.isPickerOpened = ! self.isPickerOpened;
        [super tableView:tableView heightForRowAtIndexPath:indexPath];
        [self.tableView endUpdates];
    }
}

主要变化是使用-

        [super tableView:tableView heightForRowAtIndexPath:indexPath];

要更新该行,这样表格的其余部分和单元格不会设置动画。

希望它可以帮助某人。

香妮


这极大地帮助了我们。谢谢!具体来说,与Aaron Bratcher的帖子捆绑在一起的[super tableView]方面为我提供了我在iOS 9.2上需要的结果。再次感谢你!
Terrance Shaw

2

添加到以前的答案和@Aaron Bratcher解决方案...

自从iOS 9起,我就获得了动荡的动画,并且该表格需要花费一些时间来加载,而且足够令人讨厌。我把它的范围缩小到从情节提要中加载日期选择器的速度很慢。以编程方式而不是在情节提要中添加选择器可以改善加载性能,并且作为副产品,动画更流畅。

从情节提要中删除日期选择器,并有一个空单元格,您可以像以前的答案中那样设置高度,然后在viewDidLoad上调用初始化:

- (void)initialiseDatePickers
{
    self.isEditingStartTime = NO;
    self.startTimePickerCell.clipsToBounds = YES;

    UIDatePicker *startTimePicker = [[UIDatePicker alloc] init];
    [startTimePicker addTarget:self action:@selector(startTimePickerChanged:) forControlEvents:UIControlEventValueChanged];
    [self.startTimePickerCell addSubview:startTimePicker];
}

然后执行动作,例如

- (IBAction)startTimePickerChanged:(id)sender
{
    NSLog(@"start time picker changed");
}

这将比以前更快地加载表。您还可以从动画线中删除动画线,didSelectRowAtIndexPath因为动画线没有动画线(ymmv)即可平滑播放。

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0 && indexPath.row == 1) { // this is my date cell above the picker cell
        editingStartTime = !editingStartTime;
    }
}

1

在iOS 8.1中正确使用不带动画的答案。我已经将其转换为下面的Swift:

import UIKit

class TableViewController: UITableViewController {

    var editingCell: Bool = false

    @IBOutlet weak var myCell: UITableViewCell!

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

        // Change the section and row to the title cell the user taps to reveal 
        // the cell below
        if (indexPath.section == 0 && indexPath.row == 2 && !editingCell) {
            return 0
        } else {
            return self.tableView.rowHeight
        }
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        self.tableView.deselectRowAtIndexPath(indexPath, animated: false);

        var cell = tableView.cellForRowAtIndexPath(indexPath)

        self.tableView.beginUpdates()
        if (cell == self.myCell) {
            editingType = !editingType;
        }
        self.tableView.endUpdates()
    }
}

1

这是没有静态常数的情况下解决问题的另一种方法。所有单元格都可以在静态和动态表视图中使用。此方法将单个单元格用于标题和日期选择器!

顺便说一句,您可以在表中随心所欲地选择日期选择器!

创建一个UITableViewCell子类:

您必须从此类继承所有表格视图单元格,并且必须手动为每一行设置单元格高度。

//
//  CPTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

@class CPTableViewCell;

#define kUIAnimationDuration 0.33f

@protocol CPTableViewCellDelegate <NSObject>

@required
- (void)tableViewCellDidChangeValue:(CPTableViewCell *)cell;
@optional
- (void)tableViewCellDidBecomeFirstResponder:(CPTableViewCell *)cell;
- (void)tableViewCellResignedFirstResponder:(CPTableViewCell *)cell;
@end

@interface CPTableViewCell : UITableViewCell

@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet CPTableViewCell *nextCell;
@property (nonatomic, weak) IBOutlet id<CPTableViewCellDelegate> delegate;

@property (nonatomic, copy) IBInspectable NSString *dataBindKey;
@property (nonatomic) IBInspectable CGFloat height;

@property (nonatomic, readonly) BOOL isFirstResponder;
@property (nonatomic) BOOL isEnabled;

- (void)commonInit;

- (id)value;
- (void)setValue:(id)value;

@end

//
//  CPTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPTableViewCell ()
@end

@implementation CPTableViewCell

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (!self)
        return nil;

    [self commonInit];

    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if (!self)
        return nil;

    [self commonInit];

    return self;
}

- (void)commonInit
{
    _isFirstResponder = NO;
    _isEnabled = YES;
}

- (BOOL)canBecomeFirstResponder
{
    return _isEnabled;
}

- (BOOL)becomeFirstResponder
{
    if ([_delegate respondsToSelector:@selector(tableViewCellDidBecomeFirstResponder:)])
        [_delegate tableViewCellDidBecomeFirstResponder:self];

    return _isFirstResponder = YES;
}

- (BOOL)resignFirstResponder
{
    if (_isFirstResponder)
    {
        if ([_delegate respondsToSelector:@selector(tableViewCellResignedFirstResponder:)])
            [_delegate tableViewCellResignedFirstResponder:self];

        _isFirstResponder = NO;
    }

    return _isFirstResponder;
}

- (id)value
{
    [self doesNotRecognizeSelector:_cmd];

    return nil;
}

- (void)setValue:(id)value
{
    [self doesNotRecognizeSelector:_cmd];
}

@end

从我们的CPTableViewCell 创建一个CPDatePickerTableViewCell

//
//  CPDatePickerTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPDatePickerTableViewCell : CPTableViewCell

@property (nonatomic, copy) IBInspectable NSString *dateFormat;

@property (nonatomic, weak) IBOutlet UILabel *titleLabel;
@property (nonatomic, weak) IBOutlet UILabel *dateLabel;

@property (nonatomic, weak) IBOutlet UIDatePicker *datePicker;

@end

//
//  CPDatePickerTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPDatePickerTableViewCell.h"

#define kCPDatePickerTableViewCellPickerHeight 162.f

@interface CPDatePickerTableViewCell () <UITextFieldDelegate, UIPickerViewDelegate>
{
    NSDateFormatter *_dateFormatter;
    BOOL _isOpen;
}
@end

@implementation CPDatePickerTableViewCell

- (void)awakeFromNib
{
    [super awakeFromNib];

    _dateFormatter = [NSDateFormatter new];
    [_dateFormatter setDateFormat:_dateFormat];

    self.selectionStyle = UITableViewCellSelectionStyleNone;

    _dateLabel.text = [_dateFormatter stringFromDate:_datePicker.date];
    _datePicker.alpha = 0.f;
    _isOpen = NO;
}

- (BOOL)becomeFirstResponder
{
    if (_isOpen == NO)
    {
        self.height += kCPDatePickerTableViewCellPickerHeight;
    }
    else
    {
        self.height -= kCPDatePickerTableViewCellPickerHeight;
    }

    [UIView animateWithDuration:kUIAnimationDuration animations:^{
        _datePicker.alpha = _isOpen ? 0.0f : 1.0f;
    }];

    [self.tableView beginUpdates];
    [self.tableView endUpdates];

    _isOpen = !_isOpen;

    [self.tableView endEditing:YES];

    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{
    if (_isOpen == YES)
    {
        self.height -= kCPDatePickerTableViewCellPickerHeight;

        [UIView animateWithDuration:kUIAnimationDuration animations:^{
            _datePicker.alpha = 0.0f;
        }];

        [self.tableView beginUpdates];
        [self.tableView endUpdates];

        _isOpen = NO;
    }

    return [super resignFirstResponder];
}

- (id)value
{
    return _datePicker.date;
}

- (void)setValue:(NSDate *)value
{
    _datePicker.date = value;
    _dateLabel.text = [_dateFormatter stringFromDate:_datePicker.date];
}

- (IBAction)datePickerValueChanged:(UIDatePicker *)sender
{
    [_dateLabel setText:[_dateFormatter stringFromDate:_datePicker.date]];

    [self.delegate tableViewCellDidChangeValue:self];
}

@end

在您的视图控制器中实现这两个委托方法

#pragma mark - UITableViewDelegate methods

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CPTableViewCell *cell = (CPTableViewCell *)[super tableView:tableView cellForRowAtIndexPath:indexPath];

    return [cell height];
}

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    CPTableViewCell *cell = (CPTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];

    if ([cell canBecomeFirstResponder])
    {
        [cell becomeFirstResponder];
    }

    if (cell != _selectedCell)
    {
        [_selectedCell resignFirstResponder];
    }

    _selectedCell = cell;

    return YES;
}

示例如何在“接口”构建器中设置约束

界面构建器

另外,我为UITextFieldUITextView编写了自定义单元格类,其中tableView:didSelectRowAtIndexPath:选择单元格时会调用

CPTextFieldTableViewCell

//
//  CPTextFieldTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPTextFieldTableViewCell : CPTableViewCell

@property (nonatomic, weak) IBOutlet UITextField *inputTextField;

@end

//
//  CPTextFieldTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTextFieldTableViewCell.h"

@interface CPTextFieldTableViewCell () <UITextFieldDelegate>
@end

@implementation CPTextFieldTableViewCell

- (void)awakeFromNib
{
    [super awakeFromNib];

    self.selectionStyle = UITableViewCellSelectionStyleNone;

    _inputTextField.userInteractionEnabled = NO;
    _inputTextField.delegate = self;
}

- (BOOL)becomeFirstResponder
{
    _inputTextField.userInteractionEnabled = YES;

    [_inputTextField becomeFirstResponder];

    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{
    _inputTextField.userInteractionEnabled = NO;

    return [super resignFirstResponder];
}

- (void)setIsEnabled:(BOOL)isEnabled
{
    [super setIsEnabled:isEnabled];

    _inputTextField.enabled = isEnabled;
}

- (id)value
{
    return _inputTextField.text;
}

- (void)setValue:(NSString *)value
{
    _inputTextField.text = value;
}

#pragma mark - UITextFieldDelegate methods

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self.delegate tableViewCellDidChangeValue:self];
}

@end

CBTextViewTableViewCell

单元格高度是动态的,当文本换行时,行会增加!

//
//  CBTextViewTableViewCell.h
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTableViewCell.h"

@interface CPTextViewTableViewCell : CPTableViewCell

@property (nonatomic, weak) IBOutlet UITextView *inputTextView;

@end

//
//  CBTextViewTableViewCell.m
//
//  Copyright (c) CodePigeon. All rights reserved.
//

#import "CPTextViewTableViewCell.h"

@interface CPTextViewTableViewCell () <UITextViewDelegate>
{
    UITextView *_heightTextView;
}

@end

@implementation CPTextViewTableViewCell

@synthesize height = _height;

- (void)awakeFromNib
{
    [super awakeFromNib];

    self.selectionStyle = UITableViewCellSelectionStyleNone;

    _inputTextView.userInteractionEnabled = NO;
    _inputTextView.delegate = self;
    _inputTextView.contentInset = UIEdgeInsetsZero;
    _inputTextView.scrollEnabled = NO;
}

- (CGFloat)height
{
    if (!_heightTextView)
    {
        CGRect frame = (CGRect) {
            .origin = CGPointMake(0.f, 0.f),
            .size = CGSizeMake(_inputTextView.textInputView.frame.size.width, 0.f)
        };

        _heightTextView = [[UITextView alloc] initWithFrame:frame];
        _heightTextView.font = [UIFont systemFontOfSize:_inputTextView.font.pointSize];
        _heightTextView.textColor = UIColor.whiteColor;
        _heightTextView.contentInset = UIEdgeInsetsZero;
    }

    _heightTextView.text = _inputTextView.text;

    CGSize size = [_heightTextView sizeThatFits:CGSizeMake(_inputTextView.textInputView.frame.size.width, FLT_MAX)];

    return size.height > _height ? size.height + _inputTextView.font.pointSize : _height;
}

- (BOOL)becomeFirstResponder
{
    _inputTextView.userInteractionEnabled = YES;

    [_inputTextView becomeFirstResponder];

    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{
    _inputTextView.userInteractionEnabled = NO;

    return [super resignFirstResponder];
}

- (void)setIsEnabled:(BOOL)isEnabled
{
    [super setIsEnabled:isEnabled];

    _inputTextView.editable = isEnabled;
}

- (id)value
{
    return _inputTextView.text;
}

- (void)setValue:(NSString *)value
{
    _inputTextView.text = value;

    [_inputTextView setNeedsLayout];
    [_inputTextView layoutIfNeeded];
}

#pragma mark - UITextViewDelegate methods

- (void)textViewDidChange:(UITextView *)textView
{
    [self.delegate tableViewCellDidChangeValue:self];

    [self.tableView beginUpdates];
    [self.tableView endUpdates];
}

@end

0

在Swift版本中使用DateCell的最简单方法:使用以下示例

  1. 打开此示例并进行测试(使Xcode转换为Swift 2)
  2. 将“ DateCellTableViewController.swift ”类拖到您的项目中。

  3. 打开“ Main.storyboard”,然后复制“ DateCell ” ViewController对象,并将其粘贴到情节提要中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.