tableView的section和row

tableView的section和row,第1张

说起tableView,大家都不陌生,但是说起tableView的section和row,对其概念总是很模糊,什么不要线、设置线宽度、sectionHeader高度等等,有时还真得花一些时间去调试,总的说来,还是对tableView这些细节不太熟悉,下面我总结了一些小细节,希望对大家有所帮助

1一个section:两个cell之间的行间距无法改变

2多个section:能改变两个相邻section的相邻cell之间的高度,即区头和区尾高度

3cell默认是整个tableView都有分隔线的,即系统默认属性是

所以要想去掉分隔线,一般是

但是此时你会发现有内容的cell分隔线也没了,对于有内容的cell,我们一般是保留其分隔线的,不用急,往下看

4上面说了,系统默认是

如果我们不手动去调用separatorStyle这个属性,cell之间是有线的,这时可以设置heightForFooterInSection和heightForHeaderInSection,值得注意的是,如果最底部区尾高度设置为0,下面无内容的cell的分隔线是去不掉的,所以只要给区尾设置一个高度即可去掉分隔线,同时保留有内容的cell的分隔线,至于区头和区尾设置多高根据需求而定

5多个section有多个区头和区尾,如果设置区头过高,当你往上滑动时,区头也会往上移动,但是如果达到了tableView顶端,会发现第一个区头会停留在顶端,不再随cell移动而往上移动,但是你再往下拉,会随tableView滑动而下来,如果在自定义headerView时,如果想要这种效果,完全可以这么做

6不设置相邻区头和区尾高度或者设置为0,在UITableViewCellSeparatorStyleSingleLine情况下,两个section之间的高度默认是分割线的高度

7设置cell分隔线的宽度

宽度为0:

屏幕宽度:

小贴士:没有数据时,记得去掉分隔线哦,不然会有可能会有一条线在上面

1系统默认UITableViewCellSeparatorStyleSingleLine,但不会出现多余的分隔线

2如果不设置区头和区尾高度,或者设置为0,区头和区尾均为默认高度,大概为15

3区头或者区尾高度设置成很小貌似不行,比如0001,运行出来的效果还是差不多1的高度

4区头和区尾会一直随着tableView滚动,不会停留在顶部或底部

在有规律的列表中,我们可以有四种选择布局,假如数据源数组为array

1plain:返回section数为arraycount 每组一个row 可以精确的改变两个cell之间的高度 但是区头会停留在顶部,需要做判断解决第一个区头高度问题

2plain:返回section数为1 共arraycount个row 无法改变两个cell之间的高度

3grouped:返回section数为arraycount 每组一个row 即使区头和区尾之间高度给的再小,高度依然接近于1

4grouped:返回section数为1 共arraycount个row 无法改变两个cell之间的高度

具体哪种按需求去选择

复杂的tableView也可以借鉴上面四种去选择

1 webView加载H5链接,设置它为tableView的 headerView,下方评论信息用Cell加载展示。

2 在webView的回调方法webViewDidFinishLoad中获取网页内容高度,设置为webView的高度,重新将webView赋给tableView的headerView。

Tip: 将一个View赋值给UITableView的tableHeaderView时,不需要手动设置高度,HeaderView会自动使用View的高度。

像上面这样,类似的方法很多,无论是JS获取,还是contentSize获取,最后结果都难以获取到准确高度,并非方法不行,而是:

技术点:UILabel的自动换行,自动换行的同时要自适应Frame大小。UITableView的行高自适应内容,实时调整高度。实现方法:UILabel的自动换行获取UILabel的frame大小获取UILabel的字体大小获取UILabel的文本内容根据上面的3部分数据,计算文本显示区域大小根据4计算的大小,实时改变UILabel的framecode如下:NSStringlabelStr=@“你好,这是UILabel的自动换行测试内容,主要实现多行数据的自动换行,自适应不同行数的数据”;CGSizelabelSize={0,0};labelSize=[labelStrsizeWithFont:[UIFontsystemFontOfSize:14]constrainedToSize:CGSizeMake(2000,5000)lineBreakMode:UILineBreakModeWordWrap];//14为UILabel的字体大小//200为UILabel的宽度,5000是预设的一个高度,表示在这个范围内

在IOS开发中,很多时候项目需求会有点击某一行,展开cell下面的cell,在此点击会收起;

这种实现方式很多,个人这里随便推荐一种实现方式:

1、在数据转模型的model里面添加一个属性, @property ( assign , nonatomic ) BOOL isOpen; //是否展开

