didMoveToSuperview

视图管理与布局核心函数详解
本文深入探讨了iOS中视图管理的关键函数,包括didMoveToSuperview、didAddSubview等,详细解释了这些函数在视图生命周期中的作用及应用实例。

转载自:http://www.cnblogs.com/jay-dong/archive/2012/06/13/2547489.html

代码:

- (void)didMoveToSuperview

{

    if (!_navigationBar)

    {

        self.navigationBar = (UINavigationBar *)self.superview;

    }

}


  1. //当加入视图完成后调用  
  2. (void)didAddSubview:(UIView *)subview  
  3. //当视图移动完成后调用  
  4. (void)didMoveToSuperview  
  5. //当视图移动到新的WINDOW后调用  
  6. (void)didMoveToWindow  
  7. //在删除视图之后调用  
  8. (void)willRemoveSubview:(UIView *)subview  
  9. //当移动视图之前调用  
  10. (void)didMoveToSuperview:(UIView *)subview  
  11. //当视图移动到WINDOW之前调用  
  12. (void)didMoveToWindow  

import SnapKit final class TPMediaPlayerTooView : UIView, TPMediaViewRefreshDelegate { private(set) var clickAction : TPMediaPlayerClickAction?; private var viewBtns = [UIButton](); private var btnItems = [TPMediaPlayToolItem](); private let maxCnt : Int = 5; private lazy var contentView : UIScrollView = { let view = UIScrollView(); view.showsHorizontalScrollIndicator = false; view.showsVerticalScrollIndicator = false; view.backgroundColor = UIColor.clear; view.delegate = self; return view }() var isVertical : Bool = false { didSet { self.relaySubviews(views: self.viewBtns, isVertical: isVertical); } } var isInScreen: Bool = false { didSet { if (!isInScreen && !self.indicator.isHidden) { self.contentView.contentOffset = .zero; self.indicator.offset = 0; } } } var darkStyle : Bool = false; var enableIndicator : Bool = false; let indicatorWidth : CGFloat = 25; private(set) lazy var indicator : TPProgressIndicatorView = { let view = TPProgressIndicatorView(); view.clipsToBounds = true; view.backgroundColor = UIColor.tpbGrey//.tpbProgressBackground; view.isHidden = true; return view; }() init(items:[TPMediaPlayToolItem], downloadCenterViewModel: TPDownloadCenterViewModel? = nil, clickAction:@escaping TPMediaPlayerClickAction) { super.init(frame: CGRectZero); self.addSubview(self.contentView); self.contentView.snp.remakeConstraints { make in make.top.bottom.leading.trailing.equalToSuperview() }; self.clickAction = clickAction; self.downloadCenterViewModel = downloadCenterViewModel; self.downloadCenterViewModel?.reloadDownloadTaskNumberViewInToolViewAction = { [weak self](downloadTaskNumber: Int, failedTaskNumber: Int) in if let self = self { for (index, item) in items.enumerated() { if index >= 0 && index < self.viewBtns.count && item.type == .PlayBackDownload { reloadDownloadNumberSubScript(downloadTaskNumber: downloadTaskNumber, errorTaskNumber: failedTaskNumber); } } } } self.setItems(items: items); } var downloadCenterViewModel: TPDownloadCenterViewModel?; lazy var downloadingTaskNumberLabel: UILabel = { let downloadingTaskNumberLabel = UILabel(frame: .zero); downloadingTaskNumberLabel.textColor = UIColor.tpbTextWhite; downloadingTaskNumberLabel.font = .projectFont(ofSize: 12); downloadingTaskNumberLabel.textAlignment = .center; downloadingTaskNumberLabel.backgroundColor = .tpbRed; return downloadingTaskNumberLabel; }() lazy var downloadErrorImageView: UIImageView = { let imageView = UIImageView(frame: .zero) imageView.backgroundColor = .clear; imageView.image = UIImage(named: "playback_download_error"); return imageView; }() public func setItems(items:[TPMediaPlayToolItem]) { if self.btnItems.elementsEqual(items, by: { item1, item2 in return item1.type == item2.type }) { refresh(self.darkStyle); return } self.viewBtns.forEach({$0.removeFromSuperview()}); self.viewBtns.removeAll() self.btnItems.removeAll(); self.btnItems.append(contentsOf: items); for item in items { let btn = UIButton.init(type: .custom); btn.setImage(TPImageLiteral(item.normalImgUri), for: .normal); btn.imgUri = item.normalImgUri; btn.secondUri = item.secondUri; var img = TPImageLiteral(item.highImgUri) btn.setImage(img, for: .highlighted) img = TPImageLiteral(item.disableImgUri) btn.setImage(img, for: .disabled) btn.uriList = item.uriList; btn.tag = TPMediaPreviewUtils.kMediaPlayerSubviewBaseTag + item.type.rawValue; btn.addTarget(self, action: #selector(clickViewAction), for: .touchUpInside); // 如果有图片变化的需要在变化的时候再次修改 btn.accessibilityLabel = item.accessibilityLabel self.contentView.addSubview(btn); self.viewBtns.append(btn); } relaySubviews(views: self.viewBtns, isVertical: isVertical) refresh(self.darkStyle); reloadDownloadNumberSubScript(downloadTaskNumber: self.downloadCenterViewModel?.downloadingTaskNumber ?? 0, errorTaskNumber: self.downloadCenterViewModel?.failedTaskNumber ?? 0) } func reloadDownloadNumberSubScript(downloadTaskNumber: Int, errorTaskNumber: Int){ relayoutDownloadingSubviews() if downloadTaskNumber > errorTaskNumber { // 存在正在下载的任务,优先显示正在下载的任务数 downloadingTaskNumberLabel.isHidden = false; downloadErrorImageView.isHidden = true; downloadingTaskNumberLabel.text = String(format: "%d", downloadTaskNumber - errorTaskNumber); } else if downloadTaskNumber == errorTaskNumber && errorTaskNumber > 0 { // 没有正在下载任务,但是有下载失败任务,显示error图标 downloadErrorImageView.isHidden = false; downloadingTaskNumberLabel.isHidden = true; } else { downloadingTaskNumberLabel.isHidden = true; downloadErrorImageView.isHidden = true; } } private func relayoutDownloadingSubviews() { guard let downBtn = self.viewWithType(type: .PlayBackDownload) else { return } let blk = { (view:UIView, clip:Bool) in if (view.superview != downBtn) { view.removeFromSuperview() downBtn.addSubview(view) let downloadingTaskNumberLabelHW = 16.0; view.snp.remakeConstraints { make in make.leading.equalToSuperview().offset(30); make.top.equalToSuperview().offset(-6); make.width.height.equalTo(downloadingTaskNumberLabelHW); } if (clip) { view.layer.cornerRadius = downloadingTaskNumberLabelHW / 2.0; view.clipsToBounds = true; } } } blk(self.downloadErrorImageView, false); blk(self.downloadingTaskNumberLabel, true); } public func viewWithType(type:TPMediaPlayerFuncType) -> UIButton? { let tag = type.rawValue + TPMediaPreviewUtils.kMediaPlayerSubviewBaseTag; return self.viewWithTag(tag) as? UIButton; } public func view(types:[TPMediaPlayerFuncType]) -> [UIButton]? { var items : [UIButton] = [UIButton](); for type in types { guard let btn = self.viewWithType(type: type) else { continue } items.append(btn); } return items; } public func setEnable(enable:Bool) { if enable { self.viewBtns.forEach({$0.isEnabled = true}) } else { self.viewBtns.forEach({$0.isEnabled = false}) } } public func setEnable(type:TPMediaPlayerFuncType, enable:Bool) { self.viewWithType(type: type)?.isEnabled = enable; } public func hitInBtn(point:CGPoint, parent:UIView) -> Bool { if (self.isHidden) { return false; } for btn in self.viewBtns { let btnFrame = btn.convert(btn.bounds, to: parent); if (btnFrame.contains(point)) { self.clickViewAction(btn); return true } } return false; } public func itemTypes() -> [TPMediaPlayerFuncType] { var types : [TPMediaPlayerFuncType] = []; self.btnItems.forEach({ types.append($0.type) }); return types; } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() relaySubviews(views: self.viewBtns, isVertical: isVertical) } override func didMoveToSuperview() { super.didMoveToSuperview() if !self.isInScreen, self.indicator.superview == nil, let superView = self.superview { superView.addSubview(self.indicator) self.indicator.snp.remakeConstraints { make in make.centerX.equalTo(self); make.size.equalTo(CGSize(width: indicatorWidth, height: 2)); make.top.equalTo(self.snp.bottom).offset(5); } self.indicator.layer.cornerRadius = 1; } } override func removeFromSuperview() { super.removeFromSuperview() self.indicator.removeFromSuperview() } //MARK: - TPMediaViewRefreshDelegate func refresh(_ darkStyle: Bool) { self.darkStyle = darkStyle; self.viewBtns.forEach({ $0.refresh(darkStyle)}) self.indicator.isHidden = self.isHidden || !enableIndicator || darkStyle || self.viewBtns.count <= maxCnt; if (!self.indicator.isHidden) { self.handleScroll(self.contentView); } } //MARK: - Private private func relaySubviews(views:[UIButton], isVertical:Bool) { if (views.count <= 0) { return } var lastBtn : UIButton? = nil; var lrMargin : CGFloat = 0; let btnWH : CGFloat = 56.0; let btnH : CGFloat = 24.0; var itemMargin : CGFloat = 24.0; var vContH : CGFloat = 0; var minVMargin : CGFloat = isVertical && views.count > 3 ? 10 : 24; if (!isVertical) { if isInScreen { let itemCnt = views.count// > 5 ? 5 : views.count lrMargin = views.count <= 2 ? (CGRectGetWidth(self.frame) - btnWH * CGFloat(itemCnt)) / CGFloat(itemCnt + 1) : lrMargin let totalMargin = CGRectGetWidth(self.frame) - 2.0 * lrMargin - btnWH * CGFloat(itemCnt) itemMargin = totalMargin / CGFloat(max(1, (itemCnt - 1))) } else { if (CGFloat((views.count - 1) * 24) + CGFloat(views.count) * btnWH) > CGRectGetWidth(UIScreen.main.bounds) || views.count > 4 { let itemCnt : CGFloat = views.count > maxCnt ? (CGFloat(maxCnt) + 0.5) : CGFloat(views.count) lrMargin = views.count <= 2 ? (CGRectGetWidth(self.frame) - btnWH * CGFloat(itemCnt)) / CGFloat(itemCnt + 1) : lrMargin + 45 let totalMargin = CGRectGetWidth(self.frame) - 2.0 * lrMargin - btnWH * CGFloat(itemCnt) itemMargin = abs(totalMargin / CGFloat(max(1, itemCnt - (CGFloat(views.count) > itemCnt ? 0.5 : 1)))) } else { lrMargin = (CGRectGetWidth(self.frame) - (CGFloat((views.count - 1) * 24) + CGFloat(views.count) * btnWH)) / 2 } } } else { //横屏特殊处理 minVMargin = isVertical && views.count > 3 ? 0 : 24; let itemCnt = CGFloat(views.count); let vMargin : CGFloat = 32; let contH = max(0, itemCnt - 1) * itemMargin + (btnH + vMargin) * itemCnt; if contH > CGRectGetHeight(self.frame) { let totalMargin = CGRectGetHeight(self.frame) - 2.0 * lrMargin - btnH * CGFloat(itemCnt) itemMargin = totalMargin / CGFloat(max(1, (itemCnt - 1))) vContH = max(0, itemCnt - 1) * itemMargin + btnH * itemCnt lrMargin = max(minVMargin, (CGRectGetHeight(self.frame) - vContH) / 2) } else { itemMargin = itemMargin + vMargin vContH = max(0, itemCnt - 1) * itemMargin + (btnH + vMargin) * itemCnt; lrMargin = max(minVMargin, (CGRectGetHeight(self.frame) - vContH) / 2) } } for i in 0..<views.count { let btn = views[i]; guard let lastView = lastBtn else { btn.snp.remakeConstraints { make in if (isVertical) { make.top.equalToSuperview().offset(lrMargin / 2); make.centerX.equalToSuperview(); } else { make.leading.equalToSuperview().offset(lrMargin); make.centerY.equalToSuperview(); } make.width.equalTo(btnWH); make.height.lessThanOrEqualTo(btnWH); make.height.greaterThanOrEqualTo(btnH) }; lastBtn = btn; continue } btn.snp.remakeConstraints { make in make.width.height.equalTo(lastView); if (isVertical) { make.centerX.equalTo(lastView); make.top.equalTo(lastView.snp_bottomMargin).offset(itemMargin); if (i == views.count - 1) { make.bottom.equalToSuperview().offset(0 - itemMargin); } } else { make.centerY.equalTo(lastView); make.leading.equalTo(lastView.snp.trailing).offset(itemMargin); if (i == views.count - 1) { if (isVertical) { make.bottom.equalToSuperview(); } else { make.trailing.equalToSuperview().offset(0 - lrMargin); } } } } lastBtn = btn; } let itemCnt : CGFloat = CGFloat(self.viewBtns.count); if (isVertical) { self.contentView.contentSize = CGSizeMake(CGRectGetWidth(self.frame), max(CGRectGetHeight(self.frame) - 2 * minVMargin, vContH)) } else { let gap = enableIndicator && self.viewBtns.count > self.maxCnt ? 5.0 : 0.0; self.contentView.contentSize = CGSize(width: max(CGRectGetWidth(self.frame), lrMargin * 2 + max(0, itemCnt - 1) * itemMargin + itemCnt * btnWH) + gap, height: CGRectGetHeight(self.frame)); } } @objc private func clickViewAction(_ sender:UIButton) { guard let type = TPMediaPlayerFuncType(rawValue: sender.tag - TPMediaPreviewUtils.kMediaPlayerSubviewBaseTag) else { return } for item in self.btnItems { if (type == item.type) { guard let callback = item.clickAction else { self.clickAction?(type, false, nil); break } callback(type, false, nil); break; } } } } extension UIButton { @objc var textLable : UILabel { get { if let view = objc_getAssociatedObject(self, unsafeBitCast(#selector(setter: self.textLable), to: UnsafeRawPointer.self)) as? UILabel { return view; } let view = UILabel.init(); view.font = .projectFont(ofSize: 12) view.textColor = UIColor.tpbTextWhite; view.textAlignment = .center; view.backgroundColor = .clear; self.addSubview(view); view.snp.remakeConstraints { make in make.center.equalTo(self); }; self.textLable = view; return view; } set { objc_setAssociatedObject(self, unsafeBitCast(#selector(setter: textLable), to: UnsafeRawPointer.self), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } @objc var subTextLabel: UILabel { get { if let view = objc_getAssociatedObject(self, unsafeBitCast(#selector(setter: self.subTextLabel), to: UnsafeRawPointer.self)) as? UILabel { return view } let view = UILabel.init() view.font = .projectFont(ofSize: 12) view.textColor = .tpbRed view.textAlignment = .center view.backgroundColor = .clear self.addSubview(view) view.snp.remakeConstraints { make in make.centerX.equalTo(self) make.top.equalTo(self.snp.bottom) make.height.equalTo(15) }; self.subTextLabel = view return view; } set { objc_setAssociatedObject(self, unsafeBitCast(#selector(setter: subTextLabel), to: UnsafeRawPointer.self), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } } extension TPMediaPlayerTooView : UIScrollViewDelegate { func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { handleScroll(scrollView) } func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { handleScroll(scrollView, decelerate: decelerate) } func scrollViewDidScroll(_ scrollView: UIScrollView) { handleScroll(scrollView) } private func handleScroll(_ scrollView:UIScrollView, decelerate: Bool = false) { if (decelerate || self.indicator.isHidden) { return } let len = scrollView.contentSize.width - CGRectGetWidth(self.frame); let offset = scrollView.contentOffset.x; if (len >= 1) { self.indicator.offset = offset / len * (indicatorWidth - self.indicator.width); } } } final class TPProgressIndicatorView : UIView { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } var width : CGFloat = 11 { didSet { width != oldValue ? self.setNeedsDisplay() : nil; } } var color : UIColor = .tpbGreen { didSet { color != oldValue ? self.setNeedsDisplay() : nil } } var offset : CGFloat = 0 { didSet { if (offset != oldValue) { self.setNeedsDisplay() } } } init() { super.init(frame: .zero) } override func draw(_ rect: CGRect) { super.draw(rect) let pathH = CGRectGetHeight(rect); let path = UIBezierPath(rect: CGRect(x: offset, y: 0, width: width , height: pathH)) path.lineWidth = pathH; color.setStroke() path.stroke() } } 帮我修改整个代码,用方案2实现
10-15
import SnapKit final class TPMediaPlayerTooView : UIView, TPMediaViewRefreshDelegate { private(set) var clickAction : TPMediaPlayerClickAction?; private var viewBtns = [UIButton](); private var btnItems = [TPMediaPlayToolItem](); private let maxCnt : Int = 5; private lazy var contentView : UIScrollView = { let view = UIScrollView(); view.showsHorizontalScrollIndicator = false; view.showsVerticalScrollIndicator = false; view.backgroundColor = UIColor.clear; view.delegate = self; return view }() var isVertical : Bool = false { didSet { self.relaySubviews(views: self.viewBtns, isVertical: isVertical); } } var isInScreen: Bool = false { didSet { if (!isInScreen && !self.indicator.isHidden) { self.contentView.contentOffset = .zero; self.indicator.offset = 0; } } } var darkStyle : Bool = false; var enableIndicator : Bool = false; let indicatorWidth : CGFloat = 25; private(set) lazy var indicator : TPProgressIndicatorView = { let view = TPProgressIndicatorView(); view.clipsToBounds = true; view.backgroundColor = UIColor.tpbGrey//.tpbProgressBackground; view.isHidden = true; return view; }() init(items:[TPMediaPlayToolItem], downloadCenterViewModel: TPDownloadCenterViewModel? = nil, clickAction:@escaping TPMediaPlayerClickAction) { super.init(frame: CGRectZero); self.addSubview(self.contentView); self.contentView.snp.remakeConstraints { make in make.top.bottom.leading.trailing.equalToSuperview() }; self.clickAction = clickAction; self.downloadCenterViewModel = downloadCenterViewModel; self.downloadCenterViewModel?.reloadDownloadTaskNumberViewInToolViewAction = { [weak self](downloadTaskNumber: Int, failedTaskNumber: Int) in if let self = self { for (index, item) in items.enumerated() { if index >= 0 && index < self.viewBtns.count && item.type == .PlayBackDownload { reloadDownloadNumberSubScript(downloadTaskNumber: downloadTaskNumber, errorTaskNumber: failedTaskNumber); } } } } self.setItems(items: items); } var downloadCenterViewModel: TPDownloadCenterViewModel?; lazy var downloadingTaskNumberLabel: UILabel = { let downloadingTaskNumberLabel = UILabel(frame: .zero); downloadingTaskNumberLabel.textColor = UIColor.tpbTextWhite; downloadingTaskNumberLabel.font = .projectFont(ofSize: 12); downloadingTaskNumberLabel.textAlignment = .center; downloadingTaskNumberLabel.backgroundColor = .tpbRed; return downloadingTaskNumberLabel; }() lazy var downloadErrorImageView: UIImageView = { let imageView = UIImageView(frame: .zero) imageView.backgroundColor = .clear; imageView.image = UIImage(named: "playback_download_error"); return imageView; }() public func setItems(items:[TPMediaPlayToolItem]) { if self.btnItems.elementsEqual(items, by: { item1, item2 in return item1.type == item2.type }) { refresh(self.darkStyle); return } self.viewBtns.forEach({$0.removeFromSuperview()}); self.viewBtns.removeAll() self.btnItems.removeAll(); self.btnItems.append(contentsOf: items); for item in items { let btn = UIButton.init(type: .custom); btn.setImage(TPImageLiteral(item.normalImgUri), for: .normal); btn.imgUri = item.normalImgUri; btn.secondUri = item.secondUri; var img = TPImageLiteral(item.highImgUri) btn.setImage(img, for: .highlighted) img = TPImageLiteral(item.disableImgUri) btn.setImage(img, for: .disabled) btn.uriList = item.uriList; btn.tag = TPMediaPreviewUtils.kMediaPlayerSubviewBaseTag + item.type.rawValue; btn.addTarget(self, action: #selector(clickViewAction), for: .touchUpInside); // 如果有图片变化的需要在变化的时候再次修改 btn.accessibilityLabel = item.accessibilityLabel // 根据type判断是否添加背景圆角样式 switch item.type { case .LiveMultiPlay, .LiveQuality, .LivePlay, .LiveVolume, .LiveLandscape: // 屏幕上的五个按钮不添加 break default: // 其他类型添加背景圆角 btn.backgroundColor = UIColor.tpbBackgroundForPopup btn.layer.cornerRadius = 12 btn.clipsToBounds = true btn.imageEdgeInsets = UIEdgeInsets(top: 6, left: 0, bottom: 6, right: 0) } self.contentView.addSubview(btn); self.viewBtns.append(btn); } relaySubviews(views: self.viewBtns, isVertical: isVertical) refresh(self.darkStyle); reloadDownloadNumberSubScript(downloadTaskNumber: self.downloadCenterViewModel?.downloadingTaskNumber ?? 0, errorTaskNumber: self.downloadCenterViewModel?.failedTaskNumber ?? 0) } func reloadDownloadNumberSubScript(downloadTaskNumber: Int, errorTaskNumber: Int){ relayoutDownloadingSubviews() if downloadTaskNumber > errorTaskNumber { // 存在正在下载的任务,优先显示正在下载的任务数 downloadingTaskNumberLabel.isHidden = false; downloadErrorImageView.isHidden = true; downloadingTaskNumberLabel.text = String(format: "%d", downloadTaskNumber - errorTaskNumber); } else if downloadTaskNumber == errorTaskNumber && errorTaskNumber > 0 { // 没有正在下载任务,但是有下载失败任务,显示error图标 downloadErrorImageView.isHidden = false; downloadingTaskNumberLabel.isHidden = true; } else { downloadingTaskNumberLabel.isHidden = true; downloadErrorImageView.isHidden = true; } } private func relayoutDownloadingSubviews() { guard let downBtn = self.viewWithType(type: .PlayBackDownload) else { return } let blk = { (view:UIView, clip:Bool) in if (view.superview != downBtn) { view.removeFromSuperview() downBtn.addSubview(view) let downloadingTaskNumberLabelHW = 16.0; view.snp.remakeConstraints { make in make.leading.equalToSuperview().offset(30); make.top.equalToSuperview().offset(-6); make.width.height.equalTo(downloadingTaskNumberLabelHW); } if (clip) { view.layer.cornerRadius = downloadingTaskNumberLabelHW / 2.0; view.clipsToBounds = true; } } } blk(self.downloadErrorImageView, false); blk(self.downloadingTaskNumberLabel, true); } public func viewWithType(type:TPMediaPlayerFuncType) -> UIButton? { let tag = type.rawValue + TPMediaPreviewUtils.kMediaPlayerSubviewBaseTag; return self.viewWithTag(tag) as? UIButton; } public func view(types:[TPMediaPlayerFuncType]) -> [UIButton]? { var items : [UIButton] = [UIButton](); for type in types { guard let btn = self.viewWithType(type: type) else { continue } items.append(btn); } return items; } public func setEnable(enable:Bool) { if enable { self.viewBtns.forEach({$0.isEnabled = true}) } else { self.viewBtns.forEach({$0.isEnabled = false}) } } public func setEnable(type:TPMediaPlayerFuncType, enable:Bool) { self.viewWithType(type: type)?.isEnabled = enable; } public func hitInBtn(point:CGPoint, parent:UIView) -> Bool { if (self.isHidden) { return false; } for btn in self.viewBtns { let btnFrame = btn.convert(btn.bounds, to: parent); if (btnFrame.contains(point)) { self.clickViewAction(btn); return true } } return false; } public func itemTypes() -> [TPMediaPlayerFuncType] { var types : [TPMediaPlayerFuncType] = []; self.btnItems.forEach({ types.append($0.type) }); return types; } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() relaySubviews(views: self.viewBtns, isVertical: isVertical) } override func didMoveToSuperview() { super.didMoveToSuperview() if !self.isInScreen, self.indicator.superview == nil, let superView = self.superview { superView.addSubview(self.indicator) self.indicator.snp.remakeConstraints { make in make.centerX.equalTo(self); make.size.equalTo(CGSize(width: indicatorWidth, height: 2)); make.top.equalTo(self.snp.bottom).offset(5); } self.indicator.layer.cornerRadius = 1; } } override func removeFromSuperview() { super.removeFromSuperview() self.indicator.removeFromSuperview() } //MARK: - TPMediaViewRefreshDelegate func refresh(_ darkStyle: Bool) { self.darkStyle = darkStyle; self.viewBtns.forEach({ $0.refresh(darkStyle)}) self.indicator.isHidden = self.isHidden || !enableIndicator || darkStyle || self.viewBtns.count <= maxCnt; if (!self.indicator.isHidden) { self.handleScroll(self.contentView); } } //MARK: - Private private func relaySubviews(views:[UIButton], isVertical:Bool) { if (views.count <= 0) { return } var lastBtn : UIButton? = nil var lrMargin : CGFloat = 0 let btnWH : CGFloat = 130.0 let btnH : CGFloat = 60.0 var itemMargin : CGFloat = 15.0 var vContH : CGFloat = 0 var minVMargin : CGFloat = isVertical && views.count > 3 ? 10 : 24 // 竖屏状态下 if (!isVertical) { if isInScreen { let itemCnt = views.count// > 5 ? 5 : views.count lrMargin = views.count <= 2 ? (CGRectGetWidth(self.frame) - btnWH * CGFloat(itemCnt)) / CGFloat(itemCnt + 1) : lrMargin let totalMargin = CGRectGetWidth(self.frame) - 2.0 * lrMargin - btnWH * CGFloat(itemCnt) itemMargin = totalMargin / CGFloat(max(1, (itemCnt - 1))) } else { if (CGFloat((views.count - 1) * 24) + CGFloat(views.count) * btnWH) > CGRectGetWidth(UIScreen.main.bounds) || views.count > 4 { let itemCnt : CGFloat = views.count > maxCnt ? (CGFloat(maxCnt) + 0.5) : CGFloat(views.count) lrMargin = views.count <= 2 ? (CGRectGetWidth(self.frame) - btnWH * CGFloat(itemCnt)) / CGFloat(itemCnt + 1) : lrMargin + 15 let totalMargin = CGRectGetWidth(self.frame) - 2.0 * lrMargin - btnWH * CGFloat(itemCnt) itemMargin = abs(totalMargin / CGFloat(max(1, itemCnt - (CGFloat(views.count) > itemCnt ? 0.5 : 1)))) } else { lrMargin = (CGRectGetWidth(self.frame) - (CGFloat((views.count - 1) * 24) + CGFloat(views.count) * btnWH)) / 2 } } } else { //横屏特殊处理 for subView in contentView.subviews { if let btn = subView as? UIButton { btn.backgroundColor = UIColor.tpbCardDark } } minVMargin = isVertical && views.count > 3 ? 0 : 24; let itemCnt = CGFloat(views.count); let vMargin : CGFloat = 32; let contH = max(0, itemCnt - 1) * itemMargin + (btnH + vMargin) * itemCnt; if contH > CGRectGetHeight(self.frame) { let totalMargin = CGRectGetHeight(self.frame) - 2.0 * lrMargin - btnH * CGFloat(itemCnt) itemMargin = totalMargin / CGFloat(max(1, (itemCnt - 1))) vContH = max(0, itemCnt - 1) * itemMargin + btnH * itemCnt lrMargin = max(minVMargin, (CGRectGetHeight(self.frame) - vContH) / 2) } else { itemMargin = itemMargin + vMargin vContH = max(0, itemCnt - 1) * itemMargin + (btnH + vMargin) * itemCnt; lrMargin = max(minVMargin, (CGRectGetHeight(self.frame) - vContH) / 2) } } for i in 0..<views.count { let btn = views[i]; guard let lastView = lastBtn else { btn.snp.remakeConstraints { make in if (isVertical) { make.top.equalToSuperview().offset(lrMargin / 2); make.centerX.equalToSuperview(); } else { make.leading.equalToSuperview().offset(lrMargin); make.centerY.equalToSuperview(); } make.width.equalTo(btnWH); make.height.lessThanOrEqualTo(btnWH); make.height.greaterThanOrEqualTo(btnH) }; lastBtn = btn; continue } btn.snp.remakeConstraints { make in make.width.height.equalTo(lastView); if (isVertical) { make.centerX.equalTo(lastView); make.top.equalTo(lastView.snp_bottomMargin).offset(itemMargin); if (i == views.count - 1) { make.bottom.equalToSuperview().offset(0 - itemMargin); } } else { make.centerY.equalTo(lastView); make.leading.equalTo(lastView.snp.trailing).offset(itemMargin); if (i == views.count - 1) { if (isVertical) { make.bottom.equalToSuperview(); } else { make.trailing.equalToSuperview().offset(0 - lrMargin); } } } } lastBtn = btn; } let itemCnt : CGFloat = CGFloat(self.viewBtns.count); if (isVertical) { self.contentView.contentSize = CGSizeMake(CGRectGetWidth(self.frame), max(CGRectGetHeight(self.frame) - 2 * minVMargin, vContH)) } else { let gap = enableIndicator && self.viewBtns.count > self.maxCnt ? 5.0 : 0.0; self.contentView.contentSize = CGSize(width: max(CGRectGetWidth(self.frame), lrMargin * 2 + max(0, itemCnt - 1) * itemMargin + itemCnt * btnWH) + gap, height: CGRectGetHeight(self.frame)); } } @objc private func clickViewAction(_ sender:UIButton) { guard let type = TPMediaPlayerFuncType(rawValue: sender.tag - TPMediaPreviewUtils.kMediaPlayerSubviewBaseTag) else { return } for item in self.btnItems { if (type == item.type) { guard let callback = item.clickAction else { self.clickAction?(type, false, nil); break } callback(type, false, nil); break; } } } } extension UIButton { @objc var textLable : UILabel { get { if let view = objc_getAssociatedObject(self, unsafeBitCast(#selector(setter: self.textLable), to: UnsafeRawPointer.self)) as? UILabel { return view; } let view = UILabel.init(); view.font = .projectFont(ofSize: 12) view.textColor = UIColor.tpbTextWhite; view.textAlignment = .center; view.backgroundColor = .clear; self.addSubview(view); view.snp.remakeConstraints { make in make.center.equalTo(self); }; self.textLable = view; return view; } set { objc_setAssociatedObject(self, unsafeBitCast(#selector(setter: textLable), to: UnsafeRawPointer.self), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } @objc var subTextLabel: UILabel { get { if let view = objc_getAssociatedObject(self, unsafeBitCast(#selector(setter: self.subTextLabel), to: UnsafeRawPointer.self)) as? UILabel { return view } let view = UILabel.init() view.font = .projectFont(ofSize: 12) view.textColor = .tpbRed view.textAlignment = .center view.backgroundColor = .clear self.addSubview(view) view.snp.remakeConstraints { make in make.centerX.equalTo(self) make.top.equalTo(self.snp.bottom) make.height.equalTo(15) }; self.subTextLabel = view return view; } set { objc_setAssociatedObject(self, unsafeBitCast(#selector(setter: subTextLabel), to: UnsafeRawPointer.self), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC); } } } extension TPMediaPlayerTooView : UIScrollViewDelegate { func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { handleScroll(scrollView) } func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { handleScroll(scrollView, decelerate: decelerate) } func scrollViewDidScroll(_ scrollView: UIScrollView) { handleScroll(scrollView) } private func handleScroll(_ scrollView:UIScrollView, decelerate: Bool = false) { if (decelerate || self.indicator.isHidden) { return } let len = scrollView.contentSize.width - CGRectGetWidth(self.frame); let offset = scrollView.contentOffset.x; if (len >= 1) { self.indicator.offset = offset / len * (indicatorWidth - self.indicator.width); } } } final class TPProgressIndicatorView : UIView { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } var width : CGFloat = 11 { didSet { width != oldValue ? self.setNeedsDisplay() : nil; } } var color : UIColor = .tpbGreen { didSet { color != oldValue ? self.setNeedsDisplay() : nil } } var offset : CGFloat = 0 { didSet { if (offset != oldValue) { self.setNeedsDisplay() } } } init() { super.init(frame: .zero) } override func draw(_ rect: CGRect) { super.draw(rect) let pathH = CGRectGetHeight(rect); let path = UIBezierPath(rect: CGRect(x: offset, y: 0, width: width , height: pathH)) path.lineWidth = pathH; color.setStroke() path.stroke() } } 代码里关于按钮背景颜色的逻辑说一下
最新发布
10-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值