热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:基于UILabel的动态UICollectionView标头大小

篇首语:本文由编程笔记#小编为大家整理,主要介绍了基于UILabel的动态UICollectionView标头大小相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了基于UILabel的动态UICollectionView标头大小相关的知识,希望对你有一定的参考价值。



我已经阅读了一些关于向UICollectionView添加标题的帖子。在Swift的ios 7+应用程序中,我正在尝试添加一个带有UILabel的标头,其高度应根据UILabel的高度进行调整。 UILabel的行= 0。

我已经使用AutoLayout在IB中设置了标题

ViewController实现了UICollectionViewDelegate, UICollectionViewDataSource。我没有为标题设置自定义类,但我正在使用这两个函数:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
//description is a String variable defined in the class
let size:CGSize = (description as NSString).boundingRectWithSize(CGSizeMake(CGRectGetWidth(collectionView.bounds) - 20.0, 180.0), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont(name: "Helvetica Neue", size: 16.0)], context: nil).size
return CGSizeMake(CGRectGetWidth(collectionView.bounds), ceil(size.height))
}
func collectionView(collectionView: UICollectionView!, viewForSupplementaryElementOfKind kind: String!, atIndexPath indexPath: NSIndexPath!) -> UICollectionReusableView! {
var reusableview:UICollectiOnReusableView= UICollectionReusableView()
if (kind == UICollectionElementKindSectionHeader) {
//listCollectionView is an @IBOutlet UICollectionView defined at class level, using collectionView crashes
reusableview = listCollectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "ListHeader", forIndexPath: indexPath) as UICollectionReusableView
let label = reusableview.viewWithTag(200) as UILabel //the UILabel within the header is tagged with 200
label.text = description //description is a String variable defined in the class
}
}
return reusableview
}

显示文本似乎有效,但高度计算似乎不起作用(见下面的截图)。另外,我不认为我可以通过collectionView...referenceSizeForHeaderInSection函数访问UILabel。有关如何正确计算CGSize的任何建议?


答案

这就是我做的方式:

let labels = [
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ac lorem enim. Curabitur rhoncus efficitur quam, et pretium ipsum. Nam eu magna at velit sollicitudin fringilla nec nec nisi. Quisque nec enim et ipsum feugiat pretium. Vestibulum hendrerit arcu ut ipsum gravida, ut tincidunt justo pellentesque. Etiam lacus ligula, aliquet at lorem vel, ullamcorper commodo turpis. Nullam commodo sollicitudin mauris eu faucibus.",
"Lorem ipsum dolor",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ac lorem enim. Curabitur rhoncus efficitur quam, et pretium ipsum. Nam eu magna at velit sollicitudin fringilla nec nec nisi. Quisque nec enim et ipsum feugiat pretium."]

基本思想是创建一个相同的UILabel到将在节标题中显示的那个。该标签将用于在referenceSizeForHeaderInSection方法中设置标题的所需大小。

我在我的label子类(UICollectionReusableView)中有一个名为MyHeaderCollectionReusableView的标签出口,我通过在故事板中分配它来将其用于我的节标题视图(将“MyHeader”设置为剖面视图的重用标识符)。提到的标签对部分标题边框具有水平和垂直空间限制,以便正确地自动布局。

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 3
}
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
let headerView =
collectionView.dequeueReusableSupplementaryViewOfKind(kind,
withReuseIdentifier: "MyHeader",
forIndexPath: indexPath)
as MyHeaderCollectionReusableView
headerView.label.text = labels[indexPath.section]
return headerView
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
// that -16 is because I have 8px for left and right spacing constraints for the label.
let label:UILabel = UILabel(frame: CGRectMake(0, 0, collectionView.frame.width - 16, CGFloat.max))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.ByWordWrapping
//here, be sure you set the font type and size that matches the one set in the storyboard label
label.fOnt= UIFont(name: "Helvetica", size: 17.0)
label.text = labels[section]
label.sizeToFit()
// Set some extra pixels for height due to the margins of the header section.
//This value should be the sum of the vertical spacing you set in the autolayout constraints for the label. + 16 worked for me as I have 8px for top and bottom constraints.
return CGSize(width: collectionView.frame.width, height: label.frame.height + 16)
}

另一答案

就像提问者一样,我有一个UICollectionView,其中包含一个带有单个标签的标题,我希望它的高度可以变化。我创建了UILabel的扩展,以测量具有已知宽度的多线标签的高度:

