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
Having a UITextField in a UITableViewCell
提问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 UITextField
in some of my UITableViewCells
, just like in this example:
我试图做了两天的现在,和阅读吨的人试图做到这一点的消息后,我仍然无法有一个完全工作UITextField
在一些我的UITableViewCells
,就像这个例子:
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 UITextField
in a UITableViewCell
, that works fine?
有人可以帮助我(以及所有试图实现此控件的人)并发布一个简单的 a UITextField
in 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:
结果如下所示:
回答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 UITableViewCellStyleValue1
and staple a UITextField
where the detailTextLabel
is 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。
Note: this is using storyboard with a UITableViewCellStyleValue1
type 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
结果
回答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.text
property 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;
}