ios 在Scrollview中添加拉取到刷新,而不启用反弹[关闭]

aiqt4smr  于 2023-08-08  发布在  iOS
关注(0)|答案(1)|浏览(115)

已关闭。此问题需要更多focused。它目前不接受回答。
**希望改进此问题?**更新问题,使其仅针对editing this post的一个问题。

4个月前关闭。
Improve this question
我们如何配置拉刷新无反弹启用滚动视图。
它很简单,当我们保持反弹启用,我们只需要分配刷新控制滚动视图,但我不想启用反弹
任何建议将不胜感激。提前致谢
已经尝试过滚动视图做滚动方法,但它不会调用,因为可能会有滚动视图没有足够的数据滚动页面的情况

hmae6n7t

hmae6n7t1#

一种方法是创建自己的“刷新视图”,并:

  • 将其约束到滚动视图的顶部
  • 将平移手势添加到滚动视图
  • 如果用户向下拖动,则向下移动“刷新视图”
  • 当它完全可见时,运行数据刷新
  • 将其设置为后退

下面是一个简单的例子:

class RefreshVC: UIViewController {
    
    let scrollView: UIScrollView = UIScrollView()
    let contentView: UIView = UIView()
    let contentLabel: UILabel = UILabel()
    
    let myRefreshView: UIView = UIView()
    let activityView: UIActivityIndicatorView = UIActivityIndicatorView()
    
    var cBottom: NSLayoutConstraint!
    
    var myData: [String] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        [contentLabel, contentView, scrollView, myRefreshView, activityView].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
        }
        
        myRefreshView.addSubview(activityView)
        contentView.addSubview(contentLabel)
        scrollView.addSubview(contentView)
        scrollView.addSubview(myRefreshView)
        
        view.addSubview(scrollView)
        
        let g = view.safeAreaLayoutGuide
        let cg = scrollView.contentLayoutGuide
        let fg = scrollView.frameLayoutGuide
        
        NSLayoutConstraint.activate([
            
            scrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 80.0),
            scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
            scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
            scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -80.0),

            contentView.topAnchor.constraint(equalTo: cg.topAnchor, constant: 8.0),
            contentView.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 8.0),
            contentView.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -8.0),
            contentView.bottomAnchor.constraint(equalTo: cg.bottomAnchor, constant: -8.0),
            
            contentView.widthAnchor.constraint(equalTo: fg.widthAnchor, constant: -16.0),
            
            contentLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8.0),
            contentLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0),
            contentLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8.0),
            contentLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8.0),
            
            activityView.centerXAnchor.constraint(equalTo: myRefreshView.centerXAnchor),
            activityView.centerYAnchor.constraint(equalTo: myRefreshView.centerYAnchor),
            
            myRefreshView.widthAnchor.constraint(equalToConstant: 200.0),
            myRefreshView.heightAnchor.constraint(equalToConstant: 100.0),
            myRefreshView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),

        ])

        cBottom = myRefreshView.bottomAnchor.constraint(equalTo: fg.topAnchor)
        cBottom.isActive = true

        myRefreshView.backgroundColor = .white.withAlphaComponent(0.90)
        myRefreshView.layer.cornerRadius = 12
        myRefreshView.layer.borderColor = UIColor.black.cgColor
        myRefreshView.layer.borderWidth = 1
        
        //activityView.style = .large
        activityView.color = .red
        activityView.startAnimating()
        
        scrollView.backgroundColor = .systemBlue
        contentView.backgroundColor = .systemYellow
        contentLabel.backgroundColor = .cyan
        
        contentLabel.numberOfLines = 0
        contentLabel.textAlignment = .center
        contentLabel.font = .systemFont(ofSize: 40.0, weight: .bold)
        
        // let's start with 5 lines of text as our content
        myData = (1...5).compactMap({ "Line \($0)" })
        
        contentLabel.setContentCompressionResistancePriority(.required, for: .vertical)
        contentLabel.text = myData.joined(separator: "\n")
        
        scrollView.bounces = false
        
        let pg = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
        scrollView.addGestureRecognizer(pg)
        pg.delegate = self
    }
    
    var startPT: CGPoint = .zero
    var isRefreshing: Bool = false
    
    @objc func handlePan(_ pan: UIPanGestureRecognizer) {
        
        guard let sv = pan.view as? UIScrollView,
              isRefreshing == false
        else { return }
        
        let curPT = pan.location(in: view)
        
        switch pan.state {
        case .began:
            // we only want to "pull down" the refresh view if
            //  we start dragging when the scroll view is all the
            //  way at the top
            if sv.contentOffset.y == 0 {
                startPT = curPT
            } else {
                startPT.y = .greatestFiniteMagnitude
            }
            
        case .changed:
            let diff = curPT.y - startPT.y
            // if we are dragging down
            if diff > 0 {
                // if the scroll view content is at the top
                if sv.contentOffset.y == 0 {
                    scrollView.isScrollEnabled = false
                    // move the refresh view down
                    cBottom.constant = min(diff, myRefreshView.frame.height + 4.0)
                    // if the refresh view is fully down
                    if cBottom.constant == myRefreshView.frame.height + 4.0 {
                        isRefreshing = true
                        refreshContent()
                    }
                }
            }
            
        default:
            // if the refresh view has not been pulled all the way
            //  when drag ended / was cancelled
            // animate it back up
            print("done", cBottom.constant)
            self.scrollView.isScrollEnabled = true
            if cBottom.constant > 0.0, cBottom.constant < myRefreshView.frame.height + 4.0 {
                cBottom.constant = 0
                UIView.animate(withDuration: 0.3, animations: {
                    self.view.layoutIfNeeded()
                })
            }

        }
        
    }
    
    @objc func refreshContent() {
        
        // let's simulate a 1-second refresh task
        //  and add a line to the scroll view content
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
            self.myData.append("Line \(self.myData.count + 1)")
            self.contentLabel.text = self.myData.joined(separator: "\n")
            // animate the refresh view back up
            DispatchQueue.main.async {
                self.cBottom.constant = 0
                UIView.animate(withDuration: 0.3, animations: {
                    self.view.layoutIfNeeded()
                }, completion: {_ in
                    self.isRefreshing = false
                    self.scrollView.isScrollEnabled = true
                })
            }
        })
        
    }
    
}

extension RefreshVC: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

字符串
运行时看起来像这样:
x1c 0d1x的数据
一旦你添加了足够的行,滚动视图将滚动。。并且如果滚动视图一直滚动到顶部,则“刷新视图”将仅被下拉。
注意:这只是 * 示例代码!!!***
这只是给予你一个开始。您可能希望调整距离、交互功能等。

相关问题