日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

scrollview复用节点_利用ScrollView实现TableView效果(实现复用)

發布時間:2023/12/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 scrollview复用节点_利用ScrollView实现TableView效果(实现复用) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

TableView在iOS中的作用毋庸置疑,每一款App或多或少的都會使用到UITableView這個控件。作為iOS開發者,我們知道UITableView是繼承自UIScrollView的,那么UITableView是如何在繼承UIScrollView的基礎上實現的呢?今天我們就嘗試用代碼一步步分析,在UIScrollView的基礎上實現一個簡單的TableView。

** 在這里需要感謝各路大神的分享,這篇文章是參考Colin Eberhardt的一系列文章最后總結記錄于簡書,為自己的iOS之路添磚加瓦。**

創建自定義表格視圖

新建一個工程,這里命名為CustomTableView,新建一個類,繼承UIScrollView,類名為YFTableView:

1.png

仿照原生的UITableView為YFTableView添加一個簡便的@protocol:

@protocol YFTableViewDataSource

//表示表中的行數

- (NSInteger)numberOfRows;

//獲取給定的單元格

- (UIView *)cellForRow:(NSInteger)row;

@end

同時在YFTableView.h文件中添加dataSource:

@property (nonatomic,assign) id dataSource;

在YFTableView.m中實現以下方法,每個方法都有詳細的注釋:

//初始化

- (instancetype)initWithFrame:(CGRect)frame{

if (self = [super initWithFrame:frame]) {

self.backgroundColor = [UIColor clearColor];

}

return self;

}

//更新布局

- (void)layoutSubviews{

[super layoutSubviews];

[self refreshView];

}

//固定行高

const float SHC_ROW_HEIGHT = 50.0f;

- (void)refreshView{

//設置scrollView的高度

self.contentSize = CGSizeMake(self.bounds.size.width, [_dataSource numberOfRows] * SHC_ROW_HEIGHT);

//添加cell

for (int row = 0; row < [_dataSource numberOfRows]; row ++) {

//獲得cell

UIView * cell = [_dataSource cellForRow:row];

//每個cell的y坐標

float topEdgeForRow = row * SHC_ROW_HEIGHT;

//每個cell的位置

CGRect frame = CGRectMake(0, topEdgeForRow, self.frame.size.width, SHC_ROW_HEIGHT);

cell.frame = frame;

//添加到視圖

[self addSubview:cell];

}

}

#pragma mark - property setters

- (void)setDataSource:(id)dataSource{

_dataSource = dataSource;

[self refreshView];

}

新建一個類YFTableViewCell繼承自UITableViewCell:

2.png

回到ViewController.m創建YFTableView,并遵行協議實現簡單的TableView效果:

#import "ViewController.h"

#import "YFTableView.h"

#import "YFTableViewCell.h"

#define SCREEB_SIZE [UIScreen mainScreen].bounds.size

@interface ViewController ()

@property (nonatomic,strong) YFTableView * tableView;

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

self.tableView = [[YFTableView alloc] initWithFrame:CGRectMake(0, 20, SCREEB_SIZE.width, SCREEB_SIZE.height - 20)];

self.tableView.dataSource = self;

[self.view addSubview:self.tableView];

}

- (NSInteger)numberOfRows{

return 30;

}

