ios 在 UITableViewCell 中有一个 UITextField

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/409259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:29:11  来源:igfitidea点击:

Having a UITextField in a UITableViewCell

iosobjective-cuitableviewcocoa-touchuitextfield

提问by Mathieu

I'm trying to do that for a couple of days now, and after reading tons of messages of people trying to do that too, I'm still unable to have a fully working UITextFieldin some of my UITableViewCells, just like in this example:

我试图做了两天的现在,和阅读吨的人试图做到这一点的消息后,我仍然无法有一个完全工作UITextField在一些我的UITableViewCells,就像这个例子:

Screenshot

截屏

Either I have the form working but the text is not visible (although I set its color to blue), the keyboard goes on the field when I click on it and I haven't been able to correctly implement the keyboard events. I tried with a bunch of examples from Apple (mainly UICatalog, where there is a kinda similar control) but it's still not working correctly.

要么我有表单工作但文本不可见(尽管我将其颜色设置为蓝色),当我点击它时键盘会进入该字段并且我无法正确实现键盘事件。我尝试了一堆来自 Apple 的例子(主要是UICatalog,那里有一个类似的控件),但它仍然无法正常工作。

Can somebody help me (and all the people trying to realize this control) and post a simple implementation of a UITextFieldin a UITableViewCell, that works fine?

有人可以帮助我(以及所有试图实现此控件的人)并发布一个简单的 a UITextFieldin a实现UITableViewCell吗?

回答by leviathan

Try this out. Works like a charm for me (on iPhone devices). I used this code for a login screen once. I configured the table view to have two sections. You can of course get rid of the section conditionals.

试试这个。对我来说就像一个魅力(在 iPhone 设备上)。我曾经将此代码用于登录屏幕。我将表格视图配置为有两个部分。您当然可以摆脱部分条件。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                   reuseIdentifier:kCellIdentifier] autorelease];
    cell.accessoryType = UITableViewCellAccessoryNone;

    if ([indexPath section] == 0) {
        UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
        playerTextField.adjustsFontSizeToFitWidth = YES;
        playerTextField.textColor = [UIColor blackColor];
        if ([indexPath row] == 0) {
            playerTextField.placeholder = @"[email protected]";
            playerTextField.keyboardType = UIKeyboardTypeEmailAddress;
            playerTextField.returnKeyType = UIReturnKeyNext;
        }
        else {
            playerTextField.placeholder = @"Required";
            playerTextField.keyboardType = UIKeyboardTypeDefault;
            playerTextField.returnKeyType = UIReturnKeyDone;
            playerTextField.secureTextEntry = YES;
        }       
        playerTextField.backgroundColor = [UIColor whiteColor];
        playerTextField.autocorrectionType = UITextAutocorrectionTypeNo; // no auto correction support
        playerTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; // no auto capitalization support
        playerTextField.textAlignment = UITextAlignmentLeft;
        playerTextField.tag = 0;
        //playerTextField.delegate = self;

        playerTextField.clearButtonMode = UITextFieldViewModeNever; // no clear 'x' button to the right
        [playerTextField setEnabled: YES];

        [cell.contentView addSubview:playerTextField];

        [playerTextField release];
    }
}
if ([indexPath section] == 0) { // Email & Password Section
    if ([indexPath row] == 0) { // Email
        cell.textLabel.text = @"Email";
    }
    else {
        cell.textLabel.text = @"Password";
    }
}
else { // Login button section
    cell.textLabel.text = @"Log in";
}
return cell;    
}

Result looks like this:

结果如下所示:

login form

登录表格

回答by William Entriken

Here is a solution that looks good under iOS6/7/8/9.

这是一个在 iOS6/7/8/9 下看起来不错的解决方案

Update 2016-06-10: this still works with iOS 9.3.3

2016 年 6 月 10 日更新:这仍然适用于 iOS 9.3.3

Thanks for all your support, this is now on CocoaPods/Carthage/SPM at https://github.com/fulldecent/FDTextFieldTableViewCell

感谢您的支持,现在在 CocoaPods/Carthage/SPM 上https://github.com/fulldecent/FDTextFieldTableViewCell

Basically we take the stock UITableViewCellStyleValue1and staple a UITextFieldwhere the detailTextLabelis supposed to be. This gives us automatic placement for all scenarios: iOS6/7/8/9, iPhone/iPad, Image/No-image, Accessory/No-accessory, Portrait/Landscape, 1x/2x/3x.

基本上,我们把库存UITableViewCellStyleValue1和订书钉UITextField放在detailTextLabel应该在的地方。这为我们提供了所有场景的自动放置:iOS6/7/8/9、iPhone/iPad、图像/无图像、附件/无附件、纵向/横向、1x/2x/3x。

