簡體   English   中英

自定義UITableViewCells

[英]Custom UITableViewCells

我真的很驚訝在執行iphone應用程序時保持代碼結構良好和可讀性有多么困難......但這可能是因為我做錯了什么。

我有一個注冊頁面,其中包含不同類型的內聯可編輯數據:生日,性別,姓名,密碼,電話號碼。 我將頁面作為自定義單元格的表格視圖,其中每個單元格是UITableViewCell子類的一個實例,並從其自己的nib文件中讀取。 這是因為我認為我可能稍后可以在其他表視圖頁面中重用這些不同類型的單元格。

將不同的自定義單元封裝在自己的位置的方法雖然效果不好:

  1. 誰將成為GenderCell內部性別選擇器的控制者?

  2. 當我不得不將SignUpController作為文件的單元nib文件的所有者時,我實際上如何在不同的表視圖控制器中重用單元格?

我不知道除了我以外是否有人理解我剛寫的內容,但如果有的話,我會非常感謝有關如何以不同方式構建代碼的任何建議。

非常感謝,
斯坦

為了使事情更清楚(?!),讓我在這里粘貼一些代碼:

EditableLabel.h

@interface EditableLabel : UILabel {   
    UIView *inputView, *inputAccessoryView; 
}

@property (nonatomic, retain) UIView *inputView, *inputAccessoryView; 

- (void) setInputView:(UIView *)aView andToolbar:(UIToolbar *)aToolbar;

@end

EditableLabel.m

@implementation EditableLabel

@synthesize inputView, inputAccessoryView;

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

- (void) setInputView:(UIView *)aView andToolbar:(UIToolbar *)aToolbar {
    self.inputAccessoryView = aToolbar;
    self.inputView = aView;
}

- (BOOL) canBecomeFirstResponder {
    return YES;
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [self becomeFirstResponder];
}

@end

EditableCell.h

typedef enum {
    USERNAME, PASSWORD, MOBILE, BIRTHDAY, GENDER, DESCRIPTION, CATEGORY
} CellTag;

@interface EditableCell : UITableViewCell {
    CellTag tag;    
    UIView *editPoint;
    IBOutlet UILabel *headerLabel;
}

- (void) setTag:(CellTag)aTag andHeader:(NSString *)aHeader andEditPoint:(UIView *)aView;

@property (nonatomic) CellTag tag;
@property (nonatomic, retain) UIView *editPoint;
@property (nonatomic, retain) UILabel *headerLabel;

- (IBAction) editingDone:(id)sender;

- (void) showInputView;
- (void) hideInputView;

@end

EditableCell.m

@implementation EditableCell

@synthesize tag, editPoint, headerLabel;

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

- (void) setTag:(CellTag)aTag andHeader:(NSString *)aHeader andEditPoint:(UIView *)aView {
    self.tag = aTag;
    self.headerLabel.text = aHeader;
    self.editPoint = aView;
}

- (IBAction) editingDone:(id)sender {
    [self hideInputView];
}

- (void) showInputView {   
    [self.editPoint becomeFirstResponder];
}

- (void) hideInputView {
    [self.editPoint resignFirstResponder];    
}

@end

EditableLabelCell.h

@interface EditableLabelCell : EditableCell {
    IBOutlet UILabel *placeHolderLabel;
    IBOutlet EditableLabel *editableLabel;
}

@property (nonatomic, retain) UILabel *placeHolderLabel;
@property (nonatomic, retain) EditableLabel *editableLabel;

- (void) setTag:(CellTag)aTag 
      andHeader:(NSString *)aHeader 
 andPlaceHolder:(NSString *)aPlaceHolder
   andInputView:(UIView *)aView
     andToolbar:(UIToolbar *)aToolbar;

- (void) setValue:(NSString *)aValue;

@end

EditableLabelCell.m

@implementation EditableLabelCell

@synthesize placeHolderLabel, editableLabel;

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

- (void) setTag:(CellTag)aTag andHeader:(NSString *)aHeader andPlaceHolder:(NSString *)aPlaceHolder andInputView:(UIView *)aView andToolbar:(UIToolbar *)aToolbar {
    [super setTag:aTag andHeader:aHeader andEditPoint:self.editableLabel];
    self.placeHolderLabel.text = aPlaceHolder;
    [self.editableLabel setInputView:aView andToolbar:aToolbar];    
}

- (void) setValue:(NSString *)aValue {
    if (aValue && aValue != @"") {                
        self.placeHolderLabel.hidden = YES;
        self.editableLabel.text = aValue;        
    } else {
        self.editableLabel.text = nil;
        self.placeHolderLabel.hidden = NO;
    }
}

@end

EditableGenderCell.h

@protocol EditableGenderCellDelegate <NSObject>
@required
  - (NSString *) getTextForGender:(Gender)aGender;
  - (void) genderChangedTo:(Gender)aGender forTag:(CellTag)aTag;
@end

@interface EditableGenderCell : EditableLabelCell <UITableViewDataSource, UITableViewDelegate> {
    id<EditableGenderCellDelegate> delegate;    
    Gender gender;
    IBOutlet UITableView *genderTable;
    IBOutlet UIToolbar *doneBar;
}