- (UIView *)cellForRow:(NSInteger)row{

NSString * ident = @"cell";

YFTableViewCell * cell = [[YFTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:ident];

cell.textLabel.text = @"測試";

return cell;

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

}

@end

此時運行我們的程序,如下圖:

3.png

這時,我們在ScrollView的基礎上仿寫了一個簡單的TableView。但細心的我們會發現,仿寫的這個TableView存在一個很嚴重的問題,subViews沒有復用,在有限的手機內存里,這時非常可怕的。so,我們將改寫這個ScrollView,讓它擁有更棒的性能。

實現復用

首先我們需要一個表的結構來存儲單元格以供復用,因此我們需要在YFTableView.m中添加實例變量:

//可復用的一組單元格

NSMutableSet * _reuseCells;

現在,我們需要使RefreshView更加智能化。例如,屏幕滾動的單元格需要放入復用池_reuseCells中。此外,當出現空白時,需要從池中取出可復用的單元格填充空白處。

優化refreshView如下:

- (void)refreshView{

//設置scrollView的高度

self.contentSize = CGSizeMake(self.bounds.size.width, [_dataSource numberOfRows] * SHC_ROW_HEIGHT);

//刪除不再可見的細胞

for (UIView * cell in [self cellSubViews]) {

//滑出頂部的cell

if (cell.frame.origin.y + cell.frame.size.height < self.contentOffset.y) {

[self recycleCell:cell];

}

//底部沒有出現的cell

if (cell.frame.origin.y > self.contentOffset.y + self.frame.size.height) {

[self recycleCell:cell];

}

}

//確保每一行都有一個單元格

int firstVisibleIndex = MAX(0, floor(self.contentOffset.y / SHC_ROW_HEIGHT));

int lastVisibleIndex = MIN([_dataSource numberOfRows], firstVisibleIndex + 1 + ceil(self.frame.size.height / SHC_ROW_HEIGHT));

//添加cell

for (int row = firstVisibleIndex; row < lastVisibleIndex; row ++) {

//獲得cell

UIView * cell = [self cellForRow:row];

if (!cell) {

//如果cell不存在(沒有復用的cell),則創建一個新的cell添加到scrollView中

UIView * cell = [_dataSource cellForRow:row];

float topEdgeForRow = row * SHC_ROW_HEIGHT;

cell.frame = CGRectMake(0, topEdgeForRow, self.frame.size.width, SHC_ROW_HEIGHT);

[self insertSubview:cell atIndex:0];

}

}

}

//從滾動視圖返回一個單元格數組,self子視圖時單元格

- (NSArray *)cellSubViews{

NSMutableArray * cells = [[NSMutableArray alloc] init];

for (UIView * subView in self.subviews) {

if ([subView isKindOfClass:[YFTableViewCell class]]) {

[cells addObject:subView];

}

}

return cells;

}

//通過添加一組復用單元格,并從視圖中刪除它來循環單元格

- (void)recycleCell:(UIView *)cell{

[_reuseCells addObject:cell];

[cell removeFromSuperview];

}

//返回給定的單元格,如果不存在則返回nil

- (UIView *)cellForRow:(NSInteger)row{

float topEdgeForRow = row * SHC_ROW_HEIGHT;

for (UIView * cell in [self cellSubViews]) {

if (cell.frame.origin.y == topEdgeForRow) {

return cell;

}

}

return nil;

}

上面的代碼做了一個很好的回收單元格的工資,但是如果沒有提供一個機制來允許數據源將cell從池中拉出來,它將毫無用處。因此,我們需要在YFTableView.h中添加一下方法:

//出現一個可以重用的單元格

- (UIView *)dequeueReusableCell;

//注冊一個用作新單元格的類

- (void)registerClassForCells:(Class)cellClass;

在實現上述方法之前,您需要為YFTableView.m添加一個實例變量:

//表示單元格類型的類

Class _cellClass;

現在添加方法實現:

- (void)registerClassForCells:(Class)cellClass{

_cellClass = cellClass;

}

- (UIView *)dequeueReusableCell{

//首先從復用池獲取一個單元格

UIView * cell = [_reuseCells anyObject];

if (cell) {

NSLog(@"從池中返回單元格");

[_reuseCells removeObject:cell];

}

if (!cell) {

NSLog(@"創建新單單元格");

cell = [[_cellClass alloc] init];

}

return cell;

}

回到ViewController.m中添加注冊代碼:

[self.tableView registerClassForCells:[YFTableViewCell class]];

并在ViewController.m中替換代碼:

//YFTableViewCell * cell = [[YFTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:ident];

YFTableViewCell * cell = (YFTableViewCell *)[self.tableView dequeueReusableCell];

到此,我們就完成了一個簡易的TableView,但我們發現,這是一個固定高度的TableView,當我們需要修改行高時,需要在YFTableView.m里修改,這時非常不合理的。

為實現任意的行高,我們在YFTableViewDataSource中添加新的方法:

//返回表格的高度

- (CGFloat)rowHeight;

在YFTableView.m中實現該方法:

//單元格高度

- (CGFloat)getRowHeight{

CGFloat rowHeight = 50.0f;

@try {

if ([self.dataSource rowHeight]) { //自定義的高度

rowHeight = [self.dataSource rowHeight];

}

} @catch (NSException *exception) {//默認高度

rowHeight = 50.0f;

} @finally {

}

return rowHeight;

}

并且用該方法替換所有SHC_ROW_HEIGHT常量:

//self.contentSize = CGSizeMake(self.bounds.size.width, [_dataSource numberOfRows] * SHC_ROW_HEIGHT);

self.contentSize = CGSizeMake(self.bounds.size.width, [_dataSource numberOfRows] * [self getRowHeight]);

...

這時回到ViewController.m中,當實現rowHeight方法是,行高是該方法中設置的高度,當沒有實現該方法是,行高默認為50.0f:

//設置行高為100

- (CGFloat)rowHeight{

return 100;

}

此時運行程序如下:

4.png

我們發現表格沒有分割線,這時我們可以在YFTableViewCell.m中添加代碼實現分割線效果:

#import "YFTableViewCell.h"

@implementation YFTableViewCell{

CAGradientLayer * _gradientLayer;

}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{

if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

_gradientLayer = [CAGradientLayer layer];

_gradientLayer.colors = @[(id)[[ UIColor colorWithWhite:1.0f alpha:0.2f] CGColor],

(id)[[ UIColor colorWithWhite:1.0f alpha:0.1f] CGColor],

(id)[[ UIColor clearColor] CGColor],

(id)[[ UIColor colorWithWhite:0.0f alpha:0.1f] CGColor]];

_gradientLayer.locations = @[@0.00f,@0.01f,@0.95f,@1.00f];

[self.layer insertSublayer:_gradientLayer above:0];

}

return self;

}

