2017-05-09 172 views
1

我会说得很对。滚动/调整大小UITableView

我有一个UIViewController,它有两个子视图。最上面的一个(我们现在称之为HeaderView)是一个自定义的UIView,最底层的是一个UITableView。
我已经在InterfaceBuilder中设置了它们,以便HeaderView从左边,顶部和右边开始有0个边距,并且它还有一个固定的高度。 UITableView直接在下面,各边都有0的余量。

我的目标是实现这样的行为,当我开始滚动UITableView的内容时,HeaderView将开始收缩并且UITableView在没有滚动的情况下变得更高。这应该继续,直到HeaderView达到最小高度。之后,UITableView应该像平常一样开始滚动。当向下滚动效果应该颠倒。

我最初开始使用UIScrollView而不是UITableView来实现期望的结果。下面是如何:

  1. 所述的UIScrollView连接到出口
    @IBOutlet weak var scrollView: UIScrollView!

  2. 设置UIScrollViewDelegate在控制器的viewDidLoad()方法 self.scrollView.delegate = self 并宣布的UIViewController以符合协议

  3. 当UIScrollView滚动时截取:
    func scrollViewDidScroll(_ scrollView: UIScrollView) { self.adjustScrolling(offset: scrollView.contentOffset.y, scrollView: scrollView) }

  4. 在我adjustScrolling(offset:scrollView:)法“魔术”发生

现在让我们来看看这种方法会发生什么。

private func adjustScrolling(offset: CGFloat, scrollView: UIScrollView) { 

     // bind value between 0 and max header scroll 
     let actualOffset: CGFloat = offset < 0 ? 0 : (offset >= self.maxHeaderScroll ? self.maxHeaderScroll : offset) 

     // avoid useless calculations 
     if (actualOffset == self.currentOffset) { 
      return 
     } 

     /** 
     * Apply the vertical scrolling to the header 
     */ 
     // Translate the header up to give more space to the scrollView 
     let headerTransform = CATransform3DTranslate(CATransform3DIdentity, 0, -(actualOffset), 0) 
     self.header.layer.transform = headerTransform 
     // Adjust header's subviews to new size 
     self.header.didScrollBy(actualOffset) 

     /** 
     * Apply the corrected vertical scrolling to the scrollView 
     */ 
     // Resize the scrollView to fill all empty space 
     let newScrollViewY = self.header.frame.origin.y + self.header.frame.height 
     scrollView.frame = CGRect(
      x: 0, 
      y: newScrollViewY, 
      width: scrollView.frame.width, 
      height: scrollView.frame.height + (scrollView.frame.origin.y - newScrollViewY) 
     ) 
     // Translate the scrollView's content view down to contrast scrolling 
     let scrollTransform = CATransform3DTranslate(CATransform3DIdentity, 0, (actualOffset), 0) 
     scrollView.subviews[0].layer.transform = scrollTransform 
     // Set bottom inset to show content hidden by translation 
     scrollView.contentInset = UIEdgeInsets(
      top: 0, 
      left: 0, 
      bottom: actualOffset, 
      right: 0 
     ) 

     self.currentOffset = actualOffset 
    } 

如果我没有忘记任何东西,这应该足以达到预期的效果。让我把它分解:

  1. 我计算actualOffset结合其0和self.MaxHeaderScroll之间这仅仅是67(我认为,它是动态的计算,但这个并不重要)
  2. 如果我看到actualOffset自从上次调用这个函数以来没有改变,我懒得去适应任何改变。这避免了一些无用的计算。
  3. 我将滚动应用到标题,只需在y轴上将CATransform3DTranslate翻译为负值actualOffset
  4. 我打电话给self.header.didScrollBy(actualOffset),这样HeaderView可以在内部应用一些可视变化。但这并不能解决问题。
  5. 我调整了scrollView的大小,以便它保持顶部和底部0的边距,现在HeaderView更高了。
  6. 我翻译下scrollView的内容相同的actualOffset数量来对比滚动。这件作品对于我想达到的正确视觉效果至关重要。如果我没有这样做,scrollView仍然会正确调整大小,但内容会立即开始滚动,这是我不想要的。它应该只在HeaderView达到最小高度时开始滚动。
  7. 我现在在scrollView中设置一个底部插入,这样我就可以一直滚动到最后。如果没有这个,scrollView的最后一部分会被截断,因为scrollView本身会认为它已经达到了它的内容的末尾。
  8. 最后我存储actualOffset供以后比较

正如我所说的,这工作正常。从UIScrollView切换到UITableView时出现问题。我认为它会工作,因为UITableView从UIScrollView继承。
不工作的唯一代码是数字6.我不知道发生了什么问题,所以我只列出我发现和/或注意到的所有内容。希望有人能帮助我。

  • 在UIScrollView的情况下,在第6点,scrollView.subviews[0]引用了一个视图,该视图包含其中的所有内容。当我更改为UITableView时,此子视图的类型似乎是UITableViewWrapperView,我找不到任何有关文档,XCode也不认为它是有效的类。这已经令人沮丧。
  • 如果在第6点我也给了x轴上的一些翻译(比方说50)我可以看到一个初始的非常快速的翻译,立即返回到0.这只发生在UITableView开始滚动时,它不会'滚动时继续。
  • 我已经尝试改变点6的子视图的框架来实现所需的结果。虽然滚动是正确的,但是当我滚动UITableView时,顶部单元格开始消失。我很细致,因为我正在使用dequeueReusableCell(withIdentifier:for:)来安装单元,而UITableView认为顶部单元实际上不可见。我无法解决这个问题。
  • 我已经尝试将self.tableView.tableHeaderView设置为高度为actualOffset的UIView以对比滚动,但这给出了一种奇怪的效果,其中单元格不能正确滚动,并且当UITableView返回初始位置时,最佳。对此也没有任何线索。

我知道这里有很多,所以请不要犹豫,询问更多细节。先谢谢你。

+0

只是做一个演示 – SeanLintern88

+0

@ SeanLintern88有没有运气? –

+0

嘿,我做了一个演示,但后来重新读你的问题,并不确定我是否覆盖了所有,请看看演示 – SeanLintern88

回答

6

我做了这样的事情最近,所以继承人我如何实现它:

做有高度限制不变一个UIView和链接给你的视图/ VC,你的UITableView受限于VC的看法全屏幕背后UIView。

现在将您的UITableViews contentInset设置为您的'headerView'的起始高度,现在在scrollViewDidScroll中调整常量,直到标题的高度达到最小值。

Here is a demo

如果你只要运行它,蓝色区域是你的“头”和有色行只是任何细胞。你可以在蓝色区域自动布置任何你想要的东西,它应该自动调整尺寸和一切

+0

嘿,我设法得到它的工作感谢您的例子。太棒了,我欠你一个! –

+0

只要StackOverflow让我,我也会奖励你的赏金:) –

+0

当你实现targetContentOffset,另一个scrollViewDelegate方法时,它也会得到易货贸易,这意味着你可以停止在最小/最大高度之间结束的滚动动画,如果这就是你需要 – SeanLintern88