public extension UILabel {
public class func size(withText text: String, forWidth width: CGFloat) -> CGSize {
let measurementLabel = UILabel()
measurementLabel.text = text
measurementLabel.numberOfLines = 0
measurementLabel.lineBreakMode = .byWordWrapping
measurementLabel.translatesAutoresizingMaskIntoCOnstraints= false
measurementLabel.widthAnchor.constraint(equalToConstant: width).isActive = true
let size = measurementLabel.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
return size
}
}

注意:以上是Swift 3语法。

然后我实现了UICollectionViewDelegateFlowLayout的头大小方法:

extension MyCollectionViewController : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
let text = textForHeader(inSection: section)
var size = UILabel.size(withAttributedText: text, forWidth: collectionView.frame.size.width)
size.height = size.height + 16
return size
}
}

计算标题大小的工作委托给上面的UILabel扩展。 +16是一个实验得出的固定偏移量(8 + 8),它基于边距,可以通过编程方式获得。

标头回调中所需的只是设置文本:

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionElementKindSectionHeader, let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerIdentifier, for: indexPath) as? MyCollectionHeader {
let text = textForHeader(inSection: section)
headerView.label.text = text
return headerView
}
return UICollectionReusableView()
}

另一答案

我们的想法是在内存中有一个模板头实例,以便在创建结果头视图之前计算所需的高度。您应该将节标题视图移动到单独的.nib文件,设置所有自动布局约束并在viewDidLoad方法中实例化模板,如下所示:

class MyViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
@IBOutlet var collectionView : UICollectionView?
private var _templateHeader : MyHeaderView
override func viewDidLoad() {
super.viewDidLoad()
let nib = UINib(nibName: "HeaderView", bundle:nil)
self.collectionView?.registerNib(nib, forCellWithReuseIdentifier: "header_view_id")
_templateHeader = nib.instantiateWithOwner(nil, options:nil)[0] as! MyHeaderView
}
}

然后,您将能够在流布局委托方法中计算标题大小(在我的示例中为高度):

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
_templateHeader.lblTitle.text = "some title here"
_templateHeader.lblDescription.text = "some long description"
_templateHeader.setNeedsUpdateConstraints();
_templateHeader.updateConstraintsIfNeeded()
_templateHeader.setNeedsLayout();
_templateHeader.layoutIfNeeded();
let computedSize = _templateHeader.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
return CGSizeMake(collectionView.bounds.size.width, computedSize.height);
}

然后一如既往地创建并返回常规标题视图,因为您已经在流布局委托方法中计算了它的大小:

func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "header_view_id", forIndexPath: indexPath) as! MyHeaderView
headerView.lblTitle.text = "some title here"
headerView.lblDescription.text = "some long description"
headerView.setNeedsUpdateConstraints()
headerView.updateConstraintsIfNeeded()
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
return headerView
default:
assert(false, "Unexpected kind")
}
}

忘了说一个重要的时刻 - 你的标题视图应该在其contentView上有一个自动布局约束,以适应集合视图宽度(加上或减去所需的边距)。


另一答案

我们可以简单地使用现有的标签来计算拟合大小,而不是从多个答案中显示的代码重新创建新标签。

你的UICollectionViewDelegate的代码:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
// We get the actual header view
let header = self.collectionView(collectionView, viewForSupplementaryElementOfKind: UICollectionView.elementKindSectionHeader, at: IndexPath(row: 0, section: section)) as! MyHeaderView
// We ask the label what size it takes (eventually accounting for horizontal margins)
var size = header.myLabel.sizeThatFits(CGSize(width: collectionView.frame.width - horizontalMargins, height: .greatestFiniteMagnitude))
// We eventually account for vertical margins

推荐阅读
  • 本文介绍了一款名为TimeSelector的Android日期时间选择器,采用了Material Design风格,可以在Android Studio中通过gradle添加依赖来使用,也可以在Eclipse中下载源码使用。文章详细介绍了TimeSelector的构造方法和参数说明,以及如何使用回调函数来处理选取时间后的操作。同时还提供了示例代码和可选的起始时间和结束时间设置。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 本文介绍了如何使用elementui分页组件进行分页功能的改写,只需一行代码即可调用。通过封装分页组件,避免在每个页面都写跳转请求的重复代码。详细的代码示例和使用方法在正文中给出。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
author-avatar
离开一场爱的风雪
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有