Personalizar la sección de encabezado UITableView


141

Quiero personalizar el UITableViewencabezado para cada sección. Hasta ahora, he implementado

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

Este UITabelViewDelegatemétodo Lo que quiero hacer es obtener el encabezado actual para cada sección y simplemente agregarlo UILabelcomo una subvista.

Hasta ahora, no puedo lograr eso. Porque no pude encontrar nada para obtener el encabezado de sección predeterminado. Primera pregunta, ¿hay alguna forma de obtener el encabezado de sección predeterminado ?

Si no es posible, necesito crear una vista de contenedor que es un UIViewpero, esta vez necesito establecer el color de fondo predeterminado, el color de sombra, etc. Porque, si miras detenidamente el encabezado de la sección, ya está personalizado.

¿Cómo puedo obtener estos valores predeterminados para cada encabezado de sección?

Gracias a todos.


1
¿Qué hay de malo en usar tableView:titleForHeaderInSection:?
Borrrden

Devuelve un NSString, necesito configurar una fuente personalizada, así que no puedo si usotableView:titleForHeaderInSection:
limon

O puede usar imágenes para imitar los encabezados de sección predeterminados. teehanlax.com/blog/ios-6-gui-psd-iphone-5
Desdenova

@limon: Cómo implementar el encabezado de sección: stackoverflow.com/a/32261262/1457385
shallowThought

Respuestas:


288

Puedes probar esto:

 -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 18)];
    /* Create custom view to display section header... */
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, tableView.frame.size.width, 18)];
    [label setFont:[UIFont boldSystemFontOfSize:12]];
     NSString *string =[list objectAtIndex:section];
    /* Section header is in 0th index... */
    [label setText:string];
    [view addSubview:label];
    [view setBackgroundColor:[UIColor colorWithRed:166/255.0 green:177/255.0 blue:186/255.0 alpha:1.0]]; //your background color...
    return view;
}

ese es tu color bg, sea cual sea el color que quieras configurar, puedes
Lochana Ragupathy

Ese es el problema, ya hice lo que escribiste. Pero no sé el color de fondo predeterminado del encabezado de sección, que es un poco gris. Pero, necesito que sea exactamente el encabezado de sección predeterminado.
limon

15
hola vamos a usar el medidor digital de color
Lochana Ragupathy

asegúrese de establecer también el color de fondo de UILabel. Sé que estaba un poco confundido cuando mi fondo no se estaba volviendo claro para mí.
shulmey

3
¿Qué es list in line NSString * string = [list objectAtIndex: section]; Alguien me puede decir
Nisha Gupta

45

La respuesta seleccionada usando tableView :viewForHeaderInSection:es correcta.

Solo para compartir un consejo aquí.

Si está usando storyboard / xib, entonces podría crear otra celda prototipo y usarla para su "celda de sección". El código para configurar el encabezado es similar a cómo se configura para las celdas de fila.

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    static NSString *HeaderCellIdentifier = @"Header";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:HeaderCellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:HeaderCellIdentifier];
    }

    // Configure the cell title etc
    [self configureHeaderCell:cell inSection:section];

    return cell;
}

14
Hay varias cosas mal con esta solución. En primer lugar, el hecho de que si implementa "tableView (tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool", notará que el encabezado de la sección se moverá junto con la fila cuando se deslice. Para evitar esto, debe devolver cell.contentView en su lugar. El problema más grande es el hecho de que con esta solución, la aplicación se bloqueará cuando mantenga presionada la cabecera de la sección. La forma correcta es crear una punta que extienda UITableViewHeaderFooterView, registrarlo con la vista de tabla y devolverlo en este método. Probado en iOS8
Kachi

@Kachi La solución está usando viewForHeaderInSectionno canEditRowAtIndexPathcomo usted mencionó. Nunca verifico el bloqueo que dijiste, pero ¿podrías aclarar cómo una presión prolongada puede causar un bloqueo?
samwize

1
lo que quise decir es que si implementa esta solución e implementa canEditRowAtIndexPath, verá que el encabezado también se deslizará con la fila superior que está eliminando si no devuelve cell.contentView. Vea esta publicación SO: stackoverflow.com/questions/26009722/… La presión prolongada provoca un bloqueo porque un mensaje intenta enviarse a un objeto desasignado. Vea esta publicación SO: stackoverflow.com/questions/27622290/…
Kachi

1
No lo use nunca UITableViewCellcomo una vista de encabezado. Te resultará muy difícil depurar fallas visuales: el encabezado a veces desaparecerá debido a la deducción de las celdas y estarás buscando durante horas por qué es así hasta que te des cuenta de UITableViewCellque no pertenece al UITableViewencabezado.
raven_raven

Usar a UITableViewCellcomo encabezado es simplemente incorrecto.
Alex Zavatone

31

