ios - tablas - Cómo crear una UITableViewCell personalizada mediante programación mediante AutoLayout
uitableview in swift 4 (2)
Hay varias cosas mal con su código. Primero, creo que encontrará, si realiza algún registro, que nunca se llama a updateConstraints. Pondría todo el código en el método init. Además, hay varias cosas mal en sus restricciones. La restricción en la que establece la altura en 44 no es necesaria ya que ya tiene las etiquetas ancladas en la parte inferior y posterior de la celda. No sé qué estás tratando de hacer con ese último, parece que eso haría que el nombre Label tenga un punto de ancho. Además, no debe establecer traduceAutoresizingMaskIntoConstraints en NO para la vista de contenido, que causa efectos extraños. Este es el código que creo que quieres:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
reuseID = reuseIdentifier;
nameLabel = [[UILabel alloc] init];
[nameLabel setTextColor:[UIColor blackColor]];
[nameLabel setBackgroundColor:[UIColor colorWithHue:32 saturation:100 brightness:63 alpha:1]];
[nameLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]];
[nameLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:nameLabel];
mainLabel = [[UILabel alloc] init];
[mainLabel setTextColor:[UIColor blackColor]];
[mainLabel setBackgroundColor:[UIColor colorWithHue:66 saturation:100 brightness:63 alpha:1]];
[mainLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]];
[mainLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:mainLabel];
NSDictionary *views = NSDictionaryOfVariableBindings(nameLabel, mainLabel);
if (reuseID == kCellIDTitle) {
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|"
options: 0
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel]|"
options: 0
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
}
if (reuseID == kCellIDTitleMain) {
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|"
options:0
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mainLabel]|"
options: 0
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel][mainLabel(==nameLabel)]|"
options: 0
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
}
}
return self;
}
Estoy tratando de implementar una UITableView que se comportará de manera similar a la línea de tiempo de un cliente de Twitter. En este momento, simplemente estoy tratando de obtener dos etiquetas dentro de una UITableViewCell. Tal como lo recomienda esta respuesta de desbordamiento de pila , estoy usando un reuseIdentifier diferente para cada diseño. Mis diseños son simples, que constan de una sola etiqueta o dos etiquetas. Eventualmente ajustaré la altura de las UITableViewCells pero primero necesito que las celdas se llenen de contenido.
Puedo obtener las etiquetas para que aparezcan si establezco su marco con initWithFrame:
sin embargo, las restricciones no se están implementando.
Pregunta: ¿Qué impide que aparezcan las etiquetas y las restricciones? Me falta algo en mi implementación del UITableViewCell, pero no tengo idea de qué se trata.
Pregunta secundaria: ¿estoy registrando la clase UITableViewCell correctamente para cada reuseIdentifier en
viewDidLoad
?
Esto puede parecer difícil, pero Interface Builder me confunde, me gustaría lograr todo esto en el código.
Aquí está el código para la UITableViewCell personalizada llamada TVTCell.h:
static NSString * const kCellIDTitle = @"CellWithTitle";
static NSString * const kCellIDTitleMain = @"CellWithTitleMain";
@interface TVTCell : UITableViewCell
{
NSString *reuseID;
}
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *mainLabel;
@end
Y TVTCell.m:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
reuseID = reuseIdentifier;
nameLabel = [[UILabel alloc] init];
[nameLabel setTextColor:[UIColor blackColor]];
[nameLabel setBackgroundColor:[UIColor colorWithHue:32 saturation:100 brightness:63 alpha:1]];
[nameLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]];
[nameLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:nameLabel];
mainLabel = [[UILabel alloc] init];
[mainLabel setTextColor:[UIColor blackColor]];
[mainLabel setBackgroundColor:[UIColor colorWithHue:66 saturation:100 brightness:63 alpha:1]];
[mainLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]];
[mainLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:mainLabel];
[self.contentView setTranslatesAutoresizingMaskIntoConstraints:NO];
}
return self;
}
- (void)updateConstraints
{
[super updateConstraints];
NSDictionary *views = NSDictionaryOfVariableBindings(nameLabel, mainLabel);
if (reuseID == kCellIDTitle) {
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|"
options: NSLayoutFormatAlignAllCenterX
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel]|"
options: NSLayoutFormatAlignAllCenterX
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
}
if (reuseID == kCellIDTitleMain) {
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|"
options: NSLayoutFormatAlignAllCenterX
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mainLabel]|"
options: NSLayoutFormatAlignAllCenterX
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel][mainLabel]|"
options: NSLayoutFormatAlignAllLeft
metrics:nil
views:views];
[self.contentView addConstraints:constraints];
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:nameLabel
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0.0
constant:44.0]];
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:nameLabel
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.contentView
attribute:NSLayoutAttributeNotAnAttribute
multiplier:0.0
constant:1]];
}
}
Lo siento, toneladas de código. Aquí está mi tableView de tableView:cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0 || indexPath.row == 2 || indexPath.row == 3) {
TVTCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIDTitle forIndexPath:indexPath];
[[cell nameLabel] setText:[nameArray objectAtIndex:indexPath.row]];
return cell;
} else if (indexPath.row == 1 || indexPath.row == 4 || indexPath.row == 5) {
TVTCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIDTitleMain forIndexPath:indexPath];
[[cell nameLabel] setText:[nameArray objectAtIndex:indexPath.row]];
[[cell mainLabel] setText:[dataArray objectAtIndex:indexPath.row]];
return cell;
} else
{
UITableViewCell *badCell = [[UITableViewCell alloc] init];
NSLog(@"Warning! returning a cell that shouldnt be here");
badCell.textLabel.text = @"Warning!";
return badCell;
}
}
Y, por último, el método viewDidLoad de UITableView:
- (void)viewDidLoad
{
[super viewDidLoad];
[[self tableView] registerClass:[TVTCell class] forCellReuseIdentifier:kCellIDTitle];
[[self tableView] registerClass:[TVTCell class] forCellReuseIdentifier:kCellIDTitleMain];
}
Puede crear UITableViewCell programáticamente en swift 4 usando auto-layout como se muestra a continuación. No es exactamente la solución de su problema anterior como usted especificó en la pregunta. Es una implementación más genérica de cómo crear la celda Tableview programáticamente en swift usando el diseño automático:
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(CustomCell2.self, forCellReuseIdentifier: "cell")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? CustomCell2 else { return UITableViewCell() }
cell.model = CellModel(labelString: "set constriant by code")
return cell
}
}
Definir modelo:
struct CellModel {
let labelString : String
}
Definir celda personalizada:
class CustomCell2 : UITableViewCell {
private let label : UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false // enable auto layout
label.backgroundColor = .green // to visualize the background of label
label.textAlignment = .center // center text alignment
return label
}()
private func addLabel() {
addSubview(label)
NSLayoutConstraint.activate([
// label width is 70% of cell width
label.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.7),
// label is horizontally center of cell
label.centerXAnchor.constraint(equalTo: centerXAnchor)
])
}
var model : CellModel? {
didSet {
label.text = model?.labelString ?? ""
}
}
// Init
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
addLabel()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}