JXSegmentedTitleAttributeDataSource.swift 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. //
  2. // JXSegmentedTitleAttributeDataSource.swift
  3. // JXSegmentedView
  4. //
  5. // Created by jiaxin on 2019/1/2.
  6. // Copyright © 2019 jiaxin. All rights reserved.
  7. //
  8. import UIKit
  9. open class JXSegmentedTitleAttributeDataSource: JXSegmentedBaseDataSource {
  10. /// 富文本title数组
  11. open var attributedTitles = [NSAttributedString]()
  12. /// 选中时的富文本,可选。如果要使用确保count与attributedTitles一致。
  13. open var selectedAttributedTitles: [NSAttributedString]?
  14. /// 如果将JXSegmentedView嵌套进UITableView的cell,每次重用的时候,JXSegmentedView进行reloadData时,会重新计算所有的title宽度。所以该应用场景,需要UITableView的cellModel缓存titles的文字宽度,再通过该闭包方法返回给JXSegmentedView。
  15. open var widthForTitleClosure: ((NSAttributedString)->(CGFloat))?
  16. /// title的numberOfLines
  17. open var titleNumberOfLines: Int = 2
  18. open override func preferredItemModelInstance() -> JXSegmentedBaseItemModel {
  19. return JXSegmentedTitleAttributeItemModel()
  20. }
  21. open override func preferredItemCount() -> Int {
  22. return attributedTitles.count
  23. }
  24. open override func preferredRefreshItemModel(_ itemModel: JXSegmentedBaseItemModel, at index: Int, selectedIndex: Int) {
  25. super.preferredRefreshItemModel(itemModel, at: index, selectedIndex: selectedIndex)
  26. guard let myItemModel = itemModel as? JXSegmentedTitleAttributeItemModel else {
  27. return
  28. }
  29. myItemModel.attributedTitle = attributedTitles[index]
  30. myItemModel.selectedAttributedTitle = selectedAttributedTitles?[index]
  31. myItemModel.textWidth = widthForTitle(myItemModel.attributedTitle, selectedTitle: myItemModel.selectedAttributedTitle)
  32. myItemModel.titleNumberOfLines = titleNumberOfLines
  33. }
  34. open func widthForTitle(_ title: NSAttributedString?, selectedTitle: NSAttributedString?) -> CGFloat {
  35. let attriText = selectedTitle != nil ? selectedTitle : title
  36. guard let text = attriText else {
  37. return 0
  38. }
  39. if widthForTitleClosure != nil {
  40. return widthForTitleClosure!(text)
  41. }else {
  42. let textWidth = text.boundingRect(with: CGSize(width: CGFloat.infinity, height: CGFloat.infinity), options: NSStringDrawingOptions.init(rawValue: NSStringDrawingOptions.usesLineFragmentOrigin.rawValue | NSStringDrawingOptions.usesFontLeading.rawValue), context: nil).size.width
  43. return CGFloat(ceilf(Float(textWidth)))
  44. }
  45. }
  46. /// 因为该方法会被频繁调用,所以应该在`preferredRefreshItemModel( _ itemModel: JXSegmentedBaseItemModel, at index: Int, selectedIndex: Int)`方法里面,根据数据源计算好文字宽度,然后缓存起来。该方法直接使用已经计算好的文字宽度即可。
  47. open override func preferredSegmentedView(_ segmentedView: JXSegmentedView, widthForItemAt index: Int) -> CGFloat {
  48. var width: CGFloat = 0
  49. if itemWidth == JXSegmentedViewAutomaticDimension {
  50. let myItemModel = dataSource[index] as! JXSegmentedTitleAttributeItemModel
  51. width = myItemModel.textWidth + itemWidthIncrement
  52. }else {
  53. width = itemWidth + itemWidthIncrement
  54. }
  55. return width
  56. }
  57. //MARK: - JXSegmentedViewDataSource
  58. open override func registerCellClass(in segmentedView: JXSegmentedView) {
  59. segmentedView.collectionView.register(JXSegmentedTitleAttributeCell.self, forCellWithReuseIdentifier: "cell")
  60. }
  61. open override func segmentedView(_ segmentedView: JXSegmentedView, cellForItemAt index: Int) -> JXSegmentedBaseCell {
  62. let cell = segmentedView.dequeueReusableCell(withReuseIdentifier: "cell", at: index)
  63. return cell
  64. }
  65. }