当用户滚动到不同的页面时,如何在“UICollectionView”的不同背景颜色之间淡化?

Posted

技术标签:

【中文标题】当用户滚动到不同的页面时,如何在“UICollectionView”的不同背景颜色之间淡化?【英文标题】:How to fade between different background colors of a `UICollectionView` as the user scrolls to a different page? 【发布时间】:2016-12-19 03:02:18 【问题描述】:

我正在尝试在他们的 ios 应用上复制 eBay 的列表菜单,用户可以在其中滚动浏览列表的不同图像。我注意到背景颜色是一种纯色,可以复制每个图像中背景的环绕颜色。

当我滚动浏览具有不同环绕背景的不同图像(不同页面)时,UICollectionView 的实际背景会发生变化以某种方式反映它。

这就是我的意思:

正如您在第一张图片中看到的那样,背景是浅色,有点类似于图像的背景。当我滚动到第二张图片的一半时,背景变暗了。

最后:

我的设置类似:

使用DominantColor,我可以用每个UIImage 的主色来设置UICollectionView 的背景色。当用户在第一页和第二页之间滚动时,UICollectionView 的背景颜色将设置为第二页 UIImage 的主色。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as UICollectionViewCell

    let frame: CGRect = CGRect(x: 0, y: 0, width: imagesView.frame.size.width, height: imagesView.frame.size.height)

    let subView: UIImageView = UIImageView(frame: frame)

    subView.image = imagesArray[indexPath.row].image

    subView.contentMode = UIViewContentMode.scaleAspectFit

    if colorsArray.count > 0
    
        // Set background dominant color of first image
        collectionView.backgroundColor = colorsArray[0]
    

    cell.addSubview(subView)

    return cell


func scrollViewDidScroll(_ scrollView: UIScrollView)

    let scrollValue = (scrollView.contentOffset.x / UIScreen.main.bounds.width)

    let pageWidth: CGFloat = imagesCollectionView.bounds.size.width

    let currentPage: Int = Int( floor( (imagesCollectionView.contentOffset.x - pageWidth / 2) / pageWidth) + 1)

    if scrollValue != 1
    
        UIView.animate(withDuration: 1, animations: 

            self.imagesCollectionView.backgroundColor = self.colorsArray[currentPage]

        )

    
    else
    
        UIView.animate(withDuration: 1, animations: 

            self.imagesCollectionView.backgroundColor = self.colorsArray[currentPage]

        )

    

但是,我很难在用户开始滚动时很快从当前背景颜色慢慢过渡到下一个背景颜色,如上面的第二张图片所示。

目前在scrollViewDidScroll中实现的方式,当页面在下一页之间滚动到一半时,它开始淡入下一个颜色,并带有1秒动画, 1秒内变成那个颜色,不管下一页是半显示还是全显示。

我怎样才能做到这一点?

【问题讨论】:

在这里回答***.com/a/56072529/4568747 【参考方案1】:

使用Fogmeister's answer in obj-C 和user3344977's answer to Swift,以及Tonton's guide,我想出了解决方案:

func scrollViewDidScroll(_ scrollView: UIScrollView)

    let pageWidth: CGFloat = imagesCollectionView.bounds.size.width
    let currentPage: Int = Int( floor( (imagesCollectionView.contentOffset.x - pageWidth / 2) / pageWidth) + 1)

    let maximumHorizontalOffset: CGFloat = scrollView.contentSize.width - scrollView.frame.size.width
    let currentHorizontalOffset: CGFloat = scrollView.contentOffset.x

    let percentageHorizontalOffset: CGFloat = currentHorizontalOffset / maximumHorizontalOffset

    if percentageHorizontalOffset < 0.5
    
        imagesCollectionView.backgroundColor = fadeFromColor(fromColor: colorsArray[currentPage], toColor: colorsArray[currentPage + 1], withPercentage: percentageHorizontalOffset)
    
    else
    
        imagesCollectionView.backgroundColor = fadeFromColor(fromColor: colorsArray[currentPage - 1], toColor: colorsArray[currentPage], withPercentage: percentageHorizontalOffset)
    


