Ios 在UICollectionView中滚动到上一个/下一个图像时,是否正确计算颜色不透明度偏移以更改背景颜色?

Ios 在UICollectionView中滚动到上一个/下一个图像时,是否正确计算颜色不透明度偏移以更改背景颜色?,ios,swift,uicollectionview,swift3,Ios,Swift,Uicollectionview,Swift3,如果标题不明确,我深表歉意,但目前我有一个UICollectionView图像。我最近发现了一种方法,可以使用。这样,当用户从一个UIImage单元格滚动到下一个单元格时,我尝试更改UICollectionView的背景色,即背景色将从imageX的主色慢慢淡入imageX+1的主色 然而,我已经花了好几天的时间在这上面,当单元格开始滚动到下一个/prev图像时,我很难改变UICollectionView的背景色不透明度 我的用户界面: 背景代码: func collectionView(_

如果标题不明确,我深表歉意,但目前我有一个
UICollectionView
图像。我最近发现了一种方法,可以使用。这样,当用户从一个
UIImage
单元格滚动到下一个单元格时,我尝试更改
UICollectionView
的背景色,即背景色将从imageX的主色慢慢淡入imageX+1的主色

然而,我已经花了好几天的时间在这上面,当单元格开始滚动到下一个/prev图像时,我很难改变
UICollectionView
的背景色不透明度

我的用户界面:

背景代码:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as UICollectionViewCell

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

    let subView: UIImageView = UIImageView(frame: frame)

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

    subView.contentMode = UIViewContentMode.scaleAspectFit

    cell.addSubview(subView)

    return cell
}

// The colorsArray will contain a dominant color for each image in the CollectionView
func dominantColorOfImages()
{
    for index in 0..<imagesArray.count
    {
        if let image = imagesArray[index].theImage
        {
            let colors: [UIColor] = image.dominantColors()

            colorsArray[index] = colors[index]
        }
    }

    // Default dominant background color for first image in CollectionView
    imagesCollectionView.backgroundColor = colorsArray[0]

    imagesCollectionView.reloadData()
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView)
{
    let pageWidth: CGFloat = scrollView.bounds.size.width

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

    currentImagePage = currentPage
}

func scrollViewDidScroll(_ scrollView: UIScrollView)
{
    let pageWidth: CGFloat = scrollView.bounds.size.width
    let currentPage: Int = Int( floor( (scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1)

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


    // This is the offset of how far the right side edge of the current image has pass the end of the left screen (i.e. when the user scrolls the image from the right to the left to get to the next image)
    let pageOffset: CGFloat = ( (pageWidth * CGFloat(currentImagePage) ) + (pageWidth / 2) ) / maximumHorizontalOffset

    if percentageHorizontalOffset < pageOffset
    {

        imagesCollectionView.backgroundColor = fadeFromColorToColor(fromColor: colorsArray[currentImagePage], toColor: colorsArray[currentImagePage + 1], withPercentage: percentageHorizontalOffset * CGFloat(colorsArray.count - 1 ) )

    }
    else
    {

        imagesCollectionView.backgroundColor = fadeFromColorToColor(fromColor: colorsArray[currentImagePage], toColor: colorsArray[currentImagePage + 1], withPercentage: (percentageHorizontalOffset - pageOffset) * CGFloat(colorsArray.count - 1) ))

    }
}

func fadeFromColorToColor(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

如果将scrollViewDidScroll func的else子句中的行更改为:

    imagesCollectionView.backgroundColor = fadeFromColorToColor(fromColor: colorsArray[currentImagePage], toColor: colorsArray[currentImagePage], withPercentage: (percentageHorizontalOffset - pageOffset) * CGFloat(colorsArray.count - 1) ))

很难准确阅读代码示例,因为示例文本中没有定义某些变量/标识符,例如percentageHorizontalOffset

如果将scrollViewDidScroll func的else子句中的行更改为:

    imagesCollectionView.backgroundColor = fadeFromColorToColor(fromColor: colorsArray[currentImagePage], toColor: colorsArray[currentImagePage], withPercentage: (percentageHorizontalOffset - pageOffset) * CGFloat(colorsArray.count - 1) ))

fadeFromColorToColor
中,如果百分比为负值,则交换
toColor
fromColor
并将
percent
变为正值。

fadeFromColorToColor
中,如果百分比为负值,则交换
toColor
fromColor
并将
百分比变为正值。

这里是一些代码准备粘贴到操场上。打开“助手编辑器”以使用“集合”视图。这就是你要找的吗

import UIKit
import PlaygroundSupport

extension UIColor {
    func components() -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {
        var r: CGFloat = 0.0
        var g: CGFloat = 0.0
        var b: CGFloat = 0.0
        var a: CGFloat = 0.0
        getRed(&r, green: &g, blue: &b, alpha: &a)
        return (r, g, b, a)
    }
}

class Controller: UICollectionViewController {

