我现在想实现这样的:首先在所有的水平阶段(竖屏)保持现在的所有逻辑不变,然后在垂直(横屏)状态下,修改原来的布局逻辑,将除了按钮为item.type为case .LiveMultiPlay, .LiveQuality, .LivePlay, .LiveVolume, .LiveLandscape这五个按钮之外的需要用到的按钮排成双列显示(跟填充背景色的按钮一样,只有填充背景色按钮的才在横屏时排双列显示),请帮我修改整个代码,一次成功。
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) {
// 恢复竖屏下非Live类型按钮的默认背景色
for subView in contentView.subviews {
if let btn = subView as? UIButton, !btn.isLiveButtonType() {
btn.backgroundColor = UIColor.tpbBackgroundForPopup
}
}
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 > 5 {
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.isLiveButtonType() {
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 {
func isLiveButtonType() -> Bool {
let tag = self.tag - TPMediaPreviewUtils.kMediaPlayerSubviewBaseTag
guard let type = TPMediaPlayerFuncType(rawValue: tag) else {
return false
}
switch type {
case .LiveMultiPlay, .LiveQuality, .LivePlay, .LiveVolume, .LiveLandscape:
return true
default:
return false
}
}
@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()
}
}
最新发布