- (void)layoutSubviews{

[super layoutSubviews];

_gradientLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);

}

- (void)awakeFromNib {

[super awakeFromNib];

}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

[super setSelected:selected animated:animated];

}

@end

到這里我們就實現了一個自定義的表格視圖。

我知道你會看到這里的,那誰還生氣嗎?

總結

以上是生活随笔為你收集整理的scrollview复用节点_利用ScrollView实现TableView效果(实现复用)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩欧美视频 | 男男黄网站 | 精品中文字幕一区二区 | 色噜噜日韩精品欧美一区二区 | www.国产色 | 99热麻豆 | 男女无遮挡免费视频 | 精品黄色av | 寂寞少妇让水电工爽hd | 狠狠a | 91久久久久久久久久久 | 欧美激情亚洲激情 | 欧美日韩h| 久草资源站 | 伊人久久大香线蕉av色婷婷色 | 亚洲精品乱码久久久久久蜜桃麻豆 | 狂躁美女大bbbbbb黑人 | 男ji大巴进入女人的视频 | 欧美特级黄色 | 91精品国产综合久久香蕉922 | 日本一区二区视频在线播放 | 胖女人做爰全过程 | 国产亚洲精品精品国产亚洲综合 | 少妇高潮一区二区三区99欧美 | 日韩欧美视频一区二区三区 | 亚洲五月网 | 欧美熟妇乱码在线一区 | 精品一区二区国产 | 高清乱码免费网 | 成人做受黄大片 | 中文字幕观看av | 日韩av一区二区三区四区 | 日本天堂免费a | 日本不卡视频一区二区三区 | 超碰97最新 | 成人福利在线视频 | 久久久综合久久 | 欧洲金发美女大战黑人 | 日韩精品高清在线 | 天天做夜夜操 | 一区二区视频免费看 | 亚洲欧美激情在线观看 | 国产又粗又黄又爽视频 | 免费日韩成人 | 中文字幕看片 | 天天做天天看 | 激情的网站 | 日日噜噜夜夜爽爽 | 免费av在线网站 | 爱情岛论坛自拍亚洲品质极速最新章 | 精品久久久久久久久久久aⅴ | 午夜日韩在线观看 | 国产精品无码一区二区三区在线看 | 久久尤物视频 | 亚洲专区免费 | 69久久精品无码一区二区 | 久婷婷| 一个色综合网站 | 国产真实夫妇交换视频 | 五月天中文字幕在线 | 日本少妇性生活 | 欧美性高潮视频 | 麻豆av导航 | 亚洲天堂男人网 | 亚洲九九视频 | 乱子伦一区二区三区 | 男女激情四射网站 | 色乱码一区二区三区在线男奴 | 鲁鲁久久 | 欧美一二三区在线观看 | 富二代成人短视频 | 调教奶奴 | 日日精| 国产成人综合在线观看 | 国产高清在线观看 | 夜夜高潮夜夜爽国产伦精品 | 国产高清一区 | 欧美精品一级二级三级 | 91cn.com| 中文在线8资源库 | 日韩色在线观看 | 91精品福利 | 免费网站污 | 成年人免费高清视频 | 青青草社区视频 | 欧美激情视频网 | 国产日韩欧美二区 | 国产精品成人久久久久 | 欧美性爱视频久久 | 亚洲成人福利在线 | 夜夜爽夜夜操 | 精品国产无码在线观看 | 又黄又湿的网站 | 啪在线视频 | 国产麻豆精品一区二区 | 一区二区欧美在线 | 日本少妇高潮 | 最新亚洲精品 | 男女啊啊啊视频 |