ios - pueda - que son los formatos numericos personalizados
El ajuste de altura de fila de celda personalizado en el guión gráfico no responde (18)
Estoy intentando ajustar la altura de la celda para una de las celdas en mi vista de tabla. Estoy ajustando el tamaño desde la configuración de "altura de fila" dentro del "inspector de tamaño" de la celda en cuestión. Cuando ejecuto la aplicación en mi iPhone, la celda tiene el tamaño predeterminado establecido en el "tamaño de fila" en la vista de tabla.
Si cambio el "tamaño de fila" de la vista de tabla, entonces cambia el tamaño de todas las celdas. No quiero hacer eso porque quiero un tamaño personalizado solo para una celda. He visto muchas publicaciones que tienen una solución programática para el problema, pero preferiría hacerlo a través del guión gráfico, si eso es posible.
Abra el guión gráfico en la vista XML e intente editar el atributo rowHeight
del elemento deseado.
Funcionó para mí cuando intenté establecer rowHeight personalizado para mi fila de prototipos. No funciona a través de inspector, pero a través de XML funciona.
Creo que es un error.
Intente ajustar la altura no por el inspector de utilidades, sino arrastrando el mouse directamente en el guión gráfico.
Resolví este problema con este método.
Dado que no encontré ninguna solución a este problema a través de Interface Builder, decidí publicar una solución programática para el problema en Swift utilizando dos celdas dinámicas , aunque la pregunta inicial pedía una solución a través de Interface Builder. Independientemente, creo que podría ser útil para la comunidad de desbordamiento de pila:
import UIKit
enum SignInUpMenuTableViewControllerCellIdentifier: String {
case BigButtonCell = "BigButtonCell"
case LabelCell = "LabelCell"
}
class SignInUpMenuTableViewController: UITableViewController {
let heightCache = [SignInUpMenuTableViewControllerCellIdentifier.BigButtonCell : CGFloat(50),
SignInUpMenuTableViewControllerCellIdentifier.LabelCell : CGFloat(115)]
private func cellIdentifierForIndexPath(indexPath: NSIndexPath) -> SignInUpMenuTableViewControllerCellIdentifier {
if indexPath.row == 2 {
return SignInUpMenuTableViewControllerCellIdentifier.LabelCell
} else {
return SignInUpMenuTableViewControllerCellIdentifier.BigButtonCell
}
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return self.heightCache[self.cellIdentifierForIndexPath(indexPath)]!
}
...
}
El mismo problema ocurrió al trabajar en XCode 9 usando Swift 4 .
Agregar AutoLayout para los elementos de la IU dentro de la celda y la altura de la fila de celdas personalizada funcionará en consecuencia como se especifica.
En realidad, hay dos lugares donde debe cambiar a la altura de la fila, primero la celda (ya lo cambió) y ahora seleccione la Vista de tabla y verifique el Inspector de tamaño
He creado el código que indican las diversas respuestas / comentarios para que esto funcione para guiones gráficos que usan celdas prototipo.
Este codigo
- No requiere que la altura de la celda se establezca en otro lugar que no sea el lugar obvio en el guión gráfico
- Caches la altura por motivos de rendimiento.
- Utiliza una función común para obtener el identificador de celda para una ruta de índice para evitar la lógica duplicada
Gracias a Answerbot, Brennan y lensovet.
- (NSString *)cellIdentifierForIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = nil;
switch (indexPath.section)
{
case 0:
cellIdentifier = @"ArtworkCell";
break;
<... and so on ...>
}
return cellIdentifier;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [self cellIdentifierForIndexPath:indexPath];
static NSMutableDictionary *heightCache;
if (!heightCache)
heightCache = [[NSMutableDictionary alloc] init];
NSNumber *cachedHeight = heightCache[cellIdentifier];
if (cachedHeight)
return cachedHeight.floatValue;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
CGFloat height = cell.bounds.size.height;
heightCache[cellIdentifier] = @(height);
return height;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [self cellIdentifierForIndexPath:indexPath];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
<... configure cell as usual...>
La única solución real que pude encontrar es esta
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = ...; // Instantiate with a "common" method you''ll use again in cellForRowAtIndexPath:
return cell.frame.size.height;
}
Esto funciona y permite no tener un interruptor horrible / si se duplica la lógica en el StoryBoard. No estoy seguro del rendimiento, pero supongo que al llegar a cellForRow:
la celda que se está inicializando es tan rápida. Por supuesto, es probable que haya daños colaterales aquí, pero parece que aquí me funciona bien.
También publiqué esto aquí: https://devforums.apple.com/message/772464
EDITAR: Ortwin Gentz me recordó que heightForRowAtIndexPath:
se llamará para todas las celdas de TableView, no solo las visibles. Suena lógico ya que iOS necesita saber la altura total para poder mostrar las barras de desplazamiento correctas. Significa que probablemente esté bien en las TableViews pequeñas (como 20 celdas), pero olvídalo en una TableView de 1000 celdas.
Además, el truco anterior con XML: igual que el primer comentario para mí. El valor correcto ya estaba allí.
Otra cosa que puedes hacer es ir a tu Esquema del documento, seleccionar la vista de tabla en la que está anidada tu celda prototipo. Luego, en el Inspector de tamaño, cambie la altura de fila de la vista de tabla al valor deseado y desactive la casilla Automático.
Para las celdas dinámicas, el conjunto rowHeight
en UITableView
siempre reemplaza a UITableView
las celdas individuales.
Este comportamiento es, IMO, un error. Cada vez que tenga que administrar su interfaz de usuario en dos lugares, es propenso a errores. Por ejemplo, si cambia el tamaño de su celda en el guión gráfico, debe recordar cambiarlos también en el heightForRowAtIndexPath:
Hasta que Apple corrija el error, la mejor solución actual es anular heightForRowAtIndexPath:
pero usa las celdas prototipo reales del guión gráfico para determinar la altura en lugar de usar números mágicos . Aquí hay un ejemplo:
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
/* In this example, there is a different cell for
the top, middle and bottom rows of the tableView.
Each type of cell has a different height.
self.model contains the data for the tableview
*/
static NSString *CellIdentifier;
if (indexPath.row == 0)
CellIdentifier = @"CellTop";
else if (indexPath.row + 1 == [self.model count] )
CellIdentifier = @"CellBottom";
else
CellIdentifier = @"CellMiddle";
UITableViewCell *cell =
[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
return cell.bounds.size.height;
}
Esto asegurará que cualquier cambio en las alturas de las celdas de su prototipo se detectará automáticamente en el tiempo de ejecución y solo necesita administrar su UI en un solo lugar: el guión gráfico.
Para las celdas dinámicas, el conjunto rowHeight en UITableView siempre reemplaza a rowHeight de las celdas individuales. Simplemente calcule la altura dinámica si el contenido dentro de la fila.
Puede obtener la altura de UITableviewCell (en UITableviewController - celdas estáticas) desde el guión gráfico con la ayuda de las siguientes líneas.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat height = [super tableView:tableView heightForRowAtIndexPath:indexPath];
return height;
}
Puede usar cells
prototipo con una height
personalizada y luego invocar cellForRowAtIndexPath:
y devolver su frame.height
.:.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableView:tableView
cellForRowAtIndexPath:indexPath];
return cell.frame.size.height;
}
Recientemente he estado luchando con esto. Mi problema fue que las soluciones publicadas arriba usando el método heightForRowAtIndexPath:
funcionaban para iOS 7.1 en el simulador, pero luego han arruinado los resultados simplemente cambiando a iOS 8.1.
Comencé a leer más sobre las celdas de auto-dimensionamiento (introducidas en iOS 8, lea aquí ). Era evidente que el uso de UITableViewAutomaticDimension
ayudaría en iOS 8. Intenté usar esa técnica y heightForRowAtIndexPath:
el uso de heightForRowAtIndexPath:
y voila, estaba funcionando perfectamente en iOS 8 ahora. Pero entonces iOS 7 no lo era. ¿Qué iba a hacer yo? Necesitaba heightForRowAtIndexPath:
para iOS 7 y no para iOS 8.
Aquí está mi solución (recortada por razones de brevedad) que se toma prestada de la respuesta @JosephH publicada anteriormente:
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 50.;
self.tableView.rowHeight = UITableViewAutomaticDimension;
// ...
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
return UITableViewAutomaticDimension;
} else {
NSString *cellIdentifier = [self reuseIdentifierForCellAtIndexPath:indexPath];
static NSMutableDictionary *heightCache;
if (!heightCache)
heightCache = [[NSMutableDictionary alloc] init];
NSNumber *cachedHeight = heightCache[cellIdentifier];
if (cachedHeight)
return cachedHeight.floatValue;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
CGFloat height = cell.bounds.size.height;
heightCache[cellIdentifier] = @(height);
return height;
}
}
- (NSString *)reuseIdentifierForCellAtIndexPath:(NSIndexPath *)indexPath {
NSString * reuseIdentifier;
switch (indexPath.row) {
case 0:
reuseIdentifier = EventTitleCellIdentifier;
break;
case 2:
reuseIdentifier = EventDateTimeCellIdentifier;
break;
case 4:
reuseIdentifier = EventContactsCellIdentifier;
break;
case 6:
reuseIdentifier = EventLocationCellIdentifier;
break;
case 8:
reuseIdentifier = NotesCellIdentifier;
break;
default:
reuseIdentifier = SeparatorCellIdentifier;
break;
}
return reuseIdentifier;
}
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO (@ "8.0") en realidad proviene de un conjunto de definiciones de macro que estoy usando, que encontré en algún lugar (muy útil). Se definen como:
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
Se agregó como un comentario, pero se publicó como una respuesta para la visibilidad:
También parece haber un problema si inicialmente configura una vista de tabla como "celdas estáticas" y luego la cambia a "prototipos dinámicos". Tuve un problema en el que incluso el método de delegado para heightForRowAtIndexPath
estaba siendo ignorado. Primero lo resolví editando directamente el XML del guión gráfico, luego, finalmente, simplemente reconstruí la escena del guión gráfico desde cero, usando prototipos dinámicos desde el principio.
Si desea establecer una altura de fila estática, puede hacer algo como esto:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 120;
}
Si estás usando swift, usa así. No utilice el guión gráfico para seleccionar la altura de la fila. Programar la altura de la fila de la tabla de esta manera,
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 || indexPath.row == 1{
let cell = self.tableView.dequeueReusableCellWithIdentifier("section1", forIndexPath: indexPath) as! Section1TableViewCell
self.tableView.rowHeight = 150
cell.label1.text = "hiiiiii"
cell.label2.text = "Huiiilllllll"
return cell
} else {
let cell = self.tableView.dequeueReusableCellWithIdentifier("section2", forIndexPath: indexPath) as! Section2TableViewCell
self.tableView.rowHeight = 60
cell.label3.text = "llll"
return cell
}
}
Si usa UITableViewController, implemente este método:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
En la función de una fila puede elegir Altura. Por ejemplo,
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
return 100;
}
else {
return 60;
}
}
En este ejemplo, la altura de la primera fila es de 100 píxeles, y las otras son de 60 píxeles.
Espero que este te pueda ayudar.
En las celdas dinámicas , el conjunto rowHeight
en UITableView siempre reemplaza a rowHeight de las celdas individuales.
Pero en las celdas estáticas , el conjunto de rowHeight
en celdas individuales puede anular las de UITableView.
¿No está seguro si es un error, Apple podría estar haciendo esto intencionalmente?