La versión rápida de Lochana Tejas responde:

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let view = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, 18))
    let label = UILabel(frame: CGRectMake(10, 5, tableView.frame.size.width, 18))
    label.font = UIFont.systemFontOfSize(14)
    label.text = list.objectAtIndex(indexPath.row) as! String
    view.addSubview(label)
    view.backgroundColor = UIColor.grayColor() // Set your background color

    return view
}

1
¿Cómo hacer que la altura de la etiqueta sea dinámica según el texto que está dentro de la vista?
Pratik Shah

La overridepalabra clave es redundante. Además, considere reutilizar las vistas de encabezado en lugar de volver a crearlas.
Vadim Bulavin

17

Si usa la vista de encabezado predeterminada, solo puede cambiar el texto con

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

Para Swift:

override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

Si desea personalizar la vista, debe crear una nueva usted mismo.


10

¿Por qué no usar UITableViewHeaderFooterView ?


Solo puede usar esto si no usa también - (UIView *) tableView: (UITableView *) tableView viewForHeaderInSection: sección (NSInteger).
SAHM

1
Respuesta perfectamente válida. Además, usar UITableViewHeaderFooterView se beneficia del reciclaje de vistas al igual que las celdas.
Gregzo

66
@dmarsi No he encontrado evidencia de que estén en desuso.
Fawkes

8

Si headerInSection no se muestra, puede probar esto.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 45;
}

Esto devuelve una altura para el encabezado de una sección determinada.


1
¿Te importaría elaborar tu respuesta?
CinCout

La sección del encabezado no se mostrará a menos que especifique con un método que enganche la 'altura' del encabezado de la sección. UITableView por defecto no muestra encabezados si no se especifica altura. @CinCout
theprojectabot

6

La versión Swift 3 de lochana y estemendoza responde:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    let view = UIView(frame: CGRect(x:0, y:0, width:tableView.frame.size.width, height:18))
    let label = UILabel(frame: CGRect(x:10, y:5, width:tableView.frame.size.width, height:18))
    label.font = UIFont.systemFont(ofSize: 14)
    label.text = "This is a test";
    view.addSubview(label);
    view.backgroundColor = UIColor.gray;
    return view

}

Además, tenga en cuenta que TAMBIÉN debe implementar:

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 100;
}

5

Prueba esto......

override func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) 
{
    // Background view is at index 0, content view at index 1
    if let bgView = view.subviews[0] as? UIView
    {
        // do your stuff
    }

    view.layer.borderColor = UIColor.magentaColor().CGColor
    view.layer.borderWidth = 1
}

5

Las otras respuestas hacen un buen trabajo al recrear la vista de encabezado predeterminada, pero en realidad no responden su pregunta principal:

¿Hay alguna forma de obtener el encabezado de sección predeterminado?

Hay una manera: simplemente implemente tableView:willDisplayHeaderView:forSection:en su delegado. La vista de encabezado predeterminada se pasará al segundo parámetro, y desde allí puede convertirla en UITableViewHeaderFooterVieway luego agregar / cambiar subvistas como desee.

Obj-C

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
    UITableViewHeaderFooterView *headerView = (UITableViewHeaderFooterView *)view;

    // Do whatever with the header view... e.g.
    // headerView.textLabel.textColor = [UIColor whiteColor]
}

Rápido

override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int)
{
    let headerView = view as! UITableViewHeaderFooterView

    // Do whatever with the header view... e.g.
    // headerView.textLabel?.textColor = UIColor.white
}

No necesitas lanzarlo. Simplemente puede agregar lo que desea a la vista. De hecho, crear un nuevo objeto no hará nada a menos que se lo asigne view.
Alex Zavatone

@AlexZavatone Así es, no necesita emitirlo si solo está agregando vistas. Es útil si desea personalizar algunas de las vistas predeterminadas, como la etiqueta de texto.
Craig Brown el

4
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    //put your values, this is part of my code
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 30.0f)];
    [view setBackgroundColor:[UIColor redColor]];
    UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(20, 5, 150, 20)];
    [lbl setFont:[UIFont systemFontOfSize:18]];
    [lbl setTextColor:[UIColor blueColor]];
    [view addSubview:lbl];

    [lbl setText:[NSString stringWithFormat:@"Section: %ld",(long)section]];

    return view;
}

4

