objective-c - uicollectionview resize cell
Autoreizing issue of UICollectionViewCell El marco de contentView en la celda del prototipo Storyboard(Xcode 6, iOS 8 SDK) ocurre cuando se ejecuta en iOS 7 solamente (12)
En Xcode 6.0.1, contentView para UICollectionViewCell está roto para dispositivos iOS7. También se puede solucionar agregando restricciones adecuadas a UICollectionViewCell y su contentView en los métodos awakeFromNib o init.
UIView *cellContentView = self.contentView;
cellContentView.translatesAutoresizingMaskIntoConstraints = NO;
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[cellContentView]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(cellContentView)]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[cellContentView]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(cellContentView)]];
Estoy usando Xcode 6 Beta 3, iOS 8 SDK. Build Target iOS 7.0 usando Swift. Por favor, consulte mi problema paso a paso con capturas de pantalla a continuación.
Tengo un UICollectionView en Storyboard. 1 Prototipo UICollectionViewCell que contiene 1 etiqueta en el centro (sin regla de autoimpresión). El fondo púrpura era para marcar una ContentView que se genera en tiempo de ejecución por la célula, supongo. Esa vista se redimensionará correctamente en base a mi UICollectionViewLayoutDelegate eventualmente, pero no en iOS 7. Tenga en cuenta que estoy usando Xcode 6 y que el problema solo ocurre en iOS 7.
Cuando construyo la aplicación en iOS 8. Todo está bien.
Nota: Purple es el contentView , Blue es mi UIButton con la esquina redondeada.
Sin embargo, en iOS 7, todas las subViews dentro de la Celda se reducen repentinamente al marco de (0,0,50,50) y nunca se ajustan a mi regla Autoresizing.
Supongo que esto es un error en iOS 8 SDK o Swift o tal vez Xcode?
Actualización 1: ¡ Este problema todavía existe en el Xcode oficial 6.0.1! El mejor trabajo es como lo que KoCMoHaBTa sugirió a continuación al establecer el marco en cellForItem de la celda (sin embargo, debe subclasificar su celda). Resultó ser una incompatibilidad entre iOS 8 SDK e iOS 7 (consulte la respuesta de ecotax a continuación citada de Apple).
Actualización 2: pegue este código al comienzo de su cellForItem y las cosas deberían estar bien:
/** Xcode 6 on iOS 7 hot fix **/
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
/** End of Xcode 6 on iOS 7 hot fix **/
En breve, coloque el siguiente código en la subclase de la celda de vista de colección:
override var bounds : CGRect {
didSet {
// Fix autolayout constraints broken in Xcode 6 GM + iOS 7.1
self.contentView.frame = bounds
}
}
Encontré el mismo problema y le pedí ayuda a Apple DTS. Su respuesta fue:
En iOS 7, las vistas de contenido de las celdas se clasifican a sí mismas a través de máscaras de aumento automático. En iOS 8, esto se modificó, las células dejaron de usar las máscaras de aumento automático y comenzaron a dimensionar la vista de contenido en layoutSubviews. Si un plumín está codificado en iOS 8 y luego decodificado en iOS 7, tendrá una vista de contenido sin una máscara de aumento de tamaño y sin otro medio para dimensionarse. Entonces, si alguna vez cambia el marco de la celda, la vista de contenido no seguirá.
Las aplicaciones que se están implementando en iOS 7 tendrán que solucionar esto dimensionando la vista de contenido en sí, agregando máscaras de aumento automático o agregando restricciones.
Supongo que esto significa que no es un error en XCode 6, sino una incompatibilidad entre el SDK de iOS 8 y el SDK de iOS 7, que te afectará si actualizas a Xcode 6, ya que comenzará a usar automáticamente el iOS 8 SDK.
Como comenté antes, la solución alternativa que Daniel Plamann describió fue para mí. Los descritos por Igor Palaguta y KoCMoHaBTa parecen más sencillos, y parecen tener sentido para dar la respuesta de Apple DTS, así que los probaré más adelante.
Esta es la versión Swift de la respuesta de @ Igor que es aceptada y gracias por su agradable respuesta compañero.
Primero, UICollectionViewCell
su Subclase UICollectionViewCell
y pegue el siguiente código tal como está dentro de la clase.
override func awakeFromNib() {
super.awakeFromNib()
self.contentView.frame = self.bounds
self.contentView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
}
Por cierto, estoy usando Xcode 7.3.1 y Swift 2.3. La solución se prueba en iOS 9.3, que funciona a la perfección.
Gracias, espero que esto haya ayudado.
Esto no funcionará correctamente sin ninguna de las otras soluciones mencionadas debido a un error en Xcode 6 GM con la forma en que Xcode compila los archivos xib en formato de punta. Si bien no puedo decir con certeza al 100% que esté relacionado con Xcode y que no tenga que ver con el tiempo de ejecución, tengo mucha confianza; así es como puedo mostrarlo:
- Build + Ejecuta la aplicación en Xcode 5.1.
- Vaya al directorio de la aplicación del simulador y copie el archivo .nib compilado para el xib con el que tiene problemas.
- Build + Ejecuta la aplicación en Xcode 6 GM.
- Detener la aplicación
- Reemplace el archivo .nib en la carpeta del simulador de la nueva aplicación con el archivo .nib creado con Xcode 5.1
- Reinicia la aplicación desde el simulador, NO desde Xcode.
- Su célula cargada desde ese .nib debería funcionar como se espera.
Espero que todos los que lean esta pregunta archiven un Radar con Apple. Este es un tema ENORME y debe abordarse antes de la versión final de Xcode.
Editar: A la luz de la publicación de ecotax , solo quería actualizar esto para decir que ahora hay diferencias de comportamiento confirmadas entre construir en iOS 8 vs iOS 7, pero no es un error. Mi truco solucionó el problema porque la construcción de iOS 7 agregaba la máscara de aumento automático a la vista de contenido necesaria para hacer que esto funcionara, lo que Apple ya no agrega.
He descubierto que también existen problemas con el dimensionamiento de contentView
en iOS 8. Tiende a establecerse muy tarde en el ciclo, lo que puede causar conflictos temporales de restricciones. Para resolver esto, agregué el siguiente método en una categoría de UICollectionViewCell
:
- (void)fixupContentView
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80100
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
self.contentView.frame = self.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
} else {
[self layoutIfNeeded];
}
#endif
#endif
}
Este método debe invocarse después de eliminar la célula.
Las respuestas en este post funcionan, lo que nunca entendí es por qué funciona.
Primero, hay dos "reglas":
- Para las vistas creadas mediante programación (Ej.
[UIView new]
), la propiedad[UIView new]
está establecida enYES
- Las vistas creadas en el constructor de interfaz, con AutoLayout habilitado, tendrán la propiedad
translatesAutoresizingMaskIntoConstraints
establecida enNO
La segunda regla no parece aplicarse a las vistas de nivel superior para las que no define restricciones. (Por ejemplo, la vista de contenido)
Al mirar una celda Storyboard, observe que la celda no tiene su contentView
expuesto. No estamos "controlando" el contentView
, Apple sí.
Profundice en el código fuente del guión gráfico y vea cómo se contentView
celda contentView
:
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
Ahora las subvistas de la celda (observe las translatesAutoresizingMaskIntoConstraints="NO"
):
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NaT-qJ-npL" userLabel="myCustomLabel">
contentView
no tiene sus contentView
establecido en NO
. Además, carece de definición de diseño, tal vez por lo que dijo @ecotax .
Si miramos en el contentView
, tiene una máscara de aumento de tamaño, pero no hay definición para él: <autoresizingMask key="autoresizingMask"/>
Entonces hay dos conclusiones:
-
contentView
está establecido enYES
. -
contentView
carece de definición de un diseño.
Esto nos lleva a dos soluciones de las que se ha hablado.
Puede configurar las máscaras de aumento automático manualmente en awakeFromNib
:
self.contentView.frame = cell.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
O puede configurar contentView
a NO
en awakeFromNib
y define restricciones en - (void)updateConstraints
.
Lo arreglé haciendo esto:
override func layoutSubviews() {
contentView.superview?.frame = bounds
super.layoutSubviews()
}
ver: here
Me encontré con el mismo problema y espero que Apple lo solucione con la próxima versión de Xcode. Mientras tanto uso una solución alternativa. En mi subclase UICollectionViewCell
, he reemplazado a layoutSubviews
y cambio el tamaño de contentView manualmente en caso de que el tamaño difiera del tamaño de collectionViewCell
.
- (void)layoutSubviews
{
[super layoutSubviews];
BOOL contentViewIsAutoresized = CGSizeEqualToSize(self.frame.size, self.contentView.frame.size);
if( !contentViewIsAutoresized) {
CGRect contentViewFrame = self.contentView.frame;
contentViewFrame.size = self.frame.size;
self.contentView.frame = contentViewFrame;
}
}
Otra solución es establecer el tamaño de contentView y las máscaras de aumento de tamaño en -collectionView: cellForItemAtIndexPath: como el siguiente:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"CellID";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
//set contentView frame and autoresizingMask
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
//You custom code goes here
return cell;
}
Esto también funciona con Diseño automático, ya que las máscaras de cambio de tamaño automático se traducen en restricciones.
Solo asegúrese de marcar la casilla de verificación "Autoresize subviews" en el plumín para esa celda de vista de colección. Funcionará bien tanto en iOS 8 como en iOS 7.
contentView está roto. También se puede arreglar en awakeFromNib
ObjC:
-(void)awakeFromNib
{
[super awakeFromNib];
self.contentView.frame = self.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
Swift3:
override func awakeFromNib() {
super.awakeFromNib()
self.contentView.frame = self.bounds
self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}