2、在对应的tableView层,- ( nullable UIView)tableView:(UITableView)tableView viewForHeaderInSection:(NSInteger)section;方法下面生成View,并未其添加点击事件;点击事件方法如下:

在对应的tableView的dataSource方法中:

以及- (UITableViewCell)tableView:(UITableView)tableView cellForRowAtIndexPath:(NSIndexPath)indexPath{  if ( self dataList[indexPathsection]isOpen) {

  if ( self dataList[indexPathsection]isOpen) {

//设置展开的cell

}else{

//设置没有展开的cell;

}}

实现的方法和tableBView差不多,实现他的几个代理方法:

解释一下:传进来的item:代表他给你的model,根据这个model可以去获取上级model: clickpackagesModelpackageModel = [treeViewparentForItem:model];

同样可以根据model获取相应的cell: clickPackageCellpackagecell01 = (clickPackageCell)[treeViewcellForItem:model];

有了上面两个方法,基本就能玩转三级展开和收起;

对于三级展开,大家还有什么好的想法亦或者好的框架没?欢迎补充

先看以下的效果图

- (void)tableView:(UITableView)tableViewwillDisplayCell:(UITableViewCell)cellforRowAtIndexPath:(NSIndexPath)indexPath {

    // 圆角角度

      CGFloatradius =10f;

      // 设置cell 背景色为透明

      cellbackgroundColor = UIColorclearColor;

      // 创建两个layer

      CAShapeLayernormalLayer = [[CAShapeLayeralloc]init];

      CAShapeLayerselectLayer = [[CAShapeLayeralloc]init];

      // 获取显示区域大小

      CGRectbounds =CGRectInset(cellbounds,10,0);

      // 获取每组行数

      NSIntegerrowNum = [tableViewnumberOfRowsInSection:indexPathsection];

      // 贝塞尔曲线

      UIBezierPathbezierPath =nil;

    //考虑一行和多行的情况,若行数为1,则这个cell的每个角都是圆角,否则第一行的左上和右上为圆角,最后一行的左下和右下为圆角

    if(rowNum ==1) {

        // 一组只有一行(四个角全部为圆角)

        bezierPath = [UIBezierPathbezierPathWithRoundedRect:bounds

                                           byRoundingCorners:UIRectCornerAllCorners

                                                 cornerRadii:CGSizeMake(radius, radius)];

    }else{

        if(indexPathrow==0) {

            // 每组第一行(添加左上和右上的圆角)

            bezierPath = [UIBezierPathbezierPathWithRoundedRect:bounds

                                               byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)

                                                     cornerRadii:CGSizeMake(radius, radius)];

        }else if(indexPathrow== rowNum -1) {

            // 每组最后一行(添加左下和右下的圆角)

            bezierPath = [UIBezierPathbezierPathWithRoundedRect:bounds

                                               byRoundingCorners:(UIRectCornerBottomLeft|UIRectCornerBottomRight)

                                                     cornerRadii:CGSizeMake(radius, radius)];

        }else{

            // 每组不是首位的行不设置圆角

            bezierPath = [UIBezierPathbezierPathWithRect:bounds];

        }

    }

    //将贝塞尔曲线的路径赋值给图层,并将图层添加到view

    // 把已经绘制好的贝塞尔曲线路径赋值给图层,然后图层根据path进行图像渲染render

    normalLayerpath= bezierPathCGPath;

    selectLayerpath= bezierPathCGPath;

    UIViewnomarBgView = [[UIViewalloc]initWithFrame:bounds];

    // 设置填充颜色

    normalLayerfillColor = [UIColor colorWithWhite:095 alpha:10]CGColor;

    // 添加图层到nomarBgView中

    [nomarBgViewlayerinsertSublayer:normalLayeratIndex:0];

    nomarBgViewbackgroundColor = UIColorclearColor;

    cellbackgroundView= nomarBgView;

    //圆角显示就完成了,但是如果没有取消cell的点击效果,会出现一个灰色的长方形的形状,再用上面创建的selectLayer给cell添加一个selectedBackgroundView

    UIViewselectBgView = [[UIViewalloc]initWithFrame:bounds];

    selectLayerfillColor = [UIColor colorWithWhite:095 alpha:10]CGColor;

    [selectBgViewlayerinsertSublayer:selectLayeratIndex:0];

    selectBgViewbackgroundColor = UIColorclearColor;

    cellselectedBackgroundView= selectBgView;

}

 func tableView(_tableView:UITableView, willDisplay cell:UITableViewCell, forRowAt indexPath:IndexPath) {

        // 圆角角度

        let radius =calculate(w:350)

        // 设置cell 背景色为透明

        cellbackgroundColor = UIColorclear

        // 创建两个layer

        let normalLayer =CAShapeLayer()

        let selectLayer =CAShapeLayer()

        // 获取显示区域大小

        let bounds = cellboundsinsetBy(dx:100, dy:0)

        // 获取每组行数

        let rowNum = tableViewnumberOfRows(inSection: indexPathsection)

        // 贝塞尔曲线

        var bezierPath:UIBezierPath

        if(rowNum==1) {

            // 一组只有一行(四个角全部为圆角)

            bezierPath =UIBezierPath(roundedRect: bounds, byRoundingCorners: allCorners, cornerRadii:CGSize(width: radius, height: radius))

        }else{

            if(indexPathrow==0) {

                // 每组第一行(添加左上和右上的圆角)

                bezierPath =UIBezierPath(roundedRect: bounds, byRoundingCorners: [UIRectCornertopLeft,UIRectCornertopRight], cornerRadii:CGSize(width: radius, height: radius))

            }elseif(indexPathrow==rowNum-1) {

                // 每组最后一行(添加左下和右下的圆角)

                bezierPath =UIBezierPath(roundedRect: bounds, byRoundingCorners: [UIRectCornerbottomLeft,UIRectCornerbottomRight], cornerRadii:CGSize(width: radius, height: radius))

            }else{

                // 每组不是首位的行不设置圆角

                bezierPath =UIBezierPath(rect: bounds)

            }

        }

        // 把已经绘制好的贝塞尔曲线路径赋值给图层,然后图层根据path进行图像渲染render

        normalLayerpath= bezierPathcgPath;

        selectLayerpath= bezierPathcgPath;

        let nomarBgView =UIView(frame: bounds);

        // 设置填充颜色

        normalLayerfillColor=UIColorwhitecgColor

        // 添加图层到nomarBgView中

        nomarBgViewlayerinsertSublayer(normalLayer, at:0)

        nomarBgViewbackgroundColor=UIColorclear

        cellbackgroundView= nomarBgView

        let selectBgView =UIView(frame: bounds)

        selectLayerfillColor=  UIColorwhitecgColor

        selectBgViewlayerinsertSublayer(selectLayer, at:0)

        selectBgViewbackgroundColor=UIColorclear

        cellselectedBackgroundView= selectBgView

    }

