Move a view when scrolling in UITableView

前端 未结 9 1930
孤街浪徒
孤街浪徒 2020-12-04 11:42

I have a UIView with a UITableView below it:

\"enter

相关标签:
9条回答
  • 2020-12-04 11:54

    Since UITableView is a subclass of UIScrollView, your table view's delegate can receive UIScrollViewDelegate methods.

    In your table view's delegate:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        static CGFloat previousOffset;
        CGRect rect = self.view.frame;
        rect.origin.y += previousOffset - scrollView.contentOffset.y;
        previousOffset = scrollView.contentOffset.y;
        self.view.frame = rect;
    }
    
    0 讨论(0)
  • 2020-12-04 11:59

    I know this post in very old. I tried above solutions but neither worked for me for tried my own, hopefully it can help you. This scenario is pretty common, as apple suggested not to use TableViewController inside any ScrollView because the compiler will confused as in whom to respond becuase it will be getting two delegate call back - one from ScrollViewDelegate and another from UITableViewDelegate.

    Instead we can use ScrollViewDelegate and disable the UITableViewScrolling.

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        CGFloat currentOffSetY = scrollView.contentOffset.y;
        CGFloat diffOffset = self.lastContentOffset - currentOffSetY;
    
        self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, 400 + [self.tableView contentSize].height);
    
        if (self.lastContentOffset < scrollView.contentOffset.y) {
            tableView.frame = CGRectMake(tableView.frame.origin.x, tableView.frame.origin.y , tableView.frame.size.width,  tableView.size.height - diffOffset);
        }
    
        if (self.lastContentOffset > scrollView.contentOffset.y) {
            tableView.frame = CGRectMake(tableView.frame.origin.x, tableViewframe.origin.y, tableViewframe.size.width,  tableView.frame.size.height + diffOffset);
        }
    
        self.lastContentOffset = currentOffSetY;
    }
    

    Here lastContentOffset is CGFloat defined as property

    The View Heirarchy is as follows: ViewController --> View contains ScrollView (whose delegate method is defined above) --> Contain TableView.

    By the above code we are manually increasing and decreasing the height of the table view along with the content size of ScrollView.

    Remember to disable the Scrolling of TableView.

    0 讨论(0)
  • 2020-12-04 12:02

    Swift 3 & 4:

        var oldContentOffset = CGPoint.zero
        let topConstraintRange = (CGFloat(0)..<CGFloat(140))
    
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
    
            let delta =  scrollView.contentOffset.y - oldContentOffset.y
    
            //we compress the top view
            if delta > 0 && yourConstraint.constant > topConstraintRange.lowerBound && scrollView.contentOffset.y > 0 {
                yourConstraint.constant -= delta
                scrollView.contentOffset.y -= delta
            }
    
            //we expand the top view
            if delta < 0 && yourConstraint.constant < topConstraintRange.upperBound && scrollView.contentOffset.y < 0{
                yourConstraint.constant -= delta
                scrollView.contentOffset.y -= delta
            }
            oldContentOffset = scrollView.contentOffset
        }
    
    0 讨论(0)
  • 2020-12-04 12:02

    To create like this animation,

    lazy var redView: UIView = {
    
        let view = UIView(frame: CGRect(x: 0, y: 0, width: 
        self.view.frame.width, height: 100))
        view.backgroundColor = .red
        return view
    }()
    
    var pageMenu: CAPSPageMenu?
    
    override func viewDidLoad() {
         super.viewDidLoad()
         self.view.addSubview(redView)
    
        let rect = CGRect(x: 0, y: self.redView.frame.maxY, width: self.view.bounds.size.width, height:(self.view.bounds.size.height - (self.redView.frame.maxY)))
        pageMenu?.view.frame = rect
        self.view.addSubview(pageMenu!.view)
    
      }
    
    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
      let offset = scrollView.contentOffset.y
    
        if(offset > 100){
            self.redView.frame = CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: 0)
        }else{
            self.redView.frame = CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: 100 - offset)
        }
    
        let rect = CGRect(x: 0, y: self.redView.frame.maxY, width: self.view.bounds.size.width, height:(self.view.bounds.size.height - (self.redView.frame.maxY)))
        pageMenu?.view.frame = rect
    }
    

    you must change pageMenu.view with your collectionView/tableView

    0 讨论(0)
  • 2020-12-04 12:05

    More simple and fast approach

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView 
    {
    
        CGRect rect = self.view.frame;
        rect.origin.y =  -scrollView.contentOffset.y;
        self.view.frame = rect;
    
    }
    
    0 讨论(0)
  • I added some constraints to the last solution to prevent some strange behaviours in case of fast scrolling

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let delta =  scrollView.contentOffset.y - oldContentOffset.y
    
        //we compress the top view
        if delta > 0 && topConstraint.constant > topConstraintRange.lowerBound && scrollView.contentOffset.y > 0 {
            searchHeaderTopConstraint.constant = max(topConstraintRange.lowerBound, topConstraint.constant - delta)
            scrollView.contentOffset.y -= delta
        }
    
        //we expand the top view
        if delta < 0 && topConstraint.constant < topConstraintRange.upperBound && scrollView.contentOffset.y < 0 {
            topConstraint.constant = min(searchHeaderTopConstraint.constant - delta, topConstraintRange.upperBound)
            scrollView.contentOffset.y -= delta
        }
        oldContentOffset = scrollView.contentOffset
    }
    
    0 讨论(0)
提交回复
热议问题