JXSegmentedTitleAttributeDataSource.swift 4.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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. deinit {
  19. widthForTitleClosure = nil
  20. }
  21. open override func preferredItemModelInstance() -> JXSegmentedBaseItemModel {
  22. return JXSegmentedTitleAttributeItemModel()
  23. }
  24. open override func reloadData(selectedIndex: Int) {
  25. super.reloadData(selectedIndex: selectedIndex)
  26. for index in 0..<attributedTitles.count {
  27. let itemModel = preferredItemModelInstance() as! JXSegmentedTitleAttributeItemModel
  28. preferredRefreshItemModel(itemModel, at: index, selectedIndex: selectedIndex)
  29. dataSource.append(itemModel)
  30. }
  31. }
  32. open override func preferredRefreshItemModel(_ itemModel: JXSegmentedBaseItemModel, at index: Int, selectedIndex: Int) {
  33. super.preferredRefreshItemModel(itemModel, at: index, selectedIndex: selectedIndex)
  34. guard let myItemModel = itemModel as? JXSegmentedTitleAttributeItemModel else {
  35. return
  36. }
  37. myItemModel.attributedTitle = attributedTitles[index]
  38. myItemModel.selectedAttributedTitle = selectedAttributedTitles?[index]
  39. myItemModel.textWidth = widthForItem(title: myItemModel.attributedTitle, selectedTitle: myItemModel.selectedAttributedTitle)
  40. myItemModel.titleNumberOfLines = titleNumberOfLines
  41. }
  42. open func widthForItem(title: NSAttributedString?, selectedTitle: NSAttributedString?) -> CGFloat {
  43. let attriText = selectedTitle != nil ? selectedTitle : title
  44. guard let text = attriText else {
  45. return 0
  46. }
  47. if widthForTitleClosure != nil {
  48. return widthForTitleClosure!(text)
  49. }else {
  50. 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
  51. return CGFloat(ceilf(Float(textWidth)))
  52. }
  53. }
  54. /// 因为该方法会被频繁调用,所以应该在`preferredRefreshItemModel( _ itemModel: JXSegmentedBaseItemModel, at index: Int, selectedIndex: Int)`方法里面,根据数据源计算好文字宽度,然后缓存起来。该方法直接使用已经计算好的文字宽度即可。
  55. open override func preferredSegmentedView(_ segmentedView: JXSegmentedView, widthForItemAt index: Int) -> CGFloat {
  56. var itemWidth: CGFloat = 0
  57. if itemContentWidth == JXSegmentedViewAutomaticDimension {
  58. let myItemModel = dataSource[index] as! JXSegmentedTitleAttributeItemModel
  59. itemWidth = myItemModel.textWidth + itemWidthIncrement
  60. }else {
  61. itemWidth = itemContentWidth + itemWidthIncrement
  62. }
  63. return itemWidth
  64. }
  65. //MARK: - JXSegmentedViewDataSource
  66. open override func registerCellClass(in segmentedView: JXSegmentedView) {
  67. segmentedView.collectionView.register(JXSegmentedTitleAttributeCell.self, forCellWithReuseIdentifier: "cell")
  68. }
  69. open override func segmentedView(_ segmentedView: JXSegmentedView, cellForItemAt index: Int) -> JXSegmentedBaseCell {
  70. let cell = segmentedView.dequeueReusableCell(withReuseIdentifier: "cell", at: index)
  71. return cell
  72. }
  73. }