func fadeFromColor(fromColor: UIColor, toColor: UIColor, withPercentage: CGFloat) -> UIColor

    var fromRed: CGFloat = 0.0
    var fromGreen: CGFloat = 0.0
    var fromBlue: CGFloat = 0.0
    var fromAlpha: CGFloat = 0.0

    // Get the RGBA values from the colours
    fromColor.getRed(&fromRed, green: &fromGreen, blue: &fromBlue, alpha: &fromAlpha)

    var toRed: CGFloat = 0.0
    var toGreen: CGFloat = 0.0
    var toBlue: CGFloat = 0.0
    var toAlpha: CGFloat = 0.0

    toColor.getRed(&toRed, green: &toGreen, blue: &toBlue, alpha: &toAlpha)

    // Calculate the actual RGBA values of the fade colour
    let red = (toRed - fromRed) * withPercentage + fromRed;
    let green = (toGreen - fromGreen) * withPercentage + fromGreen;
    let blue = (toBlue - fromBlue) * withPercentage + fromBlue;
    let alpha = (toAlpha - fromAlpha) * withPercentage + fromAlpha;

    // Return the fade colour
    return UIColor(red: red, green: green, blue: blue, alpha: alpha)

现在,当用户开始滚动到下一页/上一页时,由于percentageHorizontalOffset 中的颜色 alpha 变化,背景颜色会慢慢变化。

感谢所有提到的人!

【讨论】:

【参考方案2】:

如果颜色的变化需要与滚动同步,即逐渐改变颜色,您可能希望使用 collectionView 中的滚动视图来更改 scrollViewDidScroll

通过获取 2 背景图像颜色(可能使用 Mike JS Choi 的答案),您可以比较它们的差异。使用从 0 到 1 的滚动值,可以逐渐改变颜色。

使用一些局部变量让方法知道你当前的图像是什么

func scrollViewDidScroll(_ scrollView: UIScrollView) 
    let scrollValue = (scrollView.contentOffset.x / UIScreen.main.bounds.width) - 1

    guard let nextColor: UIColor? = getBackgroundColor(from: nextImage) else  return 

    let currentImage = getBackgroundColor(from: currentImage)

    let currentIndex = pageControl.currentPage

    if scrollValue != 0 
        backgroundColor = colorDifference(current: currentColor, next: nextColor, transitionValue: abs(scrollValue))
     else 
        backgroundColor = nextColor
    


func colorDifference(current: UIColor, next: UIColor, transitionValue: Int) -> UIColor 
    var currentRed: Float = 0
    var currentGreen: Float = 0
    var currentBlue: Float = 0
    var currentAlpha: Float = 0
    current.getRed(&currentRed, green: &currentGreen, blue: &currentBlue, alpha: &currentAlpha)

    var nextRed: Float = 0
    var nextGreen: Float = 0
    var nextBlue: Float = 0
    var nextAlpha: Float = 0
    next.getRed(&nextRed, green: &nextGreen, blue: &nextBlue, alpha: &nextAlpha)

    let finalRed = (nextRed - currentRed) * transitionValue
    let finalGreen = (nextGreen - currentGreen) * transitionValue
    let finalBlue = (nextBlue - currentBlue) * transitionValue
    let finalAlpha = (nextAlpha - currentAlpha) * transitionValue

    let finalColor = UIColor(colorLiteralRed: finalRed, green: finalGreen, blue: finalBlue, alpha: finalAlpha)
    return finalColor

因此,您必须弄清楚如何存储当前图像并获取下一张图像(您可以前后滚动),然后在 scrollViewDidScroll 方法中使用这些图像。 glhf 家族

【讨论】:

【参考方案3】:

棘手的部分是找到与每张图片对应的颜色。我曾经使用过 TDImageColors 效果很好:https://www.cocoacontrols.com/controls/tdimagecolors

那么您所要做的就是从一种颜色过渡到另一种颜色。就像@Tonton 的回答一样。

【讨论】:

以上是关于当用户滚动到不同的页面时,如何在“UICollectionView”的不同背景颜色之间淡化?的主要内容,如果未能解决你的问题,请参考以下文章

当用户滚动时将菜单从水平移动到垂直?

如何使用viewForSupplementaryElementOfKind - swift显示UICollectionView的特定单元格

当用户滚动到页面的最底部时淡入/淡出固定位置 div

检测用户何时使用 jQuery 滚动到 div 的底部

如何在页面滚动时获取嵌套面板的相对坐标

如何在动画完成之前禁用滚动?