_deltaTimes = [NSMutableArray array]; NSInteger deltaMaxTimes = [selfvideoModeldeltaMaxTimes integerValue];

NSInteger deltaMinTimes = [selfvideoModeldeltaMinTimes integerValue];

for (NSInteger i = deltaMaxTimes; i >= deltaMinTimes; i--) {

[_deltaTimes addObject:[NSString stringWithFormat:@"%d", (int)i]];

}

}

return _deltaTimes;

}

#pragma mark - 获取视频状态

#pragma mark - <UITableViewDelegate,UITableViewDataSource>

- (NSInteger)numberOfSectionsInTableView:(UITableView )tableView {

return selftitlescount;

}

- (NSInteger)tableView:(UITableView )tableView numberOfRowsInSection:(NSInteger)section {

NSArray dataArray = selfdataArray[section];

return dataArraycount;

}

- (UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath )indexPath {

NSArray dataArray = selfdataArray[indexPathsection];

NSString text = dataArray[indexPathrow];

UITableViewCell cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];

if (!cell) {

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"];

}

celltextLabeltext = text;

cellaccessoryType = UITableViewCellAccessoryNone;

cellselectionStyle = UITableViewCellSelectionStyleNone;

if (indexPathsection == 0) {

if ([text isEqualToString:selfcurrentState]) {

cellaccessoryType = UITableViewCellAccessoryCheckmark;

}

} else if (indexPathsection == 1) {

if ([text isEqualToString:[NSString stringWithFormat:@"%d", selfdeltaTimesIndex]]) {

cellaccessoryType = UITableViewCellAccessoryCheckmark;

}

}

return cell;

}

- (NSString )tableView:(UITableView )tableView titleForHeaderInSection:(NSInteger)section {

return selftitles[section];

}

