Generating UITableViews look not so plain


As most of you probably know, UITableView’s are really useful and flexible landscapes to be using in your programs.
If you have ever tried to personalize a UITableView though, you know that as soon as you begin including many UIViews, UILabels, and UImageViews to a tissue ContentView, that these tableviews begin to search more slowly and more slowly, and become choppier and choppier.

What we are going to examine these days is how to solution that circumstance.
To obtain the complete XCode venture, you may discover it at: http://github.com/elc/ICB_PrettyTableView

We are going to develop a easy get in touch with audience, that will present the mobile cellphone devices acquaintances. For each get in touch with, if they have a first name, last name, e-mail and amount, they will be viewed within one cellular, with different colours. The purpose this is useful is because it provides the principles for creating UITableViewCells that can really begin making your software look awesome, and still search well.
If you never want to have simulated information in the simulation, have a look at out this publish for duplication information from your system to the simulator: How to transfer acquaintances into the apple i cellphone simulator

In this example, we have a normal UITableViewController. We are going to have a pair training issues identified in the header

#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
 
@interface ICBTableViewController : UITableViewController
{
    ABAddressBookRef _addressBook;
}
 
@property (nonatomic, retain) NSArray *contacts;
 
@end
ABAddressBookRef _addressBook is scheduled in our headlines, so that we never have to launch it until we dealloc. And the acquaintances is so that we can carry on to the information for our tableView.
In the major desk perspective operator data file we are going to bypass the – (void)viewDidLoad to offer some preliminary arrangement of the tableView, as well as running or building our information. (We will produce bogus information for gadgets or the simulation that never have deal with publication data)

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.tableView.backgroundColor = UIColor.blackColor;
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
 
    ABAddressBookRef addressBook = ABAddressBookCreate();
    NSArray *tempArray = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
    tempArray = [tempArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        NSString *name1 = (NSString *)ABRecordCopyCompositeName((ABRecordRef)obj1);
        NSString *name2 = (NSString *)ABRecordCopyCompositeName((ABRecordRef)obj2);
        return [name1 compare:name2];
    }];
 
    if ([tempArray count] > 0) {
        self.contacts = tempArray;
    } else {
        NSMutableArray *tempMutableArray = [NSMutableArray arrayWithCapacity:100];
        for (int i = 0; i < 100; ++i) {
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            if ((i % 9) != 0) {
                [dict setObject:[NSString stringWithFormat:@"FirstName%d", i] forKey:@"firstName"];
            }
            if ((i % 3) == 0) {
                [dict setObject:[NSString stringWithFormat:@"LastName%d", i] forKey:@"lastName"];
            }
            if ((i % 3) == 0 && (i % 2) == 0) {
                [dict setObject:[NSString stringWithFormat:@"emailTest%d@test%d.com", i, i] forKey:@"email"];
            }
            if ((i % 7) == 0) {
                NSString *string = [NSString stringWithFormat:@"%d", i];
                while ([string length] < 10) {
                    string = [string stringByAppendingFormat:@"%@", string];
                }
                [dict setObject:string forKey:@"phone"];
            }
            [tempMutableArray addObject:dict];
        }
        self.contacts = tempMutableArray;
    }
}

As you can see here we have a few self.tableView techniques we have known as to make the qualifications coloring, and also the cellular separator design.
If you are managing this software on a system, or simulation that has acquaintances, this technique will also make a duplicate of the deal with publication as the information to present. If there is no information in the deal with publication, we make some bogus examine information just for showing.
Also keep in mind to contain our – (void)dealloc means for publishing our _addressBook diverse.

- (void)dealloc
{
    CFRelease(_addressBook);
    [_contacts release];
    _contacts = nil;
}

We have to provide the tableView with our amount of rows

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.contacts count];
}

The next part we have to bypass is the – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath so that we can provide the tableView with our tissue.

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
 
    static NSString *CellIdentifier = @"ICBTableViewCellIdentifier";
 
    ICBTableViewCell *cell = (ICBTableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[ICBTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.textLabel.textColor = UIColor.whiteColor;
    }
    cell.tag = indexPath.row;
 
    NSObject *object = [self.contacts objectAtIndex:indexPath.row];
    if ([object isKindOfClass:NSDictionary.class]) {
        [cell setDictionary:(NSDictionary *)object];
    } else {
        [cell setRecord:(ABRecordRef)object];
    }
 
    return cell;
}

We are verifying each subject returning out of our assortment so that we can figure out if we need to telephone the setDictionary, or setRecord technique calling.

Now the beef of this article, increasing a UITableViewCell.

In our headlines we are going to figure out a lot of post that we want to display

#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
 
@interface ICBTableViewCell : UITableViewCell
 
@property (nonatomic, retain) NSString *firstName;
@property (nonatomic, retain) NSString *lastName;
@property (nonatomic, retain) NSString *email;
@property (nonatomic, retain) NSString *phone;
@property (nonatomic, retain) NSString *address;
 
