可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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:
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.
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?
回答1:
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.
- (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 = @\"example@gmail.com\";
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:
回答2:
Here is a solution that looks good under iOS6/7/8/9.
Update 2016-06-10: this still works with iOS 9.3.3
Thanks for all your support, this is now on CocoaPods/Carthage/SPM at 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.
Note: this is using storyboard with a UITableViewCellStyleValue1
type cell named \"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;
}
回答3:
Here is how I have achieved this:
TextFormCell.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
#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!
回答4:
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];
}
回答5:
This should not be difficult. When creating a cell for your table, add a UITextField object to the cell\'s content view
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.
回答6:
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.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.
回答7:
UITextField in a UITableViewCell in Swift 3
Details
Xcode 8.2.1, Swift 3
Task
Create UITextField in UITableViewCell and delegate UITextField editing function to ViewController
Full Sample Code
class ViewController
import UIKit
class ViewController: UIViewController {
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
}
}
// MARK: - TableView
extension ViewController {
func setupTableView() {
tableView.dataSource = self
tableView.tableFooterView = UIView()
let gesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.endEditing))
tableView.addGestureRecognizer(gesture)
}
func endEditing() {
tableView.endEditing(true)
}
}
// MARK: - UITableViewDataSource
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
}
}
// MARK: - TextFieldInTableViewCellDelegate
extension ViewController: TextFieldInTableViewCellDelegate {
func textFieldInTableViewCell(didSelect cell:TextFieldInTableViewCell) {
if let indexPath = tableView.indexPath(for: cell){
print(\"didSelect cell: \\(indexPath)\")
}
}
func textFieldInTableViewCell(cell:TextFieldInTableViewCell, editingChangedInTextField newText:String) {
if let indexPath = tableView.indexPath(for: cell){
print(\"editingChangedInTextField: \\\"\\(newText)\\\" in cell: \\(indexPath)\")
}
}
}
class TextFieldInTableViewCell
import UIKit
class TextFieldInTableViewCell: UITableViewCell {
@IBOutlet var textField: UITextField!
@IBOutlet var descriptionLabel: UILabel!
var delegate: TextFieldInTableViewCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
let gesture = UITapGestureRecognizer(target: self, action: #selector(TextFieldInTableViewCell.didSelectCell))
addGestureRecognizer(gesture)
}
}
// MARK: - Actions
extension TextFieldInTableViewCell {
func didSelectCell() {
textField.becomeFirstResponder()
delegate?.textFieldInTableViewCell(didSelect: self)
}
@IBAction func textFieldValueChanged(_ sender: UITextField) {
if let text = sender.text {
delegate?.textFieldInTableViewCell(cell: self, editingChangedInTextField: text)
}
}
}
protocol TextFieldInTableViewCellDelegate
import UIKit
protocol TextFieldInTableViewCellDelegate {
func textFieldInTableViewCell(didSelect cell:TextFieldInTableViewCell)
func textFieldInTableViewCell(cell:TextFieldInTableViewCell, editingChangedInTextField newText:String)
}
Main.storyboard
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"11762\" systemVersion=\"16C67\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" colorMatched=\"YES\" initialViewController=\"BYZ-38-t0r\">
<device id=\"retina4_7\" orientation=\"portrait\">
<adaptation id=\"fullscreen\"/>
</device>
<dependencies>
<deployment identifier=\"iOS\"/>
<plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"11757\"/>
<capability name=\"Constraints to layout margins\" minToolsVersion=\"6.0\"/>
<capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID=\"tne-QT-ifu\">
<objects>
<viewController id=\"BYZ-38-t0r\" customClass=\"ViewController\" customModule=\"stackoverflow_409259\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">
<layoutGuides>
<viewControllerLayoutGuide type=\"top\" id=\"y3c-jy-aDJ\"/>
<viewControllerLayoutGuide type=\"bottom\" id=\"wfy-db-euE\"/>
</layoutGuides>
<view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">
<rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"667\"/>
<autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>
<subviews>
<tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"plain\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"28\" sectionFooterHeight=\"28\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2cP-ct-Jtg\">
<rect key=\"frame\" x=\"0.0\" y=\"20\" width=\"375\" height=\"647\"/>
<color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>
<prototypes>
<tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" selectionStyle=\"none\" indentationWidth=\"10\" reuseIdentifier=\"TextFieldInTableViewCell\" id=\"KnN-sc-zHs\" customClass=\"TextFieldInTableViewCell\" customModule=\"stackoverflow_409259\" customModuleProvider=\"target\">
<rect key=\"frame\" x=\"0.0\" y=\"28\" width=\"375\" height=\"44\"/>
<autoresizingMask key=\"autoresizingMask\"/>
<tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" tableViewCell=\"KnN-sc-zHs\" id=\"AK1-Th-ke8\">
<rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"43\"/>
<autoresizingMask key=\"autoresizingMask\"/>
<subviews>
<label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Label\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"pEG-c7-yoZ\">
<rect key=\"frame\" x=\"8\" y=\"11\" width=\"77\" height=\"21\"/>
<constraints>
<constraint firstAttribute=\"width\" constant=\"77\" id=\"zhu-LA-GOo\"/>
</constraints>
<fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>
<nil key=\"textColor\"/>
<nil key=\"highlightedColor\"/>
</label>
<textField opaque=\"NO\" clipsSubviews=\"YES\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"left\" contentVerticalAlignment=\"center\" placeholder=\"text\" textAlignment=\"natural\" minimumFontSize=\"17\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"O1l-cp-c2b\">
<rect key=\"frame\" x=\"93\" y=\"6\" width=\"256\" height=\"31\"/>
<nil key=\"textColor\"/>
<fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>
<textInputTraits key=\"textInputTraits\"/>
<connections>
<action selector=\"textFieldValueChanged:\" destination=\"KnN-sc-zHs\" eventType=\"editingChanged\" id=\"0KD-Yx-Cl0\"/>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstItem=\"O1l-cp-c2b\" firstAttribute=\"leading\" secondItem=\"pEG-c7-yoZ\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"4bh-3C-WXp\"/>
<constraint firstItem=\"pEG-c7-yoZ\" firstAttribute=\"centerY\" secondItem=\"O1l-cp-c2b\" secondAttribute=\"centerY\" id=\"A0b-Mk-8KQ\"/>
<constraint firstItem=\"O1l-cp-c2b\" firstAttribute=\"top\" secondItem=\"AK1-Th-ke8\" secondAttribute=\"topMargin\" constant=\"-2\" id=\"BDA-fk-4JI\"/>
<constraint firstAttribute=\"trailingMargin\" secondItem=\"O1l-cp-c2b\" secondAttribute=\"trailing\" constant=\"18\" id=\"bYA-UQ-iBv\"/>
<constraint firstItem=\"pEG-c7-yoZ\" firstAttribute=\"top\" secondItem=\"AK1-Th-ke8\" secondAttribute=\"topMargin\" constant=\"3\" id=\"eDx-qb-b2G\"/>
<constraint firstItem=\"pEG-c7-yoZ\" firstAttribute=\"leading\" secondItem=\"AK1-Th-ke8\" secondAttribute=\"leadingMargin\" id=\"tpb-h3-LVs\"/>
<constraint firstItem=\"pEG-c7-yoZ\" firstAttribute=\"centerY\" secondItem=\"AK1-Th-ke8\" secondAttribute=\"centerY\" id=\"vsl-oj-yAN\"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property=\"descriptionLabel\" destination=\"pEG-c7-yoZ\" id=\"qdF-mm-xgu\"/>
<outlet property=\"textField\" destination=\"O1l-cp-c2b\" id=\"WMb-QW-wLg\"/>
</connections>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>
<constraints>
<constraint firstItem=\"2cP-ct-Jtg\" firstAttribute=\"leading\" secondItem=\"8bC-Xf-vdC\" secondAttribute=\"leading\" id=\"8M7-lY-IPn\"/>
<constraint firstItem=\"2cP-ct-Jtg\" firstAttribute=\"bottom\" secondItem=\"wfy-db-euE\" secondAttribute=\"top\" id=\"GaT-6q-zdl\"/>
<constraint firstAttribute=\"trailing\" secondItem=\"2cP-ct-Jtg\" secondAttribute=\"trailing\" id=\"pSM-zU-ndL\"/>
<constraint firstItem=\"2cP-ct-Jtg\" firstAttribute=\"top\" secondItem=\"y3c-jy-aDJ\" secondAttribute=\"bottom\" id=\"tkS-4A-t2B\"/>
</constraints>
</view>
<connections>
<outlet property=\"tableView\" destination=\"2cP-ct-Jtg\" id=\"VSj-8p-8c0\"/>
</connections>
</viewController>
<placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>
</objects>
<point key=\"canvasLocation\" x=\"-79.200000000000003\" y=\"138.98050974512745\"/>
</scene>
</scenes>
</document>
Result
回答8:
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.contentView bringSubviewToFront:textField]
回答9:
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.
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.
回答10:
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:
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
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.
-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.
In your customCell.m file make sure the constructor looks something like this:
- (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 :
- (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;
}
回答11:
Here\'s a drop-in subclass for UITableViewCell
which replaces the detailTextLabel with an editable UITextField
(or, in case of UITableViewCellStyleDefault
, replaces the textLabel). This has the benefit that it allows you to re-use all the familiar UITableViewCellStyles, accessoryViews, etc, just now the detail is editable!
@interface GSBEditableTableViewCell : UITableViewCell <UITextFieldDelegate>
@property UITextField *textField;
@end
@interface GSBEditableTableViewCell ()
@property UILabel *replace;
@end
@implementation GSBEditableTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_replace = (style == UITableViewCellStyleDefault)? self.textLabel : self.detailTextLabel;
_replace.hidden = YES;
// Impersonate UILabel with an identical UITextField
_textField = UITextField.new;
[self.contentView addSubview:_textField];
_textField.translatesAutoresizingMaskIntoConstraints = NO;
[_textField.leftAnchor constraintEqualToAnchor:_replace.leftAnchor].active = YES;
[_textField.rightAnchor constraintEqualToAnchor:_replace.rightAnchor].active = YES;
[_textField.topAnchor constraintEqualToAnchor:_replace.topAnchor].active = YES;
[_textField.bottomAnchor constraintEqualToAnchor:_replace.bottomAnchor].active = YES;
_textField.font = _replace.font;
_textField.textColor = _replace.textColor;
_textField.textAlignment = _replace.textAlignment;
// Dont want to intercept UITextFieldDelegate, so use UITextFieldTextDidChangeNotification instead
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(textDidChange:)
name:UITextFieldTextDidChangeNotification
object:_textField];
// Also need KVO because UITextFieldTextDidChangeNotification not fired when change programmatically
[_textField addObserver:self forKeyPath:@\"text\" options:0 context:nil];
}
return self;
}
- (void)textDidChange:(NSNotification*)notification
{
// Update (hidden) UILabel to ensure correct layout
if (_textField.text.length) {
_replace.text = _textField.text;
} else if (_textField.placeholder.length) {
_replace.text = _textField.placeholder;
} else {
_replace.text = @\" \"; // otherwise UILabel removed from cell (!?)
}
[self setNeedsLayout];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ((object == _textField) && [keyPath isEqualToString:@\"text\"]) [self textDidChange:nil];
}
- (void)dealloc
{
[_textField removeObserver:self forKeyPath:@\"text\"];
}
@end
Simple to use - just create your cell as before, but now use cell.textField instead of cell.detailTextLabel (or cell.textLabel in case of UITableViewCellStyleDefault
). eg
GSBEditableTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"Cell\"];
if (!cell) cell = [GSBEditableTableViewCell.alloc initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:@\"Cell\"];
cell.textLabel.text = @\"Name\";
cell.textField.text = _editablename;
cell.textField.delegate = self; // to pickup edits
...
Inspired by, and improved upon, FD\'s answer
回答12:
For next/return events on multiple UITextfield inside UITableViewCell in this method I had taken UITextField in storyboard.
@interface MyViewController () {
NSInteger currentTxtRow;
}
@end
@property (strong, nonatomic) NSIndexPath *currentIndex;//Current Selected Row
@implementation MyViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@\"CELL\" forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UITextField *txtDetails = (UITextField *)[cell.contentView viewWithTag:100];
txtDetails.delegate = self;
txtDetails.placeholder = self.arrReciversDetails[indexPath.row];
return cell;
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
CGPoint point = [textField convertPoint:CGPointZero toView:self.tableView];
self.currentIndex = [self.tableView indexPathForRowAtPoint:point];//Get Current UITableView row
currentTxtRow = self.currentIndex.row;
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
currentTxtRow += 1;
self.currentIndex = [NSIndexPath indexPathForRow:currentTxtRow inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.currentIndex];
UITextField *currentTxtfield = (UITextField *)[cell.contentView viewWithTag:100];
if (currentTxtRow < 3) {//Currently I have 3 Cells each cell have 1 UITextfield
[currentTxtfield becomeFirstResponder];
} else {
[self.view endEditing:YES];
[currentTxtfield resignFirstResponder];
}
}
To grab the text from textfield-
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
switch (self.currentIndex.row) {
case 0:
NSLog(@\"%@\",[NSString stringWithFormat:@\"%@%@\",textField.text,string]);//Take current word and previous text from textfield
break;
case 1:
NSLog(@\"%@\",[NSString stringWithFormat:@\"%@%@\",textField.text,string]);//Take current word and previous text from textfield
break;
case 2:
NSLog(@\"%@\",[NSString stringWithFormat:@\"%@%@\",textField.text,string]);//Take current word and previous text from textfield
break;
default:
break;
}
}