Ios7 iOS 7内联日期选择器-不出现在单元格边界内
我已经将用于内联显示PickerView的代码合并到以前的uitableview代码中。发生的情况是,pickerView的渲染超出了tableviewcell的边界 有人知道为什么我的单元格内容不显示在单元格边界中吗 我甚至删除了picker视图并使用标签进行测试,同样的事情也发生了。很明显,cell contentView出现了一些问题-我似乎无法锁定它 屏幕截图(单击以显示日期选择器之前): 问题屏幕截图(单击显示日期选择器后): 问题V2屏幕截图: (单元格剪辑边界为“是”) 情节提要布局屏幕截图: (单元格具有绿色背景以显示可见性) 情节提要布局大纲屏幕截图: 代码: ECNAddSessionViewController.hIos7 iOS 7内联日期选择器-不出现在单元格边界内,ios7,uitableview,Ios7,Uitableview,我已经将用于内联显示PickerView的代码合并到以前的uitableview代码中。发生的情况是,pickerView的渲染超出了tableviewcell的边界 有人知道为什么我的单元格内容不显示在单元格边界中吗 我甚至删除了picker视图并使用标签进行测试,同样的事情也发生了。很明显,cell contentView出现了一些问题-我似乎无法锁定它 屏幕截图(单击以显示日期选择器之前): 问题屏幕截图(单击显示日期选择器后): 问题V2屏幕截图: (单元格剪辑边界为“是”) 情节
@interface ECNAddSessionViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
@end
通用设置方法
- (void)commonSetup {
//initialize our Session
self.session = [[Session alloc] init];
self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateStyle:NSDateFormatterShortStyle]; // show short-style date format
[self.dateFormatter setTimeStyle:NSDateFormatterNoStyle];
// obtain the picker view cell's height, works because the cell was pre-defined in our storyboard
UITableViewCell *pickerViewCellToCheck = [self.tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier];
self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
}
/*! Determines if the given indexPath has a cell below it with a UIDatePicker.
@param indexPath The indexPath to check if its cell has a UIDatePicker below it.
*/
- (BOOL)hasPickerForIndexPath:(NSIndexPath *)indexPath {
BOOL hasDatePicker = NO;
NSInteger targetedRow = indexPath.row;
targetedRow++;
UITableViewCell *checkDatePickerCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:targetedRow inSection:0]];
UIDatePicker *checkDatePicker = (UIDatePicker *)[checkDatePickerCell viewWithTag:kDatePickerTag];
hasDatePicker = (checkDatePicker != nil);
return hasDatePicker;
}
/*! Updates the UIDatePicker's value to match with the date of the cell above it.
*/
- (void)updateDatePicker {
if (self.datePickerIndexPath != nil) {
UITableViewCell *associatedDatePickerCell = [self.tableView cellForRowAtIndexPath:self.datePickerIndexPath];
UIDatePicker *targetedDatePicker = (UIDatePicker *)[associatedDatePickerCell viewWithTag:kDatePickerTag];
if (targetedDatePicker != nil) {
// we found a UIDatePicker in this cell, so update it's date value
if (self.session.date) {
[targetedDatePicker setDate:self.session.date animated:NO];
}
}
}
}
/*! Determines if the UITableViewController has a UIDatePicker in any of its cells.
*/
- (BOOL)hasInlineDatePicker {
return (self.datePickerIndexPath != nil);
}
/*! Determines if the given indexPath points to a cell that contains the UIDatePicker.
@param indexPath The indexPath to check if it represents a cell with the UIDatePicker.
*/
- (BOOL)indexPathHasPicker:(NSIndexPath *)indexPath {
return ([self hasInlineDatePicker] && self.datePickerIndexPath.row == indexPath.row);
}
/*! Determines if the given indexPath points to a cell that contains the start/end dates.
@param indexPath The indexPath to check if it represents start/end date cell.
*/
- (BOOL)indexPathHasDate:(NSIndexPath *)indexPath {
BOOL hasDate = NO;
if ((indexPath.row == kDateStartRow) || [self hasInlineDatePicker]) {
hasDate = YES;
}
return hasDate;
}
/*! Adds or removes a UIDatePicker cell below the given indexPath.
@param indexPath The indexPath to reveal the UIDatePicker.
*/
- (void)toggleDatePickerForSelectedIndexPath:(NSIndexPath *)indexPath {
[self.tableView beginUpdates];
NSArray *indexPaths = @[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];
// check if 'indexPath' has an attached date picker below it
if ([self hasPickerForIndexPath:indexPath]) {
// found a picker below it, so remove it
[self.tableView deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}else {
// didn't find a picker below it, so we should insert it
[self.tableView insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView endUpdates];
}
苹果提供的示例代码方法-略微调整
- (void)commonSetup {
//initialize our Session
self.session = [[Session alloc] init];
self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateStyle:NSDateFormatterShortStyle]; // show short-style date format
[self.dateFormatter setTimeStyle:NSDateFormatterNoStyle];
// obtain the picker view cell's height, works because the cell was pre-defined in our storyboard
UITableViewCell *pickerViewCellToCheck = [self.tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier];
self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
}
/*! Determines if the given indexPath has a cell below it with a UIDatePicker.
@param indexPath The indexPath to check if its cell has a UIDatePicker below it.
*/
- (BOOL)hasPickerForIndexPath:(NSIndexPath *)indexPath {
BOOL hasDatePicker = NO;
NSInteger targetedRow = indexPath.row;
targetedRow++;
UITableViewCell *checkDatePickerCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:targetedRow inSection:0]];
UIDatePicker *checkDatePicker = (UIDatePicker *)[checkDatePickerCell viewWithTag:kDatePickerTag];
hasDatePicker = (checkDatePicker != nil);
return hasDatePicker;
}
/*! Updates the UIDatePicker's value to match with the date of the cell above it.
*/
- (void)updateDatePicker {
if (self.datePickerIndexPath != nil) {
UITableViewCell *associatedDatePickerCell = [self.tableView cellForRowAtIndexPath:self.datePickerIndexPath];
UIDatePicker *targetedDatePicker = (UIDatePicker *)[associatedDatePickerCell viewWithTag:kDatePickerTag];
if (targetedDatePicker != nil) {
// we found a UIDatePicker in this cell, so update it's date value
if (self.session.date) {
[targetedDatePicker setDate:self.session.date animated:NO];
}
}
}
}
/*! Determines if the UITableViewController has a UIDatePicker in any of its cells.
*/
- (BOOL)hasInlineDatePicker {
return (self.datePickerIndexPath != nil);
}
/*! Determines if the given indexPath points to a cell that contains the UIDatePicker.
@param indexPath The indexPath to check if it represents a cell with the UIDatePicker.
*/
- (BOOL)indexPathHasPicker:(NSIndexPath *)indexPath {
return ([self hasInlineDatePicker] && self.datePickerIndexPath.row == indexPath.row);
}
/*! Determines if the given indexPath points to a cell that contains the start/end dates.
@param indexPath The indexPath to check if it represents start/end date cell.
*/
- (BOOL)indexPathHasDate:(NSIndexPath *)indexPath {
BOOL hasDate = NO;
if ((indexPath.row == kDateStartRow) || [self hasInlineDatePicker]) {
hasDate = YES;
}
return hasDate;
}
/*! Adds or removes a UIDatePicker cell below the given indexPath.
@param indexPath The indexPath to reveal the UIDatePicker.
*/
- (void)toggleDatePickerForSelectedIndexPath:(NSIndexPath *)indexPath {
[self.tableView beginUpdates];
NSArray *indexPaths = @[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];
// check if 'indexPath' has an attached date picker below it
if ([self hasPickerForIndexPath:indexPath]) {
// found a picker below it, so remove it
[self.tableView deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}else {
// didn't find a picker below it, so we should insert it
[self.tableView insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView endUpdates];
}
显示内联日期选择器方法
- (void)commonSetup {
//initialize our Session
self.session = [[Session alloc] init];
self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateStyle:NSDateFormatterShortStyle]; // show short-style date format
[self.dateFormatter setTimeStyle:NSDateFormatterNoStyle];
// obtain the picker view cell's height, works because the cell was pre-defined in our storyboard
UITableViewCell *pickerViewCellToCheck = [self.tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier];
self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
}
/*! Determines if the given indexPath has a cell below it with a UIDatePicker.
@param indexPath The indexPath to check if its cell has a UIDatePicker below it.
*/
- (BOOL)hasPickerForIndexPath:(NSIndexPath *)indexPath {
BOOL hasDatePicker = NO;
NSInteger targetedRow = indexPath.row;
targetedRow++;
UITableViewCell *checkDatePickerCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:targetedRow inSection:0]];
UIDatePicker *checkDatePicker = (UIDatePicker *)[checkDatePickerCell viewWithTag:kDatePickerTag];
hasDatePicker = (checkDatePicker != nil);
return hasDatePicker;
}
/*! Updates the UIDatePicker's value to match with the date of the cell above it.
*/
- (void)updateDatePicker {
if (self.datePickerIndexPath != nil) {
UITableViewCell *associatedDatePickerCell = [self.tableView cellForRowAtIndexPath:self.datePickerIndexPath];
UIDatePicker *targetedDatePicker = (UIDatePicker *)[associatedDatePickerCell viewWithTag:kDatePickerTag];
if (targetedDatePicker != nil) {
// we found a UIDatePicker in this cell, so update it's date value
if (self.session.date) {
[targetedDatePicker setDate:self.session.date animated:NO];
}
}
}
}
/*! Determines if the UITableViewController has a UIDatePicker in any of its cells.
*/
- (BOOL)hasInlineDatePicker {
return (self.datePickerIndexPath != nil);
}
/*! Determines if the given indexPath points to a cell that contains the UIDatePicker.
@param indexPath The indexPath to check if it represents a cell with the UIDatePicker.
*/
- (BOOL)indexPathHasPicker:(NSIndexPath *)indexPath {
return ([self hasInlineDatePicker] && self.datePickerIndexPath.row == indexPath.row);
}
/*! Determines if the given indexPath points to a cell that contains the start/end dates.
@param indexPath The indexPath to check if it represents start/end date cell.
*/
- (BOOL)indexPathHasDate:(NSIndexPath *)indexPath {
BOOL hasDate = NO;
if ((indexPath.row == kDateStartRow) || [self hasInlineDatePicker]) {
hasDate = YES;
}
return hasDate;
}
/*! Adds or removes a UIDatePicker cell below the given indexPath.
@param indexPath The indexPath to reveal the UIDatePicker.
*/
- (void)toggleDatePickerForSelectedIndexPath:(NSIndexPath *)indexPath {
[self.tableView beginUpdates];
NSArray *indexPaths = @[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];
// check if 'indexPath' has an attached date picker below it
if ([self hasPickerForIndexPath:indexPath]) {
// found a picker below it, so remove it
[self.tableView deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}else {
// didn't find a picker below it, so we should insert it
[self.tableView insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView endUpdates];
}
在多个部分中,我硬编码了1,使其只包含一个部分,就像苹果的示例代码一样,尽管最终tableview将包含三个部分
/*! Reveals the date picker inline for the given indexPath, called by "didSelectRowAtIndexPath".
@param indexPath The indexPath to reveal the UIDatePicker.
*/
- (void)displayInlineDatePickerForRowAtIndexPath:(NSIndexPath *)indexPath {
// display the date picker inline with the table content
[self.tableView beginUpdates];
BOOL before = NO; // indicates if the date picker is below "indexPath", help us determine which row to reveal
if ([self hasInlineDatePicker]) {
before = self.datePickerIndexPath.row < indexPath.row;
}
BOOL sameCellClicked = (self.datePickerIndexPath.row - 1 == indexPath.row);
// remove any date picker cell if it exists
if ([self hasInlineDatePicker]) {
[self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.datePickerIndexPath.row inSection:0]]
withRowAnimation:UITableViewRowAnimationFade];
self.datePickerIndexPath = nil;
}
if (!sameCellClicked) {
// hide the old date picker and display the new one
NSInteger rowToReveal = (before ? indexPath.row - 1 : indexPath.row);
NSIndexPath *indexPathToReveal = [NSIndexPath indexPathForRow:rowToReveal inSection:0];
[self toggleDatePickerForSelectedIndexPath:indexPathToReveal];
self.datePickerIndexPath = [NSIndexPath indexPathForRow:indexPathToReveal.row + 1 inSection:0];
}
// always deselect the row containing the start or end date
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.tableView endUpdates];
// inform our date picker of the current date to match the current cell
[self updateDatePicker];
}
单元配置
@interface ECNAddSessionViewController ()
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) Session *session;
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
// keep track which indexPath points to the cell with UIDatePicker
@property (nonatomic, strong) NSIndexPath *datePickerIndexPath;
@property (assign) NSInteger pickerCellRowHeight;
@property (nonatomic, strong) IBOutlet UIDatePicker *pickerView;
// this button appears only when the date picker is shown (iOS 6.1.x or earlier)
@property (nonatomic, strong) IBOutlet UIBarButtonItem *doneButton;
- (void)commonSetup;
- (void)registerForNotifications;
- (void)deregisterForNotifications;
- (IBAction)cancelAction:(UIButton *)sender;
- (IBAction)saveAction:(UIButton *)sender;
@end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
switch (indexPath.section) {
case AddSessionBasicInfoSection:
switch (indexPath.row) {
case 0: // session name cell
{
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionSessionNameCellIdentifier forIndexPath:indexPath];
}
break;
case 1: //company name cell
{
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionCompanyNameCellIdentifier forIndexPath:indexPath];
}
break;
case 2: // date cell
{
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionDateCellIdentifier forIndexPath:indexPath];
// we have either start or end date cells, populate their date field
cell.textLabel.text = [self.dateFormatter stringFromDate:self.session.date];
}
break;
case 3: // date picker cell
{
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier forIndexPath:indexPath];
NSLog(@"%@", indexPath);
}
break;
}
break;
case AddSessionTagsSection:
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionAddTagsCellIdentifier forIndexPath:indexPath];
break;
case AddSessionContentSection:
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionAddContentCellIdentifier forIndexPath:indexPath];
break;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.reuseIdentifier == kECNAddSessionDateCellIdentifier) {
if (EMBEDDED_DATE_PICKER) {
[self displayInlineDatePickerForRowAtIndexPath:indexPath];
}else {
[self displayExternalDatePickerForRowAtIndexPath:indexPath];
}
}else{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
单元格选择
@interface ECNAddSessionViewController ()
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) Session *session;
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
// keep track which indexPath points to the cell with UIDatePicker
@property (nonatomic, strong) NSIndexPath *datePickerIndexPath;
@property (assign) NSInteger pickerCellRowHeight;
@property (nonatomic, strong) IBOutlet UIDatePicker *pickerView;
// this button appears only when the date picker is shown (iOS 6.1.x or earlier)
@property (nonatomic, strong) IBOutlet UIBarButtonItem *doneButton;
- (void)commonSetup;
- (void)registerForNotifications;
- (void)deregisterForNotifications;
- (IBAction)cancelAction:(UIButton *)sender;
- (IBAction)saveAction:(UIButton *)sender;
@end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
switch (indexPath.section) {
case AddSessionBasicInfoSection:
switch (indexPath.row) {
case 0: // session name cell
{
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionSessionNameCellIdentifier forIndexPath:indexPath];
}
break;
case 1: //company name cell
{
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionCompanyNameCellIdentifier forIndexPath:indexPath];
}
break;
case 2: // date cell
{
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionDateCellIdentifier forIndexPath:indexPath];
// we have either start or end date cells, populate their date field
cell.textLabel.text = [self.dateFormatter stringFromDate:self.session.date];
}
break;
case 3: // date picker cell
{
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier forIndexPath:indexPath];
NSLog(@"%@", indexPath);
}
break;
}
break;
case AddSessionTagsSection:
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionAddTagsCellIdentifier forIndexPath:indexPath];
break;
case AddSessionContentSection:
cell = [tableView dequeueReusableCellWithIdentifier:kECNAddSessionAddContentCellIdentifier forIndexPath:indexPath];
break;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.reuseIdentifier == kECNAddSessionDateCellIdentifier) {
if (EMBEDDED_DATE_PICKER) {
[self displayInlineDatePickerForRowAtIndexPath:indexPath];
}else {
[self displayExternalDatePickerForRowAtIndexPath:indexPath];
}
}else{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
找到答案后,我觉得自己很愚蠢,因为它很简单,单元格没有得到任何高度值,应该早点找到这个值 在我的
-(void)commonSetup中,我从我的datePickerCell
询问高度
方法,该方法将单元格出列并过早地获取其frame.size.height
我不得不将下面的代码从-(void)awakFromNib移动代码>通过将代码移动到-(void)viewDidLoad代码>
// obtain the picker view cell's height, works because the cell was pre-defined in our storyboard
UITableViewCell *pickerViewCellToCheck = [self.tableView dequeueReusableCellWithIdentifier:kECNAddSessionDatePickerCellIdentifier];
self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
当awakeFromNib
调用commonSetup