- (void)tableView:(UITableView )tableView didSelectRowAtIndexPath:(NSIndexPath )indexPath {

// 1取消所有的打钩

[tableView visibleCells];

[tableViewvisibleCells enumerateObjectsUsingBlock:^(UITableViewCell _Nonnull obj, NSUInteger idx, BOOL _Nonnull stop) {

objaccessoryType = UITableViewCellAccessoryNone;

}];

// 2打钩当前选中的行

UITableViewCell cell = [tableView cellForRowAtIndexPath:indexPath];

cellaccessoryType = UITableViewCellAccessoryCheckmark;

NSArray dataArray = selfdataArray[indexPathsection];

NSString text = dataArray[indexPathrow];

if (indexPathsection == 0) {

// 3发送状态指令

[self sendStateCommand:text];

} else if (indexPathsection == 1) {

selfdeltaTimesIndex = [text integerValue];

// 4发送调档指令

[self sendDeltaCommand:selfdeltaTimesIndex];

}

}

#pragma mark - 按钮点击事件

- (void)backButtonClicked {

[selfnavigationController popViewControllerAnimated:YES];

}

#pragma mark - 发送状态指令

- (void)sendStateCommand:(NSString )state

代理模式是一种消息传递方式,一个完整的代理模式包括:委托对象、代理对象和协议

协议:用来指定代理双方可以做什么,必须做什么。

委托对象:根据指定的协议,指定代理去完成什么功能。

代理对象:根据指定的协议,完成委托方需要实现的功能。

从上图中可以看到三方之间的关系,在实际应用中通过协议来规定代理双方的行为,协议中的内容一般都是方法列表,当然也可以定义属性。

协议是公共的定义,如果只是某个类使用,我们常做的就是写在某个类中。如果是多个类都是用同一个协议,建议创建一个Protocol文件,在这个文件中定义协议。遵循的协议可以被继承,例如我们常用的 UITableView ,由于继承自 UIScrollView 的缘故,所以也将 UIScrollViewDelegate 继承了过来,我们可以通过代理方法获取 UITableView 偏移量等状态参数。

协议只能定义公用的一套接口,类似于一个约束代理双方的作用。但不能提供具体的实现方法,实现方法需要代理对象去实现。协议可以继承其他协议,并且可以继承多个协议,在iOS中对象是不支持多继承的,而协议可以多继承。

协议有两个修饰符 @optional 和 @required ,创建一个协议如果没有声明,默认是 @required 状态的。这两个修饰符只是约定代理是否强制需要遵守协议,如果 @required 状态的方法代理没有遵守,会报一个**的警告,只是起一个约束的作用,没有其他功能。

无论是 @optional 还是 @required ,在委托方调用代理方法时都需要做一个判断,判断代理是否实现当前方法,否则会导致崩溃。

在iOS中代理的本质就是代理对象内存的传递和 *** 作,我们在委托类设置代理对象后,实际上只是用一个id类型的指针将代理对象进行了一个弱引用。委托方让代理方执行 *** 作,实际上是在委托类中向这个id类型指针指向的对象发送消息,而这个id类型指针指向的对象,就是代理对象。

通过上面这张图我们发现,其实委托方的代理属性本质上就是代理对象自身,设置委托代理就是代理属性指针指向代理对象,相当于代理对象只是在委托方中调用自己的方法,如果方法没有实现就会导致崩溃。从崩溃的信息上来看,就可以看出来是代理方没有实现协议中的方法导致的崩溃。

而协议只是一种语法,是声明委托方中的代理属性可以调用协议中声明的方法,而协议中方法的实现还是有代理方完成,而协议方和委托方都不知道代理方有没有完成,也不需要知道怎么完成。

由于代理对象使用强引用指针,引用创建的委托方对象,并且成为委托对象的代理。这就会导致委托对象的delegate属性强引用代理对象,导致循环引用的问题,最终两个对象都无法正常释放。

我们将委托对象的delegate属性,设置为弱引用属性。

weak 和 assign 是一种“非拥有关系”的指针,通过这两种修饰符修饰的指针变量,都不会改变被引用对象的引用计数。但是在一个对象被释放后, weak 会自动将指针指向 nil ,而 assign 则不会。在iOS中,向 nil 发送消息时不会导致崩溃的,所以 assign 就会导致野指针的错误 unrecognized selector sent to instance 。

所以我们如果修饰代理属性,还是用 weak 修饰,比较安全。

以上就是关于tableView的section和row全部的内容,包括:tableView的section和row、webdeviceagent无法获得webview内容ios、如何计算uilabel里面文字的行数等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9709632.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存