TableView滚动上的UIView动画位置,然后再次拖动Tableview

问题描述 投票:0回答:1

我在顶部的标题菜单中有一个项目列表。

[当用户向上滚动菜单时,菜单也应滚动到屏幕之外,当他们返回列表顶部时,菜单应可见。

tableViewHeader的行为几乎相同。

但是,如果标题不在屏幕上,并且用户结束了列表上的向下拖动,则此标题视图应从顶部向下进行动画处理。如果用户随后在列表上结束向上拖动,则标题应在离开屏幕的情况下进行动画处理。

我已经完成了下面的第一部分,但是正在努力实现动画效果。

我曾考虑过使用菜单的2个视图,其中一个可滚动,另一个可对其位置进行动画处理,但是感觉不错,我敢肯定必须有一种更好的方法来避免重复视图。

class TableViewScene: UIViewController {

  let data = Array(0...99)

  var headerViewOneTopConstraint: NSLayoutConstraint!
  var tableViewTopConstraint: NSLayoutConstraint!

  lazy var headerViewOne: UIView = {
    let view = UIView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.backgroundColor = .purple
    return view
  }()

  lazy var tableView: UITableView = {
    let view = UITableView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.delegate = self
    view.dataSource = self
    view.tableFooterView = .init()
    view.refreshControl = .init()
    return view
  }()

  override func viewDidLoad() {
    super.viewDidLoad()

    navigationController?.navigationBar.isTranslucent = false

    headerViewOneTopConstraint = headerViewOne.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
    tableViewTopConstraint = tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 184)

    [headerViewOne, tableView].forEach(view.addSubview)

    NSLayoutConstraint.activate([
      headerViewOneTopConstraint,
      headerViewOne.leadingAnchor.constraint(equalTo: view.leadingAnchor),
      headerViewOne.trailingAnchor.constraint(equalTo: view.trailingAnchor),
      headerViewOne.heightAnchor.constraint(equalToConstant: 184),

      tableViewTopConstraint,
      tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
      tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
      tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
    ])
  }
}

extension TableViewScene: UITableViewDelegate {
  func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let offsetY = scrollView.contentOffset.y

    headerViewOneTopConstraint.constant = max(-184, min(0, -offsetY))
    tableViewTopConstraint.constant = 184 - max(0, offsetY)
  }
}

我也曾尝试将其添加到视图中

  func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    let translation = scrollView.panGestureRecognizer.translation(in: scrollView.superview)

    if translation.y > 0 {
      headerViewOne.transform = .init(translationX: 0, y: 184)
    } else if translation.y < 0 {
      headerViewOne.transform = .identity
    }
  }

这不起作用,而只是在滚动到顶部时呈现一个用于填充视图的黑色空间。

swift uitableview uiview uiscrollview uiviewanimation
1个回答
0
投票

很难确切地说出您要寻找的内容,但这可能对您有用。在此实现中,当用户向上拖动时,标题将隐藏,而当用户向下拖动时,标题将显示。无论滚动位置如何,都是如此。

我对您的约束之一进行了更改,因此tableView的顶部固定在标题的底部:

    tableViewTopConstraint = tableView.topAnchor.constraint(equalTo: headerViewOne.bottomAnchor)

我也在像这样跟踪标题的状态:

enum HeaderState {
    case hidden
    case revealed
    case hiding
    case revealing
}

var headerState: HeaderState = .revealed

现在为滚动逻辑。如果滚动位置在顶部附近,那么我们要手动显示/隐藏标题。但是,如果滚动位置在底部或中央附近,那么我们要设置显示/隐藏功能的动画。

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let translation = scrollView.panGestureRecognizer.translation(in: scrollView.superview)

    if scrollView.contentOffset.y < 184 {
        if translation.y > 0 && headerState != .revealed && headerState != .revealing {
            headerViewOneTopConstraint.constant = max(-184, min(0, -scrollView.contentOffset.y))
        } else if translation.y < 0 {
            headerViewOneTopConstraint.constant = max(-184, min(0, -scrollView.contentOffset.y))
        }
        return
    }

    if translation.y > 0 && headerState == .hidden {

        self.headerState = .revealing
        UIView.animate(withDuration: 0.4, animations: {
            self.headerViewOneTopConstraint.constant = 0
            self.view.layoutIfNeeded()
        }, completion: { _ in
            self.headerState = .revealed
        })

    } else if translation.y < 0 && headerState == .revealed {

        self.headerState = .hiding
        UIView.animate(withDuration: 0.4, animations: {
            self.headerViewOneTopConstraint.constant = -184
            self.view.layoutIfNeeded()
        }, completion: { _ in
            self.headerState = .hidden
        })
    }
}

试一下,看看它是否满足您的需求。

© www.soinside.com 2019 - 2024. All rights reserved.