- (void)setRecord:(ABRecordRef)record;
- (void)setDictionary:(NSDictionary *)dict;
 
@end

And then our two set methods:

- (void)setRecord:(ABRecordRef)record
{
    self.firstName = [(NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty) autorelease];
    self.lastName = [(NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty) autorelease];
    self.email = [self getFirstEmail:record];
    self.phone = [self getFirstPhone:record];
    [self setNeedsDisplay];
}
 
- (void)setDictionary:(NSDictionary *)dict
{
    self.firstName = [dict objectForKey:@"firstName"];
    self.lastName = [dict objectForKey:@"lastName"];
    self.email = [dict objectForKey:@"email"];
    self.phone = [dict objectForKey:@"phone"];
    [self setNeedsDisplay];
}

Some lessons will have you put this next piece into a individual UIView subclass, and add that training as the contentView of this UITableViewCell, but I want to bypass the drawRect of the UITableViewCell, and do all my sketching there.

The first element I am doing is getting the present design situation so that we can attract to the screen, cutting to the rect that is handed down in drawRect:(CGRect)rect, and then based on whether this cellular is even, I am completing the complete rect with an almost dark colored, or a little light.

- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
 
    CGContextClipToRect(ctx, rect);
    //If even
    if (((self.tag % 2) == 0)) {
        CGContextSetFillColorWithColor(ctx, [UIColor colorWithWhite:0.1f alpha:1.f].CGColor);
    } else {
        CGContextSetFillColorWithColor(ctx, [UIColor colorWithWhite:0.15f alpha:1.f].CGColor);
    }
 
    CGContextFillRect(ctx, rect);

The next element I am going to decide is whether I want this textual content to be located in the cellular, and I am identifying this centered off whether there is an e-mail area or not.
//Vertically center our text, if no email
    BOOL isCentered = (self.email == nil);

And now for the beef of the drawRect technique. We evaluate the dimension firstName, attract it counteract from the eventually left by 5, and then attract lastName right after it. We also modify large we are sketching between those two.

 CGRect tempRect;
    CGFloat midY = CGRectGetMidY(rect);
    [[UIColor whiteColor] set];
    UIFont *defaultFont = [UIFont systemFontOfSize:16];
    CGSize size = [self.firstName sizeWithFont:defaultFont];
    if (isCentered == NO) {
        tempRect = CGRectMake(5, 0, size.width, size.height);
    } else {
        tempRect = CGRectMake(5, midY - size.height/2, size.width, size.height);
    }
    [self.firstName drawInRect:tempRect withFont:defaultFont];
 
    [[UIColor lightGrayColor] set];
    size = [self.lastName sizeWithFont:defaultFont];
    if (isCentered == NO) {
        tempRect = CGRectMake(CGRectGetMaxX(tempRect)+5, 0, size.width, size.height);
    } else {
        tempRect = CGRectMake(CGRectGetMaxX(tempRect)+5, midY - size.height/2, size.width, size.height);
    }
    [self.lastName drawInRect:tempRect withFont:defaultFont];

Next we discover out if cellphone actually prevails, and if so set large to red, and attract it to the right of lastName. We also have to create sure we are not sketching this outside our limitations, so we have a look at to see where the end is, and if it is outside, we plants it to 5 pixels from the end.

 if (self.phone != nil) {
        [[UIColor redColor] set];
        size = [self.phone sizeWithFont:defaultFont];
        CGFloat end = CGRectGetMaxX(tempRect) + size.width;
        if (end > rect.size.width) {
            size.width = CGRectGetMaxX(rect) - CGRectGetMaxX(tempRect) - 10; //-10 so that we get 5 from the end of last name, and 5 from the end of rect
        }
        if (isCentered == NO) {
            tempRect = CGRectMake(CGRectGetMaxX(rect) - size.width - 5, 0, size.width, size.height);
        } else {
            tempRect = CGRectMake(CGRectGetMaxX(rect) - size.width - 5, midY - size.height/2, size.width, size.height);
        }
        [self.phone drawInRect:tempRect withFont:defaultFont lineBreakMode:UILineBreakModeTailTruncation];
    }

And lastly if our email actually prevails attract it on the end eventually left.

if (self.email != nil) {
        [[UIColor blueColor] set];
        size = [self.email sizeWithFont:defaultFont];
        tempRect = CGRectMake(5, midY, size.width, size.height);
        [self.email drawInRect:tempRect withFont:defaultFont];
    }

I trust this allows you in making UITableViewCells for your own venture, and hopefully will let you begin to think about the opportunities.

To obtain the complete XCode venture, you may find it at: Making UITableViews look not so plain


0 comments:

Post a Comment

Powered by Blogger.
Twitter Delicious Facebook Digg Stumbleupon Favorites More