ios - source - uicollectionview swift 3 programmatically
¿Cómo desaparecer entre diferentes colores de fondo de un `UICollectionView` cuando el usuario se desplaza a una página diferente? (3)
La parte difícil es encontrar un color correspondiente a cada imagen. Una vez usé TDImageColors que funcionó bien: https://www.cocoacontrols.com/controls/tdimagecolors
Entonces, todo lo que tienes que hacer es pasar de un color a otro. Como en @Tonton respuesta.
Intento replicar el menú de listados de eBay en su aplicación de iOS, en el que los usuarios pueden desplazarse por diferentes imágenes de una lista. Noté que el color de fondo es un color sólido que reproduce los colores envolventes del fondo en cada imagen.
A medida que me desplazo por una imagen diferente (página diferente) con un fondo envolvente diferente, el fondo real de UICollectionView
cambia para reflejarlo de alguna manera.
Esto es lo que quiero decir:
Como puede ver en la primera imagen, el fondo es de color claro, algo parecido al fondo de la imagen. A medida que avanzo hasta la mitad de la segunda imagen, el fondo se oscurece.
Finalmente:
Mi configuración es similar:
Usando DominantColor , pude establecer el color de fondo de UICollectionView
con el color dominante de cada UIImage
. A medida que el usuario se desplaza a mitad de camino entre la primera y la segunda página, el color de fondo de UICollectionView
se establece en el color dominante de la segunda página de 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]
})
}
}
Sin embargo, estoy teniendo dificultades para hacer una transición lenta del color de fondo actual al siguiente color de fondo tan pronto como el usuario comience a desplazarse, como se ve en la segunda imagen de arriba.
La forma en que se implementa actualmente como se scrollViewDidScroll
arriba en scrollViewDidScroll
, comienza a desvanecerse en el siguiente color cuando la página se desplaza a mitad de camino entre la página siguiente, y con una animación de 1 segundo , se convertirá en ese color en 1 segundo, independientemente de si la siguiente página está a la mitad o totalmente mostrada.
¿Cómo puedo conseguir esto?
Si el cambio de color necesita estar sincronizado con el desplazamiento, es decir, cambiando gradualmente el color, probablemente desee los cambios en scrollViewDidScroll utilizando la vista de desplazamiento desde su colección.
Al obtener el color de la imagen de fondo (quizás usando la respuesta de Mike JS Choi), puede comparar sus diferencias. Usando el valor de desplazamiento de 0 a 1, puede cambiar el color gradualmente.
Usa alguna variable local para que el método sepa cuál es tu imagen actual
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(¤tRed, green: ¤tGreen, blue: ¤tBlue, alpha: ¤tAlpha)
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
}
Por lo tanto, tendrá que descubrir cómo almacenar su imagen actual y obtener la siguiente imagen (que podría estar desplazando hacia adelante y hacia atrás), y luego usarla dentro del método scrollViewDidScroll. glhf fam
Utilizando la respuesta de Fogmeister en obj-C y la conversión del usuario3344977 a Swift, así como la guía de Tonton , se me ocurrió la siguiente solución:
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)
}
Ahora, cuando el usuario comienza a desplazarse a la página siguiente / anterior, el color de fondo cambiará lentamente debido al cambio de color alfa en el percentageHorizontalOffset
Disparo percentageHorizontalOffset
.
Gracias a todos los mencionados!