- (void) setTag:(CellTag)aTag 
    andDelegate:(id<EditableGenderCellDelegate>)aDelegate 
      andHeader:(NSString *)aHeader 
      andGender:(Gender)aGender
 andPlaceHolder:(NSString *)aPlaceHolder;

@property (nonatomic, retain) id<EditableGenderCellDelegate> delegate;
@property (nonatomic) Gender gender;
@property (nonatomic, retain) UITableView *genderTable;
@property (nonatomic, retain) UIToolbar *doneBar;

@end

EditableGenderCell.m

@implementation EditableGenderCell

@synthesize delegate, gender, genderTable, doneBar;

- (void) dealloc {
    [delegate release];
    [genderTable release];
    [doneBar release];
    [super dealloc];
}

- (void) setTag:(CellTag)aTag andDelegate:(id<EditableGenderCellDelegate>)aDelegate andHeader:(NSString *)aHeader andGender:(Gender)aGender andPlaceHolder:(NSString *)aPlaceHolder {
    [super setTag:aTag andHeader:aHeader andPlaceHolder:aPlaceHolder andInputView:self.genderTable andToolbar:self.doneBar];
    self.delegate = aDelegate;
    self.gender = aGender;
    [super setValue:[self.delegate getTextForGender:aGender]];
}

#pragma mark - Table view data source

- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

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

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

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

    switch (indexPath.row) {
        case MALE:
            switch (self.gender) {
                case MALE:
                    cell.accessoryType = UITableViewCellAccessoryCheckmark;    
                    break;
                default:
                    cell.accessoryType = UITableViewCellAccessoryNone;  
            } 
            break;
        case FEMALE:
            switch (self.gender) {
                case FEMALE:
                    cell.accessoryType = UITableViewCellAccessoryCheckmark;    
                    break;
                default:
                    cell.accessoryType = UITableViewCellAccessoryNone; 
            }  
            break;
    }

    cell.textLabel.text = [self.delegate getTextForGender:indexPath.row];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}

#pragma mark - Table view delegate

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    self.gender = indexPath.row;
    [super setValue:[self.delegate getTextForGender:self.gender]];
    [self.delegate genderChangedTo:self.gender forTag:self.tag];   
    [tableView reloadData];
}

@end

看看我如何使UITableViewCell具有不同的子視圖可重用的答案

您應該使用表示單元格的自定義類備份自定義tableviewcell nib文件,並在其中封裝邏輯,例如您的性別選擇器。 如果您需要通知某些外部控制器性別,您可以使用委托模式。

TableViewCell中的自定義性別選擇器

好吧,讓我們從nib文件開始,看起來像這樣:

在此輸入圖像描述

查看層次結構,不要設置文件的所有者...

在此輸入圖像描述

...設置自定義類的表視圖單元格的類:

在此輸入圖像描述

自定義類

如您所見,該類幾乎為空,僅提供分段控件作為屬性

GenderPickerTableViewCell.h

@interface GenderPickerTableViewCell : UITableViewCell 
{
    UISegmentedControl *genderPickerSegmentedControl;
}

@property (nonatomic, retain) IBOutlet UISegmentedControl *genderPickerSegmentedControl;

@end

GenderPickerTableViewCell.m

#import "GenderPickerTableViewCell.h"


@implementation GenderPickerTableViewCell

@synthesize genderPickerSegmentedControl;

#pragma mark -
#pragma mark memory management

- (void)dealloc 
{   
    [genderPickerSegmentedControl release];

    [super dealloc];
}

#pragma mark -
#pragma mark initialization

- (void)awakeFromNib
{
    // initialization goes here, for example preselect a specific gender
}

@end

使用我們的新單元格的表格視圖

我只提供必要的方法來完成這項工作。 TableViewCellFactory類只是一個nib加載器,就像我在上面引用的答案中發布的那樣。 genderPickerTableViewCellWithTableView只是一個方便類方法,可以返回那種特殊類型的單元格而沒有太多樣板代碼

最后要注意的是單元的配置,這很簡單,我只是直接訪問分段控件並向其添加目標,通知此視圖控制器有關更改。

#pragma mark -
#pragma mark view lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    tableView.rowHeight = 100.0;
    tableView.dataSource = self;
    tableView.delegate = self;
}

#pragma mark -
#pragma mark UITableView methods

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

- (UITableViewCell *) tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)anIndexPath
{
    GenderPickerTableViewCell *cell = [TableViewCellFactory genderPickerTableViewCellWithTableView:aTableView];

    [cell.genderPickerSegmentedControl addTarget:self 
                                          action:@selector(genderPicked:) 
                                forControlEvents:UIControlEventValueChanged];

    return cell;
}

#pragma mark -
#pragma mark UISegmentedControl action

- (void)genderPicked:(id)sender
{
    UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;

    NSLog(@"selected index: %d", [segmentedControl selectedSegmentIndex]);
}

我希望這對一開始有所幫助。

這是您可以用於彈跳的代碼:

 -(IBAction)textFieldDidBeginEditing:(UITextField *)textField { //Keyboard becomes visible
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3];
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y - 50, self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];

}

只需在編輯開始時相應地設置y即可調用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM