删除嵌套视图时,UIScrollView的动画偏移量更改

问题描述

我有一个UIScrollView,其中包含堆栈视图-我基本上是在复制制表符功能。

一个标签页的视图比另一个标签页高,因此当我在堆栈视图中隐藏该视图时,它会调整大小。

如果用户滚动到顶部,则滚动视图将跳至适合较短视图的偏移量。

enter image description here

是否可以为该更改设置动画?视图会滚动到正确的偏移量,而不是跳转?我不确定如何实现这一目标。


final class ScrollViewController: UIViewController {

  private var visibleTab: TabState = .overview {
    didSet {
      guard oldValue != visibleTab else { return }
      switch visibleTab {
        case .overview:
          self.spacesTab.isHidden = true
          self.overviewTab.isHidden = false
        case .spaces:
          self.spacesTab.isHidden = false
          self.overviewTab.isHidden = true
      }
    }
  }

  enum TabState {
    case overview
    case spaces
  }

  private lazy var scrollView: UIScrollView = {
    let view = UIScrollView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .white
    view.delegate = self
    view.alwaysBounceVertical = true
    return view
  }()

  private let contentStackView: UIStackView = {
    let view = UIStackView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.axis = .vertical
    view.alignment = .fill
    view.spacing = 8
    view.distribution = .fill
    return view
  }()

  private let tabSelectorView: UIStackView = {
    let view = UIStackView(frame: .zero)
    view.axis = .horizontal
    view.distribution = .fillEqually
    return view
  }()

  private let overviewTab: UIView = {
    let view = UIView(frame: .zero)
    view.backgroundColor = .darkGray
    view.heightAnchor.constraint(equalToConstant: 100).isActive = true
    view.isHidden = false
    return view
  }()

  private let spacesTab: UIView = {
    let view = UIView(frame: .zero)
    view.backgroundColor = .lightGray
    view.heightAnchor.constraint(equalToConstant: 780).isActive = true
    view.isHidden = true
    return view
  }()

  private let profileHeader = ScrollViewProfileHeaderView(frame: .zero)

  private lazy var overviewTabButton = makeButton(title: "Overview")
  private lazy var spacesTabButton = makeButton(title: "Spaces")

  override func viewDidLoad() {
    super.viewDidLoad()
    configureUI()
  }

}

extension ScrollViewController: UIScrollViewDelegate { }

private extension ScrollViewController {
  func configureUI() {
    overviewTabButton.addTarget(self,action: #selector(showOverviewTab),for: .touchUpInside)
    spacesTabButton.addTarget(self,action: #selector(showSpacesTab),for: .touchUpInside)

    [overviewTabButton,spacesTabButton].forEach(tabSelectorView.addArrangedSubview)

    profileHeader.translatesAutoresizingMaskIntoConstraints = false
    tabSelectorView.translatesAutoresizingMaskIntoConstraints = false

    [overviewTab,spacesTab].forEach(contentStackView.addArrangedSubview)

    [profileHeader,tabSelectorView,contentStackView].forEach(scrollView.addSubview(_:))
    view.addSubview(scrollView)
    NSLayoutConstraint.activate([
      scrollView.topAnchor.constraint(equalTo: view.topAnchor),scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),profileHeader.topAnchor.constraint(equalTo: scrollView.topAnchor),profileHeader.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),profileHeader.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),tabSelectorView.topAnchor.constraint(equalTo: profileHeader.bottomAnchor),tabSelectorView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),tabSelectorView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),contentStackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),contentStackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),contentStackView.topAnchor.constraint(equalTo: tabSelectorView.bottomAnchor,constant: 8),contentStackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),contentStackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
    ])
  }

  func makeButton(title: String) -> UIButton {
    let button = UIButton(type: .system)
    button.setTitle(title,for: .normal)
    button.backgroundColor = .lightGray
    return button
  }

  @objc func showOverviewTab() {
    visibleTab = .overview
  }

  @objc func showSpacesTab() {
    visibleTab = .spaces
  }
}

final class ScrollViewProfileHeaderView: UIView {

  private let headerImage: UIImageView = {
    let view = UIImageView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.contentMode = .scaleAspectFill
    view.clipsToBounds = true
    view.backgroundColor = .systemTeal
    return view
  }()

  private let profileCard: ProfileCardView = {
    let view = ProfileCardView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .purple
    return view
  }()

  override init(frame: CGRect) {
    super.init(frame: frame)

    backgroundColor = .white

    [headerImage,profileCard].forEach(addSubview(_:))

    NSLayoutConstraint.activate([
      headerImage.topAnchor.constraint(equalTo: topAnchor),headerImage.leadingAnchor.constraint(equalTo: leadingAnchor),headerImage.trailingAnchor.constraint(equalTo: trailingAnchor),headerImage.heightAnchor.constraint(equalToConstant: 180),profileCard.topAnchor.constraint(equalTo: headerImage.centerYAnchor),profileCard.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor,constant: 48),profileCard.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor,constant: -32),profileCard.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor,constant: -48),profileCard.heightAnchor.constraint(equalToConstant: 270),])
  }

  required init?(coder: NSCoder) {
    return nil
  }
}

解决方法

您可能需要进行一些其他更改,但这可能会让您无法自拔。

在您的visibleTab / didSet块中,当您隐藏UIView.animate()时使用spacesTab

private var visibleTab: TabState = .overview {
    didSet {
        guard oldValue != visibleTab else { return }
        switch self.visibleTab {
        case .overview:
            // set duration longer,such as 1.0,to clearly see the animation...
            UIView.animate(withDuration: 0.3) {
                self.spacesTab.isHidden = true
                self.overviewTab.isHidden = false
            }
        case .spaces:
            self.spacesTab.isHidden = false
            self.overviewTab.isHidden = true
        }
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...