    // some test data instead of images:
    let pages = [#colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1), #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1), #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1), #colorLiteral(red: 0.9372549057, green: 0.3490196168, blue: 0.1921568662, alpha: 1), #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1), #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)]

    // these should be your significant colors from the images:
    let colorsArray = [#colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1), #colorLiteral(red: 0.5568627715, green: 0.3529411852, blue: 0.9686274529, alpha: 1), #colorLiteral(red: 0.9098039269, green: 0.4784313738, blue: 0.6431372762, alpha: 1), #colorLiteral(red: 0.9568627477, green: 0.6588235497, blue: 0.5450980663, alpha: 1), #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1), #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1)]

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
        collectionView?.contentInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return pages.count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = pages[indexPath.item]
        return cell
    }

    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let currentHorizontalOffset = collectionView!.contentOffset.x + collectionView!.contentInset.left
        let pageWidth = scrollView.bounds.size.width
        let page = Int(max(0, floor(currentHorizontalOffset / pageWidth)))

        // Don't change the background color when scrolling past the last page:
        guard page < pages.count - 1 else {
            return
        }

        let partialPageVisibleWidth = currentHorizontalOffset - CGFloat(page) * pageWidth
        let ratio = max(0, partialPageVisibleWidth / pageWidth)

        let leftColor = colorsArray[page]
        let rightColor = colorsArray[page + 1]

        scrollView.backgroundColor = blend(leftColor, rightColor, ratio: ratio)
    }

    /**
    Blends two colors by the given ratio

    - returns: `lhs` if t == 0; `rhs` if t == 1; otherwise a blend of `lhs` and `rhs` by using a linear interpolation function
    */
    func blend(_ lhs: UIColor, _ rhs: UIColor, ratio t: CGFloat) -> UIColor
    {
        let (r1, g1, b1, a1) = lhs.components()
        let (r2, g2, b2, a2) = rhs.components()

        // Interpolation function:
        func f(_ from: CGFloat, _ to: CGFloat) -> CGFloat {
            return from * (1 - t) + to * t
        }

        // create a new color by interpolating two colors:
        return UIColor(
            red:   f(r1, r2),
            green: f(g1, g2),
            blue:  f(b1, b2),
            alpha: f(a2, a2)
        )
    }
}



// Test code:

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.itemSize = CGSize(width: 280, height: 400)
layout.minimumLineSpacing = 40

let controller = Controller(collectionViewLayout: layout)
controller.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)

PlaygroundPage.current.liveView = controller.view
导入UIKit
导入PlaygroundSupport
扩展UIColor{
func components()->(r:CGFloat,g:CGFloat,b:CGFloat,a:CGFloat){
变量r:CGFloat=0.0
变量g:CGFloat=0.0
变量b:CGFloat=0.0
变量a:CGFloat=0.0
红色(&r,绿色:&g,蓝色:&b,阿尔法:&a)
返回(r、g、b、a)
}
}
类控制器:UICollectionViewController{
//一些测试数据而不是图像:
让pages=[#colorLiteral(红色:0.2392156869,绿色:0.6745098233,蓝色:0.9686274529,α:1),#colorLiteral(红色:0.2196078449,绿色:0.007843137719,蓝色:0.854901964,α:1),#colorLiteral(红色:0.8078431487,绿色:0.0274980562,蓝色:0.3333433,α:1),#colorLiteral(红色:0.9372549057,绿色:0.3490196168,蓝色:0.1921568662,α:1),#彩色文字(红色:0.9607843161,绿色:0.7058823705,蓝色:0.20000003,α:1),#彩色文字(红色:0.4666666687,绿色:0.7647058964,蓝色:0.26666806,α:1)]
//这些应该是图像中的重要颜色:
设colorsArray=[#colorLiteral(红色:0.4745098054,绿色:0.8392156959,蓝色:0.9764705896,α:1),#colorLiteral(红色:0.5568627715,绿色:0.3529411852,蓝色:0.9686274529,α:1),#colorLiteral(红色:0.9098039269,绿色:0.4784313738,蓝色:0.6431372762,α:1),#colorLiteral(红色:0.9568627477,绿色:0.6588235497,蓝色:0.5450980663,α:1),#彩色文字(红色:0.9764705896,绿色:0.850980401,蓝色:0.5490196347,α:1),#彩色文字(红色:0.721568664,绿色:0.8862745166,蓝色:0.592156871,α:1)]
重写func viewDidLoad(){
super.viewDidLoad()
collectionView?.register(UICollectionViewCell.self,强制使用ReuseIdentifier:“单元格”)
collectionView?.contentInset=UIEdgeInSet(顶部:0,左侧:20,底部:0,右侧:20)
}
重写func collectionView(collectionView:UICollectionView,numberOfItemsInSection:Int)->Int{
返回页数.count
}
重写func collectionView(collectionView:UICollectionView,cellForItemAt indexPath:indexPath)->UICollectionViewCell{
let cell=collectionView.dequeueReusableCell(withReuseIdentifier:“cell”,for:indexath)
cell.backgroundColor=页面[indexPath.item]
返回单元
}
重写func scrollViewDidScroll(scrollView:UIScrollView){
让currentHorizontalOffset=collectionView!.contentOffset.x+collectionView!.contentInset.left
让pageWidth=scrollView.bounds.size.width
让页面=Int(最大值(0,楼层(当前水平偏移/页面宽度)))
//滚动到最后一页时不要更改背景色:
保护页UIColor
{
let(r1,g1,b1,a1)=lhs.组件()
let(r2,g2,b2,a2)=rhs.组件()
//插值函数:
func f(u-from:CGFloat,u-to:CGFloat)->CGFloat{
从*(1-t)+返回到*t
}
//通过插值两种颜色创建新颜色:
返回UIColor(
红色:f(r1,r2),
绿色:f(g1,g2),
蓝色:f(b1,b2),
α:f(a2,a2)
)
}
}
//测试代码:
let layout=UICollectionViewFlowLayout()
layout.scrollDirection=.horizontal
layout.itemSize=CGSize(宽:280,高:400)
layout.minimumLineSpacing=40
让控制器=控制器(collectionViewLayout:layout)
controller.view.frame=CGRect(x:0,y:0,宽度:320,高度:480