Esta es la solución más fácil posible. El siguiente código se puede usar directamente para crear un encabezado de sección personalizado.

 -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    SectionHeaderTableViewCell *headerView = [tableView dequeueReusableCellWithIdentifier:@"sectionHeader"];

    //For creating a drop menu of rows from the section
    //==THIS IS JUST AN EXAMPLE. YOU CAN REMOVE THIS IF-ELSE.==
    if (![self.sectionCollapsedArray[section] boolValue])
    {
        headerView.imageView.image = [UIImage imageNamed:@"up_icon"];
    }
    else
    {
        headerView.imageView.image = [UIImage imageNamed:@"drop_icon"];
    }

    //For button action inside the custom cell
    headerView.dropButton.tag = section;
    [headerView.dropButton addTarget:self action:@selector(sectionTapped:) forControlEvents:UIControlEventTouchUpInside];

    //For removing long touch gestures.
    for (UIGestureRecognizer *recognizer in headerView.contentView.gestureRecognizers)
    {
        [headerView.contentView removeGestureRecognizer:recognizer];
        [headerView removeGestureRecognizer:recognizer];
    }

    return headerView.contentView;
}

NOTA: SectionHeaderTableViewCell es un UITableViewCell personalizado creado en Storyboard.


SectionHeaderTableViewCell - uso de identificador no declarado
Boris Gafurov

@BorisGafurov SectionHeaderTableViewCell es solo un nombre de ejemplo que le di a mi UITableViewCell, que creé en el guión gráfico.
Anish Kumar

2

Si yo fuera usted, haría un método que devuelva una UIView dada una NSString para contener. Por ejemplo

+ (UIView *) sectionViewWithTitle:(NSString *)title;

En la implementación de este método, cree un UIView, agregue un UILabel con las propiedades que desea establecer y, por supuesto, establezca su título en el dado.


Sí, puedo hacer eso, pero mi pregunta es cómo puedo obtener el fondo del encabezado de sección predeterminado, el valor de sombra, el resto es fácil de implementar.
limon

a qué te refieres con el fondo del encabezado de sección predeterminado
Lochana Ragupathy

1
Bueno, lo más fácil sería usar la aplicación Digital Color Meter para obtener los colores que desea. Tomarlos por código sería difícil, por lo que puedo decir ...
cpprulez

2

La solución de @ samwize en Swift (¡así que vota!). Brillante usando el mismo mecanismo de reciclaje también para secciones de encabezado / pie de página:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let settingsHeaderSectionCell:SettingsHeaderSectionCell = self.dequeueReusableCell(withIdentifier: "SettingsHeaderSectionCell") as! SettingsHeaderSectionCell

    return settingsHeaderSectionCell
}

2
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
    if([view isKindOfClass:[UITableViewHeaderFooterView class]]){

        UITableViewHeaderFooterView *headerView = view;

        [[headerView textLabel] setTextColor:[UIColor colorWithHexString:@"666666"]];
        [[headerView textLabel] setFont:[UIFont fontWithName:@"fontname" size:10]];
    }
}

Si desea cambiar la fuente de textLabel en el encabezado de su sección, desea hacerlo en willDisplayHeaderView. Para configurar el texto, puede hacerlo en viewForHeaderInSection o titleForHeaderInSection. ¡Buena suerte!


2

Ejemplo completo de 2019 para copiar y pegar

Primero configure "Agrupado" en el guión gráfico: tiene que suceder en el momento inicial, realmente no puede configurarlo más tarde, por lo que es más fácil recordar hacerlo en el guión gráfico:

ingrese la descripción de la imagen aquí

Próximo,

Debe implementar heightForHeaderInSection debido a un error de Apple.

func tableView(_ tableView: UITableView,
                   heightForHeaderInSection section: Int) -> CGFloat {
    return CGFloat(70.0)
}

Todavía hay un error de Apple, durante diez años, donde simplemente no mostrará el primer encabezado (es decir, el índice 0) si no tiene heightForHeaderInSection llamada.

Entonces, tableView.sectionHeaderHeight = 70simplemente no funciona, está roto .

Establecer un marco no logra nada:

En viewForHeaderInSection simplemente crear un UIView ().

No tiene sentido / no logra nada si UIView (marco ...) ya que iOS simplemente establece el tamaño de la vista según lo determinado por la tabla.

Entonces, la primera línea de viewForHeaderInSectionserá simple let view = UIView()y esa es la vista que devuelve.

func tableView(_ tableView: UITableView,
                       viewForHeaderInSection section: Int) -> UIView? {
    let view = UIView()
    
    let l = UILabel()
    view.addSubview(l)
    l.bindEdgesToSuperview()
    l.backgroundColor = .systemOrange
    l.font = UIFont.systemFont(ofSize: 15)
    l.textColor = .yourClientsFavoriteColor
    
    switch section {
    case 0:
        l.text =  "First section on screen"
    case 1:
        l.text =  "Here's the second section"
    default:
        l.text =  ""
    }
    
    return view
}

Eso es todo, cualquier otra cosa es una pérdida de tiempo.

Otro problema de Apple "quisquilloso".


La extensión de conveniencia utilizada anteriormente es:

extension UIView {
    
    // incredibly useful:
    