enter image description here

在此处输入图片说明

Note: this is using storyboard with a UITableViewCellStyleValue1type cell named "word".

注意:这是使用带有UITableViewCellStyleValue1名为“word”的类型单元格的故事板。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    cell = [tableView dequeueReusableCellWithIdentifier:@"word"];
    cell.detailTextLabel.hidden = YES;
    [[cell viewWithTag:3] removeFromSuperview];
    textField = [[UITextField alloc] init];
    textField.tag = 3;
    textField.translatesAutoresizingMaskIntoConstraints = NO;
    [cell.contentView addSubview:textField];
    [cell addConstraint:[NSLayoutConstraint constraintWithItem:textField attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:cell.textLabel attribute:NSLayoutAttributeTrailing multiplier:1 constant:8]];
    [cell addConstraint:[NSLayoutConstraint constraintWithItem:textField attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:8]];
    [cell addConstraint:[NSLayoutConstraint constraintWithItem:textField attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeBottom multiplier:1 constant:-8]];
    [cell addConstraint:[NSLayoutConstraint constraintWithItem:textField attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:cell.detailTextLabel attribute:NSLayoutAttributeTrailing multiplier:1 constant:0]];
    textField.textAlignment = NSTextAlignmentRight;
    textField.delegate = self;
    return cell;
}

回答by charlax

Here is how I have achieved this:

以下是我如何实现这一目标:

TextFormCell.h

文本表格单元格.h

#import <UIKit/UIKit.h>

#define CellTextFieldWidth 90.0
#define MarginBetweenControls 20.0

@interface TextFormCell : UITableViewCell {
 UITextField *textField;
}

@property (nonatomic, retain) UITextField *textField;

@end

TextFormCell.m

TextFormCell.m

#import "TextFormCell.h"

@implementation TextFormCell

@synthesize textField;

- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
  // Adding the text field
  textField = [[UITextField alloc] initWithFrame:CGRectZero];
  textField.clearsOnBeginEditing = NO;
  textField.textAlignment = UITextAlignmentRight;
  textField.returnKeyType = UIReturnKeyDone;
  [self.contentView addSubview:textField];
    }
    return self;
}

- (void)dealloc {
 [textField release];
    [super dealloc];
}

#pragma mark -
#pragma mark Laying out subviews

- (void)layoutSubviews {
 CGRect rect = CGRectMake(self.contentView.bounds.size.width - 5.0, 
        12.0, 
        -CellTextFieldWidth, 
        25.0);
 [textField setFrame:rect];
 CGRect rect2 = CGRectMake(MarginBetweenControls,
       12.0,
         self.contentView.bounds.size.width - CellTextFieldWidth - MarginBetweenControls,
         25.0);
 UILabel *theTextLabel = (UILabel *)[self textLabel];
 [theTextLabel setFrame:rect2];
}

It may seems a bit verbose, but it works!

它可能看起来有点冗长,但它确实有效!

Don't forget to set the delegate!

不要忘记设置委托!

回答by Ali

Try this one. It can handle scrolling as well and you can reuse the cells without the hassle of removing subviews you added before.

试试这个。它也可以处理滚动,您可以重复使用单元格,而无需删除之前添加的子视图。

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section{
    return 10;
}   

- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:@"Cell"];
    if( cell == nil)
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"] autorelease];   

    cell.textLabel.text = [[NSArray arrayWithObjects:@"First",@"Second",@"Third",@"Forth",@"Fifth",@"Sixth",@"Seventh",@"Eighth",@"Nineth",@"Tenth",nil] 
                           objectAtIndex:indexPath.row];

    if (indexPath.row % 2) {
        UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 21)];
        textField.placeholder = @"Enter Text";
        textField.text = [inputTexts objectAtIndex:indexPath.row/2];
        textField.tag = indexPath.row/2;
        textField.delegate = self;
        cell.accessoryView = textField;
        [textField release];
    } else
        cell.accessoryView = nil;

    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    return cell;        
}

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    [inputTexts replaceObjectAtIndex:textField.tag withObject:textField.text];
    return YES;
}

- (void)viewDidLoad {
    inputTexts = [[NSMutableArray alloc] initWithObjects:@"",@"",@"",@"",@"",nil];
    [super viewDidLoad];
}

回答by lostInTransit

This should not be difficult. When creating a cell for your table, add a UITextField object to the cell's content view

这应该不难。为表格创建单元格时,将 UITextField 对象添加到单元格的内容视图

UITextField *txtField = [[UITextField alloc] initWithFrame....]
...
[cell.contentView addSubview:txtField]

