These two days the project is more idle, and in the spare time, try to implement the list control yourself. It took about a day from construction to preliminary completion, and now the simple functionality of the list is implemented, followed by the addition of cell reuse mechanisms, inertia features, and the ability to delete cells. The project code has been placed on GitHub, address: Https://github.com/wanglichun/CustomTableView.
Before implementing this, you need to understand how the list control works, as I've described in my previous blog, "list control implementation principle Resolution". Last year because of the project needs, using the Lua language to customize the double list (large list nested small list), this time instead of OBJC implementation, the idea of implementation is the same as before, just a change of language, so the speed is relatively fast. The following steps describe the implementation process.
Overall directory structure:
Directory Structure Description:
1, Tablewview directory: Cstableview (customtableview abbreviation) for the custom list control, Cstableviewcell for the list of cells;
2. Rootviewcontroller contains an example of a Cstableview test.
Step one: List cell Cstableviewcell implementation
To save time, I built the cell in a xib way, and the cell contains only header information, and if the user wants to implement a complex cell, they can inherit the Cstableviewcell extension cell. It is important to note that the cell layer does not handle touch events, but is passed to the parent control Cstableview processing.
The code is as follows:
Header file:
#import <UIKit/UIKit.h> @interface cstableviewcell:uiview+ (Cstableviewcell *) cstableviewcell;-(void) settitle :(NSString *) title; @end
Implementation file:
#import "CSTableViewCell.h" @interface Cstableviewcell () @property (weak, nonatomic) Iboutlet UILabel *titlelabel; @end @implementation cstableviewcell+ (Cstableviewcell *) cstableviewcell{ Nsarray *views = [[NSBundle MainBundle] loadnibnamed:@ "Cstableviewcell" Owner:nil Options:nil]; return views[0];} Passing an event to the parent control Cstableview processing-(BOOL) Pointinside: (cgpoint) point withevent: (uievent *) event{ return NO; -(void) Settitle: (NSString *) title{ self.titleLabel.text = title;}
Step two: List control Cstableview implementation
Key steps, the following code is easier to understand if you understand how the list works. It is important to note that there is a simple implementation list of the destruction creation form, and the cell reuse mechanism is not adopted, and there is time to fill up. Datasouce and delegate refer to Uitableviewdatasouce and uitableviewdelegate definitions, and only a few typical methods are currently defined.
Header file:
#import <UIKit/UIKit.h> @class cstableview; @class Cstableviewcell; @protocol cstableviewdatasource<nsobject > @required-(Nsinteger) TableView: (Cstableview *) TableView numberofrowsinsection: (Nsinteger) section;-( Cstableviewcell *) TableView: (Cstableview *) TableView Cellforrowatindexpath: (Nsindexpath *) Indexpath; @end @protocol Cstableviewdatadelegate <NSObject> @optional-(CGFloat) TableView: (Cstableview *) TableView Heightforrowatindexpath: (Nsindexpath *) Indexpath; @end @interface Cstableview:uiview@property (nonatomic,assign) ID <CSTableViewDataSource> DataSource, @property (nonatomic,assign) id<cstableviewdatadelegate> delegate;+ (Cstableview *) cstableview;-(void) reloaddata; @end
Implementation file:
#import "CSTableView.h" #import "CSTableViewCell.h" static const cgfloat kdefaultcellheight = 27.0f; @interface Cstableview () {Cgpoint _touchbeginpoint; Cgpoint _touchmovepoint; Cgpoint _touchendpoint; Nsinteger _numberofrows; CGFloat _top; Nsinteger _startindex; Nsinteger _endindex; CGFloat _starty; CGFloat _datatotalheight; Cstableview logic Height} @end @implementation cstableview+ (Cstableview *) cstableview{Nsarray *views = [[NSBundle mainBundle ] loadnibnamed:@ "Cstableview" Owner:nil Options:nil]; return views[0];} -(void) awakefromnib{//Can not be placed here, at this time delegate and DataSource are nil, previously made a mistake, and later moved to Layoutsubviews//[self Reloaddata];} -(void) layoutsubviews{[self reloaddata];} #pragma mark-touches events-(void) Updateuiwithmovedist: (cgfloat) movedist{//control Speed movedist = 0.2 * movedist; _top + = Movedist; if (_top < 0) {_top = 0; } if (_datatotalheight > Self.frame.size.height) {if (_top > _datatotalHeight-self.frame.size.height) {_top = _datatotalheight-self.frame.size.height; } [self UpdateUI]; }}-(void) Touchesbegan: (Nsset *) touches withevent: (uievent *) event{Uitouch *touch=[touches Anyobject]; _touchbeginpoint = [Touch locationinview:self];} -(void) touchesended: (Nsset *) touches withevent: (uievent *) event{Uitouch *touch=[touches Anyobject]; _touchendpoint = [Touch locationinview:self]; CGFloat movedist = _touchbeginpoint.y-_touchendpoint.y; [Self updateuiwithmovedist:movedist];} -(void) touchesmoved: (Nsset *) touches withevent: (uievent *) event{Uitouch *touch=[touches Anyobject]; Cgpoint point = [Touch locationinview:self]; CGFloat movedist = _touchbeginpoint.y-point.y; [Self updateuiwithmovedist:movedist];} #pragma mark-reloaddata//calculation display range-(void) calculatestartindexandendindex{_startindex =-1; CGFloat totalheight = 0; if ([Self.delegate respondstoselector: @selector (Tableview:heightforrowatindexpath:)]) {for (Nsinteger i = 0; i < _numberofrows; i++) {Nsindexpath *indexpath = [Nsindexpath indexpat Hforrow:i Insection:1]; CGFloat cellheight = [self.delegate tableview:self Heightforrowatindexpath:indexpath]; Totalheight + = Cellheight; if (Totalheight > _top && _startindex = =-1) {_starty = (totalheight-cellheight)-_top; _startindex = i; } if (Totalheight > _top + self.frame.size.height | | i = = _numberofrows-1) {_endindex = i; Break }}}else{for (Nsinteger i = 0; i < _numberofrows; i++) {totalheight + = Kdefaultcellheigh T if (Totalheight > _top && _startindex = =-1) {_starty = (totalheight-kdefaultcellheight)-_t Op _startindex = i; } if (Totalheight > _top + self.frame.size.height | | i = = _numberOfRows-1) {_endindex = i; Break }}}}//update ui-(void) updateui{[self calculatestartindexandendindex]; NSLog (@ "StartIndex =%ld", _startindex); NSLog (@ "EndIndex =%ld", _endindex); CGFloat totalheight = 0.0f; for (Nsinteger i = _startindex; I <= _endindex; i++) {//Create cell, if user does not have custom cell, generate a default cell Cstableviewcel L *cell; if ([Self.datasource respondstoselector: @selector (Tableview:cellforrowatindexpath:)]) {Nsindexpath *indexPath = [Nsindexpath indexpathforrow:i insection:1]; cell = [Self.datasource tableview:self Cellforrowatindexpath:indexpath]; }else{cell = [Cstableviewcell Cstableviewcell]; [Cell settitle:@ "Default cell"]; }//Set the location of the cell if ([Self.delegate respondstoselector: @selector (Tableview:heightforrowatindexpath:)]) {Nsindexpath *indexpath = [Nsindexpath indexpathforrow:i insection:1]; CGFloat cellheight = [self.delegate tableview:self Heightforrowatindexpath:indexpath]; Totalheight + = Cellheight; Cell.frame = CGRectMake (0, (totalheight-cellheight) + _starty, cell.frame.size.width, cell.frame.size.height); }else{cell.frame = CGRectMake (0, (i-_startindex) *kdefaultcellheight + _starty, cell.frame.size.width, cell. Frame.size.height); }//Add cell to Cstabelview [self addsubview:cell]; }}//reload the data, temporarily did not adopt the cell reuse mechanism, after the time after adding//delete data, call the function, reload ui-(void) reloaddata{for (UIView *subview in self.subviews) { [SubView Removefromsuperview]; } if ([Self.datasource respondstoselector: @selector (tableview:numberofrowsinsection:)]) {_numberofrows = [s Elf.datasource tableview:self Numberofrowsinsection:1]; }else{_numberofrows = 10;//display 10 data by default} _datatotalheight = 0.0f; if ([Self.delegate respondstoselector: @selector (Tableview:heightforrowatIndexpath:)] {for (Nsinteger i = 0; i < _numberofrows; i++) {Nsindexpath *indexpath = [Nsindexpath Indexpathforrow:i Insection:1]; CGFloat cellheight = [self.delegate tableview:self Heightforrowatindexpath:indexpath]; _datatotalheight + = Cellheight; }}else{_datatotalheight = Kdefaultcellheight * _numberofrows; }//Update UI [self UpdateUI];} @end
Step Three: Test cases
#import "RootViewController.h" #import "CSTableView.h" #import "CSTableViewCell.h" @interface Rootviewcontroller () <cstableviewdatasource, cstableviewdatadelegate> @property (nonatomic, strong) Cstableview *csTableView;@ End@implementation rootviewcontroller-(void) viewdidload {[Super viewdidload]; Self.cstableview = [Cstableview Cstableview]; Self.csTableView.dataSource = self; Self.csTableView.delegate = self; Self.csTableView.frame = CGRectMake (0, 0, self.csTableView.frame.size.width, self.csTableView.frame.size.height); [Self.view AddSubview:self.csTableView];} -(void) didreceivememorywarning {[Super didreceivememorywarning]; Dispose of any resources the can be recreated.} #pragma mark-cstableviewdatasource-(Nsinteger) TableView: (Cstableview *) TableView numberofrowsinsection: ( Nsinteger) section{return 50;} -(Cstableviewcell *) TableView: (Cstableview *) TableView Cellforrowatindexpath: (Nsindexpath *) indexpath{ Cstableviewcell *cell = [CstableviEwcell Cstableviewcell]; NSString *title = [[NSString alloc] initwithformat:@ "test data%ld", Indexpath.row]; [Cell Settitle:title]; return cell;} #pragma mark-cstableviewdatadelegate-(CGFloat) TableView: (Cstableview *) TableView Heightforrowatindexpath: ( Nsindexpath *) indexpath{if (Indexpath.row <) {return 20; }else if (indexpath.row >= && Indexpath.row <) {return 30; }else{return 40; }//return 27;} @end
iOS Development--Custom list controls