    func bindEdgesToSuperview() {
        
        guard let s = superview else {
            preconditionFailure("`superview` nil in bindEdgesToSuperview")
        }
        
        translatesAutoresizingMaskIntoConstraints = false
        leadingAnchor.constraint(equalTo: s.leadingAnchor).isActive = true
        trailingAnchor.constraint(equalTo: s.trailingAnchor).isActive = true
        topAnchor.constraint(equalTo: s.topAnchor).isActive = true
        bottomAnchor.constraint(equalTo: s.bottomAnchor).isActive = true
    }
}

1

Agregue mágicamente el encabezado de vista de tabla rápidamente

Recientemente probé esto.

Necesitaba uno y solo un encabezado en todo UITableView.

Como si quisiera un UIImageView en la parte superior de TableView. Así que agregué un UIImageView encima de UITableViewCell y automáticamente se agregó como tableViewHeader. Ahora conecto el ImageView al ViewController y agrego la imagen.

Estaba confundido porque hice algo así por primera vez. Entonces, para aclarar mi confusión, abra el formato xml de MainStoryBoard y descubrí que la Vista de imagen se agregó como encabezado.

Funcionó para mi. Gracias xCode y swift.



1

swif 4.2

override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    guard let header = view as? UITableViewHeaderFooterView else { return }

    header.textLabel?.textAlignment = .center // for all sections

    switch section {
    case 1:  //only section No.1
        header.textLabel?.textColor = .black
    case 3:  //only section No.3
        header.textLabel?.textColor = .red
    default: //
        header.textLabel?.textColor = .yellow
    }
}


0

Si solo desea agregar un título al encabezado tableView, no agregue una vista. En swift 3.x el código es así:

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    var lblStr = ""
    if section == 0 {
        lblStr = "Some String 1"
    }
    else if section == 1{
        lblStr = "Some String 2"
    }
    else{
        lblStr = "Some String 3"
    }
    return lblStr
}

Puede implementar una matriz para obtener el título de los encabezados.


0

Volviendo a la pregunta original (4 años después), en lugar de reconstruir su propio encabezado de sección, iOS simplemente puede llamarlo (con willDisplayHeaderView: forSection :) justo después de haber creado el predeterminado. Por ejemplo, quería agregar un botón de gráfico en el borde derecho del encabezado de sección:

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {
    UITableViewHeaderFooterView * header = (UITableViewHeaderFooterView *) view;
    if (header.contentView.subviews.count >  0) return; //in case of reuse
    CGFloat rightEdge = CGRectGetMaxX(header.contentView.bounds);
    UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(rightEdge - 44, 0, 44, CGRectGetMaxY(header.contentView.bounds))];
    [button setBackgroundImage:[UIImage imageNamed:@"graphIcon"] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(graphButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    [view addSubview:button];
}

0

Utilizar tableView: willDisplayHeaderView: para personalizar la vista cuando esté a punto de mostrarse.

Esto le brinda la ventaja de poder tomar la vista que ya se creó para la vista de encabezado y extenderla, en lugar de tener que volver a crear toda la vista del encabezado usted mismo.

Aquí hay un ejemplo que colorea la sección del encabezado según un BOOL y agrega un elemento de texto detallado al encabezado.

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
//    view.tintColor = [UIColor colorWithWhite:0.825 alpha:1.0]; // gray
//    view.tintColor = [UIColor colorWithRed:0.825 green:0.725 blue:0.725 alpha:1.0]; // reddish
//    view.tintColor = [UIColor colorWithRed:0.925 green:0.725 blue:0.725 alpha:1.0]; // pink

    // Conditionally tint the header view
    BOOL isMyThingOnOrOff = [self isMyThingOnOrOff];

    if (isMyThingOnOrOff) {
        view.tintColor = [UIColor colorWithRed:0.725 green:0.925 blue:0.725 alpha:1.0];
    } else {
        view.tintColor = [UIColor colorWithRed:0.925 green:0.725 blue:0.725 alpha:1.0];
    }

    /* Add a detail text label (which has its own view to the section header… */
    CGFloat xOrigin = 100; // arbitrary
    CGFloat hInset = 20;
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(xOrigin + hInset, 5, tableView.frame.size.width - xOrigin - (hInset * 2), 22)];

    label.textAlignment = NSTextAlignmentRight;

    [label setFont:[UIFont fontWithName:@"Helvetica-Bold" size:14.0]
    label.text = @"Hi.  I'm the detail text";

    [view addSubview:label];
}

0

Swift 4.2

En Swift 4.2, el nombre de la tabla ha cambiado un poco.

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 18))
        let label = UILabel(frame: CGRect(x: 10, y: 5, width: tableView.frame.size.width, height: 18))
        label.font = UIFont.systemFont(ofSize: 14)
        label.text = list.objectAtIndex(section) as! String
        view.addSubview(label)
        view.backgroundColor = UIColor.gray // Set your background color

        return view
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.