UICollectionView Paginación horizontal no centrada
Tengo una collectionView de desplazamiento horizontal con cada celda del tamaño de la vista. Cuando navego a través de collectionView, no lo hace por celda. Las celdas no están en el centro de la pantalla. He intentado un montón de cosas para tratar de arreglarlo y no he tenido suerte. Aquí hay un video del problema: https://www.youtube.com/watch?v=tXsxWelk16w Alguna idea?
10 answers
Elimine los espacios entre los elementos. Para la vista de colección de desplazamiento horizontal, establezca el espaciado mínimo de líneas en 0. Puede hacer esto con interface builder o con el método del protocolo UICollectionViewDelegateFlowLayout
:
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 0;
}
Otra forma es hacer que el ancho de su celda sea menor que el ancho de collectionView para un valor de espacio horizontal entre los elementos. Luego agregue inserciones de sección con inserciones de izquierda y derecha que equivalgan a la mitad del espacio horizontal entre los elementos. Por ejemplo, el interlineado mínimo es 10:
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 10;
}
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(collectionView.frame.size.width - 10, collectionView.frame.size.height);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 5, 0, 5);
}
Y tercera manera: manipular el desplazamiento collectionView en el método scrollViewDidEndDecelerating:
:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (scrollView == self.collectionView) {
CGPoint currentCellOffset = self.collectionView.contentOffset;
currentCellOffset.x += self.collectionView.frame.size.width / 2;
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:currentCellOffset];
[self.collectionView scrollToItemAtIndexPath:indexPath
atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
animated:YES];
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-16 06:25:01
Demo aquí en Swift 3 : https://github.com/damienromito/CollectionViewCustom
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let pageWidth = Float(itemWidth + itemSpacing)
let targetXContentOffset = Float(targetContentOffset.pointee.x)
let contentWidth = Float(collectionView!.contentSize.width )
var newPage = Float(self.pageControl.currentPage)
if velocity.x == 0 {
newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth)) + 1.0
} else {
newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1)
if newPage < 0 {
newPage = 0
}
if (newPage > contentWidth / pageWidth) {
newPage = ceil(contentWidth / pageWidth) - 1.0
}
}
self.pageControl.currentPage = Int(newPage)
let point = CGPoint (x: CGFloat(newPage * pageWidth), y: targetContentOffset.pointee.y)
targetContentOffset.pointee = point
}
Swift 4:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let pageWidth = Float(itemWidth + itemSpacing)
let targetXContentOffset = Float(targetContentOffset.pointee.x)
let contentWidth = Float(collectionView!.contentSize.width )
var newPage = Float(self.pageControl.currentPage)
if velocity.x == 0 {
newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth)) + 1.0
} else {
newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1)
if newPage < 0 {
newPage = 0
}
if (newPage > contentWidth / pageWidth) {
newPage = ceil(contentWidth / pageWidth) - 1.0
}
}
self.pageControl.currentPage = Int(newPage)
let point = CGPoint (x: CGFloat(newPage * pageWidth), y: targetContentOffset.pointee.y)
targetContentOffset.pointee = point
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-16 19:31:49
Versión rápida de @vlad-che respuesta aceptada:
extension GoodsViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frameSize = collectionView.frame.size
return CGSize(width: frameSize.width - 10, height: frameSize.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-04 08:42:52
Ser capaz de tener celdas que son más pequeñas el marco collectionView
con espacio entre las celdas permite insinuar al usuario que hay otras celdas a cada lado para desplazarse a lo que es una gran victoria para UX. Pero para el centrado de las páginas no funciona como se esperaba con cada celda cada vez más desplazamiento a medida que el usuario se desplaza. He encontrado que lo siguiente funciona bien. La animación de centrado/ajuste en cada celda es casi invisible para el usuario, ya que solo está ajustando donde el desplazamiento collectionView
terminaría naturalmente en lugar de sacudir el collectionView
para desplazarse rápidamente a otro indexPath
. Todavía es importante tener la propiedad sectionInset
lo suficientemente grande como para permitir que cell no se adhiera a los bordes del marco que contiene. Además, dado que hay espacios entre las celdas, el objetivo podría aterrizar en un indexPath
de nil, lo que haría que el collectionView
se desplace hacia atrás hasta el inicio. He arreglado esta compensación un poco y luego intentarlo de nuevo, pero diferentes enfoques podrían tomarse aquí.
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
{
//Ensure the scrollview is the collectionview we care about
if (scrollView == self.collectionView) {
// Find cell closest to the frame centre with reference from the targetContentOffset.
CGPoint frameCentre = self.collectionView.center;
CGPoint targetOffsetToCentre = CGPointMake((* targetContentOffset).x + frameCentre.x, (* targetContentOffset).y + frameCentre.y);
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:targetOffsetToCentre];
//Check for "edgecase" that the target will land between cells and then find a close neighbour to prevent scrolling to index {0,0}.
while (!indexPath) {
targetOffsetToCentre.x += ((UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout).minimumInteritemSpacing;
indexPath = [self.collectionView indexPathForItemAtPoint:targetOffsetToCentre];
}
// Find the centre of the target cell
CGPoint centreCellPoint = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath].center;
// Calculate the desired scrollview offset with reference to desired target cell centre.
CGPoint desiredOffset = CGPointMake(centreCellPoint.x - frameCentre.x, centreCellPoint.y - frameCentre.y);
*targetContentOffset = desiredOffset;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-16 15:21:05
Swift 3
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if scrollView == self.collectionView {
var currentCellOffset = self.collectionView.contentOffset
currentCellOffset.x += self.collectionView.frame.width / 2
if let indexPath = self.collectionView.indexPathForItem(at: currentCellOffset) {
self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-09 11:53:45
Swift 3.0 establezca su propio UICollectionViewFlowLayout
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let width = UIScreen.main.bounds.width
layout.itemSize = CGSize(width: width, height: 154)
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.scrollDirection = .horizontal
collectionView?.collectionViewLayout = layout
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-10 10:59:42
Después de tener un problema similar, arreglé el mío al darme cuenta de que cuando se usa el desplazamiento horizontal la altura es ahora el ancho y el ancho es ahora la altura porque el valor predeterminado es el desplazamiento vertical. Intente cambiar los valores y vea si eso ayuda. https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/UsingtheFlowLayout/UsingtheFlowLayout.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-05 16:43:57
El código que acabo de ver de las Guías Oficiales de Apple y el Código de muestra:
AssetViewController.swift:
self.collectionView?.isPagingEnabled = true
self.collectionView?.frame = view.frame.insetBy(dx: -20.0, dy: 0.0)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-10 14:03:31
Swift 4 solución para eliminar el espaciado entre líneas para mantener las celdas centradas:
public func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-09 21:45:32
Solución Swift 3 basada en la respuesta de @Santos, para usar si tienes una vista regular de colección de paginación horizontal sin un control de página como Paolo estaba usando en su ejemplo Swift 3.
Utilicé esto para resolver un problema en el que una celda de paginación horizontal celdas de pantalla completa con un animador de UICollectionViewFlowLayout personalizado no terminó de girar Y terminó desplazado para que los bordes de un marco de celda de pantalla completa fueran cada vez más horizontalmente límites de la vista de colección a medida que se desplaza (como en el vídeo compartido).
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
// Ensure the scrollview is the one on the collectionView we care are working with
if (scrollView == self.collectionView) {
// Find cell closest to the frame centre with reference from the targetContentOffset.
let frameCenter: CGPoint = self.collectionView.center
var targetOffsetToCenter: CGPoint = CGPoint(x: targetContentOffset.pointee.x + frameCenter.x, y: targetContentOffset.pointee.y + frameCenter.y)
var indexPath: IndexPath? = self.collectionView.indexPathForItem(at: targetOffsetToCenter)
// Check for "edge case" where the target will land right between cells and then next neighbor to prevent scrolling to index {0,0}.
while indexPath == nil {
targetOffsetToCenter.x += 10
indexPath = self.collectionView.indexPathForItem(at: targetOffsetToCenter)
}
// safe unwrap to make sure we found a valid index path
if let index = indexPath {
// Find the centre of the target cell
if let centerCellPoint: CGPoint = collectionView.layoutAttributesForItem(at: index)?.center {
// Calculate the desired scrollview offset with reference to desired target cell centre.
let desiredOffset: CGPoint = CGPoint(x: centerCellPoint.x - frameCenter.x, y: centerCellPoint.y - frameCenter.y)
targetContentOffset.pointee = desiredOffset
}
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-06 20:44:54