Set the delegate of the UITextField as self (ie your viewcontroller) Give a tag to the text field so you can identify which textfield was edited in your delegate methods. The keyboard should pop up when the user taps the text field. I got it working like this. Hope it helps.

将 UITextField 的委托设置为 self(即您的视图控制器) 给文本字段一个标签,以便您可以识别在您的委托方法中编辑了哪个文本字段。当用户点击文本字段时,键盘应该弹出。我让它像这样工作。希望能帮助到你。

回答by Vasily Bodnarchuk

Details

细节

  • Xcode 10.2 (10E125), Swift 5
  • Xcode 10.2 (10E125),Swift 5

Full Sample Code

完整示例代码

TextFieldInTableViewCell

TextFieldInTableViewCell

import UIKit

protocol TextFieldInTableViewCellDelegate: class {
    func textField(editingDidBeginIn cell:TextFieldInTableViewCell)
    func textField(editingChangedInTextField newText: String, in cell: TextFieldInTableViewCell)
}

class TextFieldInTableViewCell: UITableViewCell {

    private(set) weak var textField: UITextField?
    private(set) weak var descriptionLabel: UILabel?

    weak var delegate: TextFieldInTableViewCellDelegate?

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupSubviews()
    }

    private func setupSubviews() {
        let stackView = UIStackView()
        stackView.distribution = .fill
        stackView.alignment = .leading
        stackView.spacing = 8
        contentView.addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.topAnchor.constraint(equalTo: topAnchor, constant: 6).isActive = true
        stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -6).isActive = true
        stackView.leftAnchor.constraint(equalTo: leftAnchor, constant: 16).isActive = true
        stackView.rightAnchor.constraint(equalTo: rightAnchor, constant: -16).isActive = true

        let label = UILabel()
        label.text = "Label"
        stackView.addArrangedSubview(label)
        descriptionLabel = label

        let textField = UITextField()
        textField.textAlignment = .left
        textField.placeholder = "enter text"
        textField.setContentHuggingPriority(.fittingSizeLevel, for: .horizontal)
        stackView.addArrangedSubview(textField)
        textField.addTarget(self, action: #selector(textFieldValueChanged(_:)), for: .editingChanged)
        textField.addTarget(self, action: #selector(editingDidBegin), for: .editingDidBegin)
        self.textField = textField

        stackView.layoutSubviews()
        selectionStyle = .none

        let gesture = UITapGestureRecognizer(target: self, action: #selector(didSelectCell))
        addGestureRecognizer(gesture)
    }

    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
}

extension TextFieldInTableViewCell {
    @objc func didSelectCell() { textField?.becomeFirstResponder() }
    @objc func editingDidBegin() { delegate?.textField(editingDidBeginIn: self) }
    @objc func textFieldValueChanged(_ sender: UITextField) {
        if let text = sender.text { delegate?.textField(editingChangedInTextField: text, in: self) }
    }
}

ViewController

视图控制器

import UIKit

class ViewController: UIViewController {

    private weak var tableView: UITableView?
    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableView()
    }
}

extension ViewController {

    func setupTableView() {

        let tableView = UITableView(frame: .zero)
        tableView.register(TextFieldInTableViewCell.self, forCellReuseIdentifier: "TextFieldInTableViewCell")
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = UITableView.automaticDimension
        tableView.tableFooterView = UIView()
        self.tableView = tableView
        tableView.dataSource = self

        let gesture = UITapGestureRecognizer(target: tableView, action: #selector(UITextView.endEditing(_:)))
        tableView.addGestureRecognizer(gesture)
    }
}

extension ViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int { return 1 }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 2 }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TextFieldInTableViewCell") as! TextFieldInTableViewCell
        cell.delegate = self
        return cell
    }
}

extension ViewController: TextFieldInTableViewCellDelegate {

    func textField(editingDidBeginIn cell: TextFieldInTableViewCell) {
        if let indexPath = tableView?.indexPath(for: cell) {
            print("textfield selected in cell at \(indexPath)")
        }
    }

    func textField(editingChangedInTextField newText: String, in cell: TextFieldInTableViewCell) {
        if let indexPath = tableView?.indexPath(for: cell) {
            print("updated text in textfield in cell as \(indexPath), value = \"\(newText)\"")
        }
    }
}

Result

结果

enter image description here

在此处输入图片说明

回答by Ben Mosher

I had been avoiding this by calling a method to run [cell.contentView bringSubviewToFront:textField]every time my cells appeared, but then I discovered this relatively simple technique:

我一直通过在[cell.contentView bringSubviewToFront:textField]每次出现我的单元格时调用一个方法来避免这种情况,但后来我发现了这个相对简单的技术:

cell.accessoryView = textField;

Doesn't seem to have the same background-overpasting issue, and it aligns itself on its own (somewhat). Also, the textLabel auto-truncates to avoid overflowing into (or under) it, which is handy.

似乎没有相同的背景过度粘贴问题,并且它自己对齐(有点)。此外, textLabel 会自动截断以避免溢出(或溢出)它,这很方便。

回答by Arie Pieter Cammeraat

I ran into the same problem. It seems that setting the cell.textlabel.textproperty brings the UILabel to the front of the contentView of the cell. Add the textView after setting textLabel.text, or (if that's not possible) call this:

我遇到了同样的问题。似乎设置cell.textlabel.text属性会将 UILabel 带到单元格的 contentView 的前面。在设置之后添加 textView textLabel.text,或者(如果不可能)调用它:

[cell.contentView bringSubviewToFront:textField]

回答by Bryan

I really struggled with this task on the iPad, with text fields showing up invisible in the UITableView, and the whole row turning blue when it gets focus.

我真的在 iPad 上为这个任务苦苦挣扎,文本字段在 UITableView 中显示不可见,并且当它获得焦点时整行变成蓝色。

What worked for me in the end was the technique described under "The Technique for Static Row Content" in Apple's Table View Programming Guide. I put both the label and the textField in a UITableViewCell in the NIB for the view, and pull that cell out via an outlet in cellForRowAtIndexPath:. The resulting code is much neater than UICatalog.

最后对我有用的是 Apple 的Table View Programming Guide 中“静态行内容技术”中描述的技术 。我将标签和 textField 都放在视图的 NIB 中的 UITableViewCell 中,并通过cellForRowAtIndexPath:. 生成的代码比 UICatalog 简洁得多。

回答by j2emanue

Here's how its done i believe the correct way. It works on Ipad and Iphone as i tested it. We have to create our own customCells by classing a uitableviewcell:

这是我相信正确方法的方法。它适用于 Ipad 和 Iphone,因为我对其进行了测试。我们必须通过对 uitableviewcell 进行分类来创建我们自己的 customCells:

start off in interfaceBuilder ... create a new UIViewcontroller call it customCell (volunteer for a xib while your there) Make sure customCell is a subclass of uitableviewcell

在 interfaceBuilder 中开始...创建一个新的 UIViewcontroller,将其命名为 customCell(当你在那里时自愿加入一个 xib)确保 customCell 是 uitableviewcell 的子类

erase all views now and create one view make it the size of a individual cell. make that view subclass customcell. now create two other views (duplicate the first).
Go to your connections inspector and find 2 IBOutlets you can connect to these views now.

现在擦除所有视图并创建一个视图,使其具有单个单元格的大小。使该视图子类 customcell。现在创建另外两个视图(复制第一个)。
转到您的连接检查器并找到 2 个 IBOutlets,您现在可以连接到这些视图。

-backgroundView -SelectedBackground

-backgroundView -SelectedBackground

connect these to the last two views you just duplicated and dont worry about them. the very first view that extends customCell, put your label and uitextfield inside of it. got into customCell.h and hook up your label and textfield. Set the height of this view to say 75 (height of each cell) all done.

将这些连接到您刚刚复制的最后两个视图,不要担心它们。扩展 customCell 的第一个视图,将您的标签和 uitextfield 放在其中。进入 customCell.h 并连接您的标签和文本字段。将此视图的高度设置为 75(每个单元格的高度)全部完成。

In your customCell.m file make sure the constructor looks something like this:

在您的 customCell.m 文件中,确保构造函数看起来像这样:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
    // Initialization code
    NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"CustomCell"       owner:self options:nil]; 
    self = [nibArray objectAtIndex:0];
}
return self;
}

Now create a UITableViewcontroller and in this method use the customCell class like this :

现在创建一个 UITableViewcontroller 并在此方法中使用 customCell 类,如下所示:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
// lets use our customCell which has a label and textfield already installed for us

customCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    //cell = [[[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];


    NSArray *topLevelsObjects = [[NSBundle mainBundle] loadNibNamed:@"NewUserCustomCell" owner:nil options:nil];
    for (id currentObject in topLevelsObjects){
        if ([currentObject  isKindOfClass:[UITableViewCell class]]){
            cell = (customCell *) currentObject;
            break;
        }
    }

    NSUInteger row = [indexPath row];

switch (row) {
    case 0:
    {

        cell.titleLabel.text = @"First Name"; //label we made (uitextfield also available now)

        break;
    }


        }
return cell;

}

}

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

return 75.0;
}