对于仿照新闻首页的页面,已经有比较好用的OC版本,现在我们来写一个版本的。
设备:xcode 10.2 语言:swift 4.2
效果图:
我们先创建一个多控制器的栏,直接上代码:
- //
- // JHSBarItemView.swift
- // ScrollBarController
- //
- // Created by yaojinhai on 2019/4/15.
- // Copyright © 2019年 yaojinhai. All rights reserved.
- //
- import UIKit
- enum BarItemBorderType {
- case defualt
- case barItem
- case maskView
- case customItem
- }
- protocol JHSBarItemViewDelegate: NSObjectProtocol {
- func selectedIndexItem(view: JHSBarItemView,index: Int) -> Void
- }
- class JHSBarItemView: UIView {
- var minMargin: CGFloat = BarConfig.minMargin;
- weak var delegate: JHSBarItemViewDelegate?
- var lineBarView: UIView!
- var barType = BarItemBorderType.defualt {
- didSet{
- configBarType();
- removeBarItem(idx: selectedIndex);
- }
- }
- var selectedIndex = 0;
- var titles: [String]!{
- didSet{
- caculateItemSize();
- }
- }
- private var titlesView: UICollectionView!
- private var cachesSize = [String:CGSize]();
- override init(frame: CGRect) {
- super.init(frame: frame);
- createContentView();
- }
- convenience init(frame: CGRect,titles: [String]) {
- self.init(frame: frame);
- self.titles = titles;
- createContentView();
- caculateItemSize();
- }
- func progressWidth() -> Void {
- }
- required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension JHSBarItemView: UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
- private func caculateItemSize() -> Void {
- guard let itemTitles = titles ,itemTitles.count > 0 else {
- return;
- }
- var maxWidth: CGFloat = 0;
- for item in itemTitles {
- let size = item.textSize(size: CGSize(width: width, height: height), font: BarConfig.normalFont);
- cachesSize[item] = CGSize(width: size.width, height: height);
- maxWidth += size.width;
- }
- let gap = (width - maxWidth) / CGFloat(itemTitles.count + 1);
- minMargin = max(gap, BarConfig.minMargin);
- titlesView.reloadData();
- removeBarItem(idx: selectedIndex);
- }
- private func createContentView() -> Void {
- if titlesView != nil {
- return;
- }
- let layout = UICollectionViewFlowLayout();
- layout.minimumLineSpacing = 0;
- layout.minimumInteritemSpacing = 0;
- layout.scrollDirection = .horizontal;
- titlesView = FMBaseCollectionView(frame: .init(x: 0, y: 0, width: width, height: height), collectionViewLayout: layout);
- addSubview(titlesView);
- titlesView.register(BarItemViewCell.self, forCellWithReuseIdentifier: "title");
- titlesView.delegate = self;
- titlesView.dataSource = self;
- let lineView = createView(rect: .init(x: 0, y: height - 1, width: width, height: 1));
- lineView.backgroundColor = rgbColor(rgb: 234);
- }
- // MARK: - collection view delegate and dataSource
- func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- return titles?.count ?? 0;
- }
- func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
- return UIEdgeInsets(top: 0, left: minMargin, bottom: 0, right: minMargin);
- }
- func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
- if titles == nil {
- return CGSize.zero;
- }
- let item = titles[indexPath.row];
- if let size = cachesSize[item] {
- return CGSize(width: size.width + minMargin, height: height);
- }
- let size = titles[indexPath.row].textSize(size: CGSize.init(width: width, height: height), font: BarConfig.normalFont);
- let newSize = CGSize(width: size.width + minMargin, height: height);
- cachesSize[item] = size;
- return newSize;
- }
- func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
- let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "title", for: indexPath) as! BarItemViewCell;
- cell.titleLabel.text = titles[indexPath.row];
- cell.titleLabel.isHighlighted = selectedIndex == indexPath.row;
- return cell;
- }
- func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
- didSelected(idx: indexPath.row);
- delegate?.selectedIndexItem(view: self, index: indexPath.row);
- }
- func didSelected(idx: Int) -> Void {
- let indexPath = IndexPath(item: idx, section: 0);
- titlesView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true);
- let cell = titlesView.cellForItem(at: indexPath) as? BarItemViewCell;
- cell?.titleLabel.isHighlighted = true;
- cell?.RunAnimation();
- removeBarItem(idx: indexPath.row);
- if selectedIndex != indexPath.row {
- let preCell = titlesView.cellForItem(at: .init(row: selectedIndex, section: 0)) as? BarItemViewCell;
- preCell?.titleLabel.isHighlighted = false;
- preCell?.RunAnimation();
- selectedIndex = indexPath.row;
- }
- }
- }
- extension JHSBarItemView {
- private func removeBarItem(idx: Int) {
- if barType == .barItem {
- let size = getMaxWidthAt(index: idx);
- lineBarView.frame = .init(x: size.width, y: height - 2, width: size.height, height: 2);
- }else if barType == .maskView {
- let size = getMaxWidthAt(index: idx);
- lineBarView.frame = .init(x: size.width - minMargin/2, y: 0, width: size.height + minMargin, height: height);
- }
- }
- func getMaxWidthAt(index: Int) -> CGSize {
- if titles == nil || titles.count == 0 {
- return CGSize.zero;
- }
- var maxWidth: CGFloat = minMargin;
- var sizeWidth: CGFloat = cachesSize[titles[0]]!.width;
- if index > 0 {
- for item in 1...index {
- let title = titles[item];
- let size = cachesSize[title]!;
- maxWidth += size.width + minMargin;
- sizeWidth = size.width;
- }
- }
- return CGSize(width: maxWidth + minMargin/2, height: sizeWidth);
- }
- private func configBarType() -> Void {
- if barType == .barItem {
- if lineBarView == nil {
- lineBarView = createView(rect: .init(x: 0, y: height - 2, width: 30, height: 2));
- lineBarView.backgroundColor = UIColor.red;
- lineBarView.layer.cornerRadius = 2;
- lineBarView.layer.masksToBounds = true;
- }
- titlesView.addSubview(lineBarView);
- }else if barType == .maskView {
- if lineBarView == nil {
- lineBarView = createView(rect: .init(x: 0, y: 0, width: 30, height: height));
- lineBarView.backgroundColor = UIColor.green.withAlphaComponent(0.2);
- lineBarView.isUserInteractionEnabled = false;
- }
- titlesView.addSubview(lineBarView);
- }else{
- titlesView?.removeFromSuperview();
- }
- }
- }
- class BarItemViewCell: UICollectionViewCell {
- var titleLabel: UILabel!
- override init(frame: CGRect) {
- super.init(frame: frame);
- titleLabel = createLabel(rect: bounds, text: "");
- titleLabel.textAlignment = .center;
- titleLabel.textColor = BarConfig.normalColor;
- titleLabel.highlightedTextColor = BarConfig.hlightedColor;
- titleLabel.font = BarConfig.normalFont;
- }
- required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- func RunAnimation(animation: Bool = true) -> Void {
- self.titleLabel.font = self.titleLabel.isHighlighted ? BarConfig.hlightedFont : BarConfig.normalFont;
- }
- }
这个封装了导航栏的操作,并且实现了自动刷新功能。我们也可以自己扩展实现。
我们来定义一个控制器:
发表评论