Tengo un xib archivo con una UITableView para el que me quiera agregar una sección personalizada encabezado de la vista usando el método delegado tableView:viewForHeaderInSection:. Hay alguna posibilidad de diseñar en Interface Builder y, a continuación, cambie algunas de sus subvista de propiedades de la programación?

Mi UITableView tiene más encabezados de sección para crear una UIView en Interface Builder y regresar no funciona, porque yo tendría que duplicar, pero no hay ninguna forma de hacerlo. Archivado y descomprimir no funciona para UIImages para UIImageViews se muestran en blanco.

También, no quiero crear mediante programación debido a que son muy complejos y el código resultante sería difícil de leer y de mantener.

Editar 1: Aquí está mi tableView:viewForHeaderInSection: método:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
return nil;
}
CGSize headerSize = CGSizeMake(self.view.frame.size.width, 100);
/* wrapper */
UIView *wrapperView = [UIView viewWithSize:headerSize];
wrapperView.backgroundColor = [UIColor colorWithHexString:@"2670ce"];
/* title */
CGPoint titleMargin = CGPointMake(15, 8);
UILabel *titleLabel = [UILabel labelWithText:self.categoriesNames[section] andFrame:CGEasyRectMake(titleMargin, CGSizeMake(headerSize.width - titleMargin.x * 2, 20))];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.font = [UIFont fontWithStyle:FontStyleRegular andSize:14];
[wrapperView addSubview:titleLabel];
/* body wrapper */
CGPoint bodyWrapperMargin = CGPointMake(10, 8);
CGPoint bodyWrapperViewOrigin = CGPointMake(bodyWrapperMargin.x, CGRectGetMaxY(titleLabel.frame) + bodyWrapperMargin.y);
CGSize bodyWrapperViewSize = CGSizeMake(headerSize.width - bodyWrapperMargin.x * 2, headerSize.height - bodyWrapperViewOrigin.y - bodyWrapperMargin.y);
UIView *bodyWrapperView = [UIView viewWithFrame:CGEasyRectMake(bodyWrapperViewOrigin, bodyWrapperViewSize)];
[wrapperView addSubview:bodyWrapperView];
/* image */
NSInteger imageSize = 56;
NSString *imageName = [self getCategoryResourceItem:section + 1][@"image"];
UIImageView *imageView = [UIImageView imageViewWithImage:[UIImage imageNamed:imageName] andFrame:CGEasyRectMake(CGPointZero, CGEqualSizeMake(imageSize))];
imageView.layer.masksToBounds = YES;
imageView.layer.cornerRadius = imageSize / 2;
[bodyWrapperView addSubview:imageView];
/* labels */
NSInteger labelsWidth = 60;
UILabel *firstLabel = [UILabel labelWithText:@"first" andFrame:CGRectMake(imageSize + bodyWrapperMargin.x, 0, labelsWidth, 16)];
[bodyWrapperView addSubview:firstLabel];
UILabel *secondLabel = [UILabel labelWithText:@"second" andFrame:CGRectMake(imageSize + bodyWrapperMargin.x, 20, labelsWidth, 16)];
[bodyWrapperView addSubview:secondLabel];
UILabel *thirdLabel = [UILabel labelWithText:@"third" andFrame:CGRectMake(imageSize + bodyWrapperMargin.x, 40, labelsWidth, 16)];
[bodyWrapperView addSubview:thirdLabel];
[@[ firstLabel, secondLabel, thirdLabel ] forEachView:^(UIView *view) {
UILabel *label = (UILabel *)view;
label.textColor = [UIColor whiteColor];
label.font = [UIFont fontWithStyle:FontStyleLight andSize:11];
}];
/* line */
UIView *lineView = [UIView viewWithFrame:CGRectMake(imageSize + labelsWidth + bodyWrapperMargin.x * 2, bodyWrapperMargin.y, 1, bodyWrapperView.frame.size.height - bodyWrapperMargin.y * 2)];
lineView.backgroundColor = [UIColor whiteColorWithAlpha:0.2];
[bodyWrapperView addSubview:lineView];
/* progress */
CGPoint progressSliderOrigin = CGPointMake(imageSize + labelsWidth + bodyWrapperMargin.x * 3 + 1, bodyWrapperView.frame.size.height / 2 - 15);
CGSize progressSliderSize = CGSizeMake(bodyWrapperViewSize.width - bodyWrapperMargin.x - progressSliderOrigin.x, 30);
UISlider *progressSlider = [UISlider viewWithFrame:CGEasyRectMake(progressSliderOrigin, progressSliderSize)];
progressSlider.value = [self getCategoryProgress];
[bodyWrapperView addSubview:progressSlider];
return wrapperView;
}

y yo quisiera que se vea algo como esto:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
return nil;
}
SectionView *sectionView = ... //get the view that is already designed in the Interface Builder
sectionView.headerText = self.categoriesNames[section];
sectionView.headerImage = [self getCategoryResourceItem:section + 1][@"image"];
sectionView.firstLabelText = @"first";
sectionView.secondLabelText = @"second";
sectionView.thirdLabelText = @"third";
sectionView.progress = [self getCategoryProgress];
return wrapperView;
}

Editar 2: yo no estoy usando un Storyboard, sólo .xib archivos. Además, no tengo una UITableViewController, sólo un UIViewController en la que he añadido un UITableView.

  • Usted puede crear el UIView en el Interface Builder dar a la sección de encabezado
  • Eso es lo que me dijo, así que, obviamente, no sólo el trabajo, fuera de la caja, por lo tanto, la pregunta. ¿Cómo puedo give it como una sección de encabezado en una tabla con varias secciones?
  • No, la pregunta era si puedo diseño en INTERFAZ, no en el código!
  • La duplicación de que UIView objeto.
  • ¿Cuál es tu problema puede ex-plano claramente ,a continuación, voy a intentar ayudarte
  • ¿me puedes mostrar el código viewForHeaderInSection método
  • No importa, es sólo un UIView elementos de creación de código.
  • Duplicar stackoverflow.com/questions/9219234/…
  • No, yo uso .xib archivos, no de un Guión. Por favor retire su downvote.
  • Una razón por la downvotes de ayuda. O se trata simplemente de un caso de la teoría de ventanas Rotas?! -_-
  • de todos modos duplicado de stackoverflow.com/questions/17651880/… o stackoverflow.com/questions/19162246/… búsqueda por Favor, antes de preguntar…
  • Hice effin de búsqueda, pero no pude encontrar! Yo estaba sólo en la búsqueda de soluciones como las de arriba que no se aplica. He buscado una solución para los días. Yo no soy un retrasado. Por eso la pregunta duplicada existe. ASÍ que va a la baja, y también hacia abajo sobre mis nervios. No se trata de ayudar a los más, se trata de señalar con el dedo, downvoting, copiar+pegar-ción de la misma mal nueva solución para un par más reputación, y en la final, odio.

4 Comentarios

  1. 81

    Guión gráfico o XIB

    1. Mismo Storyboard:

      return tableView.dequeueReusableCell(withIdentifier: "header")

      Diseño UITableView la sección de encabezado en el Interface Builder

    2. Separado XIB (paso Adicional: usted debe registrarse que Nib primero):

      tableView.register(UINib(nibName: "XIBSectionHeader", bundle:nil),
      forCellReuseIdentifier: "xibheader")

    A la carga de un Storyboard en lugar de un XIB, ver este Desbordamiento de Pila respuesta.


    Utilizando UITableViewCell para crear la Sección de Encabezado en IB

    Tomar ventaja del hecho de que una sección de encabezado es un habitual UIView, y que UITableViewCell es, también, un UIView. En Interface Builder, drag & drop un la Vista de la Tabla de Células de la Biblioteca de Objetos de en su Vista de Tabla Prototipo Contenido.

    Agregar un Identificador a la nueva la Vista de la Tabla de Células, y personalizar su apariencia para adaptarse a sus necesidades. Para este ejemplo, he utilizado header.

    Diseño UITableView la sección de encabezado en el Interface Builder

    Uso dequeueReusableCell:withIdentifier para localizar a su sección de encabezado, como haría cualquier vista de tabla de la célula. Usted tendrá que proporcionar heightForHeaderInSection, que está codificado como 44 para mayor claridad:

    //MARK: UITableViewDelegate
    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
    {
    //This is where you would change section header content
    return tableView.dequeueReusableCell(withIdentifier: "header")
    }
    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
    {
    return 44
    }

    Swift 2 & anterior:

    return tableView.dequeueReusableCellWithIdentifier("header") as? UIView
    self.tableView.registerNib(UINib(nibName: "XIBSectionHeader", bundle:nil),
    forCellReuseIdentifier: "xibheader")

    ► Encontrar esta solución en GitHub y los detalles adicionales sobre Swift Recetas.

    • Lo siento, se me olvidó mencionar que yo no uso el Storyboard, sólo un .xib archivo, en el cual tengo un UITableView, no UITableViewController.
    • También, si tengo un UILabel interior que UITableViewCell, ¿cómo puedo cambiar el texto de manera diferente para cada sección?
    • Por lo tanto, si el encabezado de la sección UITableViewCell está en otro XIB archivo, en el que UITableView llamo el método dequeueReusableCellWithIdentifier:?
    • Es tan sencillo como añadir self.tableView.registerNib(UINib(nibName: "XIBSectionHeader", bundle:nil), forCellReuseIdentifier: "xibheader") en UITableViewController -viewDidLoad().
    • No tengo una UITableViewController.
    • Antes de usar esta forma, comprobar esta respuesta. Debido a que usted tiene un problema con el diseño/el manejo táctil, y la reutilización de tales vistas de sección. stackoverflow.com/questions/9219234/…
    • Aclaración: no Hay ninguna mención de un UITableViewController, sólo un UITableViewDelegate.
    • Yo creo que eso ha cambiado ahora. Utilizar formato tableview.dequeueReusableCellWithIdentifier(«header»)?.contentView. Casting para UIView siempre van a fallar.
    • Cualquier razón para no usar el método adecuado? dequeueReusableHeaderFooterView() debe ser utilizado en lugar de dequeueReusableCellWithIdentifier.
    • dequeueReusableHeaderFooterView no se mezclan bien con el Storyboard.
    • ¿qué significa «mismo » storyboard» significa?!
    • El UITableViewCell se define en el mismo Guión gráfico como el UITableViewController.
    • «No se mezcla bien con el guión» es una excusa muy pobre para el uso de un completamente inadecuado método para el encabezado y pie de página vistas. dequeueReusableHeaderFooterView() sin duda debe ser utilizado en lugar de otro; @FrederikA.Winkelsdorf es correcta
    • Aparte de @FrederikA.Winkelsdorf sugerencia, esta respuesta es irregular, Esto debería ser aceptado
    • La respuesta perfecta. Gracias.
    • Perfecto!!!!! :))

  2. 10

    Finalmente resuelto mediante este tutorial, que, en gran parte se compone de los siguientes (adaptado a mi ejemplo):

    1. Crear SectionHeaderView clase que las subclases de UIView.
    2. Crear SectionHeaderView.xib archivo y el conjunto es File's Owner‘s CustomClass a la SectionHeaderView clase.
    3. Crear un UIView de la propiedad en el .m archivo como: @property (strong, nonatomic) IBOutlet UIView *viewContent;
    4. Conecte el .xib‘s View a este viewContent de corriente.
    5. Agregar un método inicializador que se parece a esto:

      + (instancetype)header {
      SectionHeaderView *sectionHeaderView = [[SectionHeaderView alloc] init];
      if (sectionHeaderView) { //important part
      sectionHeaderView.viewContent = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:sectionHeaderView options:nil] firstObject];
      [sectionHeaderView addSubview:sectionHeaderView.viewContent];
      return sectionHeaderView;
      }
      return nil;
      }

    Entonces, he añadido un UILabel dentro de la .xib archivo y conectado a la labelCategoryName de corriente y se implementó el setCategoryName: método dentro de la SectionHeaderView clase como esta:

    - (void)setCategoryName:(NSString *)categoryName {
    self.labelCategoryName.text = categoryName;
    }

    Luego me implementado el tableView:viewForHeaderInSection: método como este:

    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    SectionHeaderView *sectionHeaderView = [SectionHeaderView header];
    [sectionHeaderView setCategoryName:self.categoriesNames[section]];
    return sectionHeaderView;
    }

    Y que finalmente se trabajó. Cada sección tiene su propio nombre, y también UIImageViews se muestren correctamente.

    Espero que ayude a otros que tropieza con la misma mal soluciones una y otra vez, en toda la web, como lo hice yo.

    • 1) «Todo tipo»?! Sólo hay 2 líneas de código que hace el trabajo. 2) ¿por Qué es estática + mal? Es simplemente un contenedor para ... alloc] init], yo lo uso todo el tiempo como custom estos inicializadores: [UIView viewWithFrame:], [UIView viewAtPoint:]. 3) ¿Qué carga de un UITableView de un XIB tiene que ver con mi problema? Tengo un XIB archivo con y UITableView y otros UIViews, no sólo de la tabla, y ahora, otra XIB para el encabezado de la sección. 3) Es mi primera recompensa, y en ninguna parte estaba escrito que yo no estoy permitido publicar una solución antes de la recompensa de que caduque. ¿Por qué no dejarles votar el mío?
    • Buenos puntos. Yo respeto su opinión.
  3. 1

    Solución Es simple

    Crear una xib, hacer de interfaz de usuario de acuerdo a su Documentación
    a continuación, en viewForHeaderInSection obtener xib

    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"HeaderView" owner:self options:nil];
    HeaderView *headerView = [nibArray objectAtIndex:0];
    return headerView;
    } 
    • Y cómo se supone que voy a cambiar un UILabel‘s el texto de la HeaderView?
  4. 0

    Tan lejos como yo entiendo su problema, usted quiere tener la misma UIView duplicado varias veces por las múltiples encabezados de sección que desea ser capaz de mostrar.

    Si este fuera mi problema, aquí es cómo lo resolvería.

    SOLUCIÓN ORIGINAL

    1)

    En mi UIViewController que posee la vista de tabla, también me gustaría crear un punto de vista que es una plantilla para el encabezado. Asignar que a un IBOutlet. Esta será la vista que se puede editar a través de la Interfaz del Generador de.

    2)

    En su ViewDidLoad o (quizá el mejor) ViewWillAppear método, usted querrá hacer tantas copias de la plantilla de encabezado UIView que usted va a necesitar para mostrar los encabezados de sección.

    Hacer copias de UIViews en la memoria no es trivial, pero no es difícil tampoco. Aquí es una respuesta de una pregunta relacionada con la que te muestra cómo hacerlo.

    Agregar la copias a un NSMutableArray (donde el índice de cada uno de los objetos que corresponden a las secciones… la vista en el índice 0 de la matriz, será lo que el retorno de la sección 0, vista 1 en la matriz de la sección 1, ec.).

    3)

    Usted no será capaz de utilizar IBOutlets para la elementos de que la sección de encabezado (debido a que el código sólo se asocia de comunicación con una visión particular desde el archivo XIB).

    Así que para esto, usted probablemente quiera usar la vista de propiedades de la etiqueta para cada uno de los elementos de interfaz de usuario en el encabezado de la vista que desea modificar o cambiar para cada sección diferente. Puede establecer estas etiquetas a través de la Interfaz del Generador y, a continuación, se refieren a ellos mediante programación en el código.

    En su viewForHeaderInSection método, que va a hacer algo como:

    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
    return nil;
    }
    SectionView *sectionView = [self.arrayOfDuplicatedHeaderViews objectAtIndex: section];
    //my title view has a tag of 10
    UILabel *titleToModify = [sectionView viewWithTag: 10]; 
    if(titleToModify)
    {
    titleToModify.text = [NSString stringWithFormat:@"section %d", section];
    }
    return sectionView;
    }

    Tiene sentido?

    SOLUCIÓN DIFERENTE

    1)

    Usted todavía necesita una matriz de UIViews (o «Section View» subclases UIViews), pero podría crear cada una de esas con las sucesivas llamadas a la carga de la vista desde su propio archivo XIB.

    Algo como esto:

    @implementation SectionView
    + (SectionView*) getSectionView
    {
    NSArray* array = [[NSBundle mainBundle] loadNibNamed:@"SectionView" owner:nil options:nil];
    return [array objectAtIndex:0]; //assume that SectionView is the only object in the xib
    }
    @end

    (más los detalles que se encuentran en la respuesta a esta pregunta relacionada con la)

    2)

    Que podría ser capaz de utilizar IBOutlets en esto (pero no estoy 100% seguro), pero las propiedades de la etiqueta una vez más, podría funcionar bastante bien.

    • En el segundo punto de su respuesta, no es un problema. Como he dicho en la pregunta: «me he duplicarlo, pero no hay ninguna forma de hacerlo. Archivado y descomprimir no funciona para UIImages para UIImageViews se muestran en blanco.». En segundo lugar, trabajar con etiquetas, supongo que no es una buena práctica, y sé que esto a partir de mi propia experiencia me resulta difícil mantener un UIViewController de un proyecto en el que estoy trabajando es que utiliza las etiquetas. Pensé que podría funcionar, tengo curiosidad de saber si no hay alguna solución más sencilla. También, ¿por qué el sectionView rodeados por paréntesis?
    • Hice una actualización a mi respuesta hasta allí para ofrecer una potencialmente más útil de la solución y sí, estoy de acuerdo en que las propiedades de etiqueta no son muy sencillo de usar. Todavía no he hecho la «loadNibNamed:» método en mi propio código en mucho tiempo, así que no estoy seguro de si IBOutlets funcionaría o no, pero darle una oportunidad. Y el parenths todo el valor de retorno es mi estilo, no es un requisito en todos. Voy a editar con ellos.
    • ¿Cómo es esto loadNibNamed solución propuesta en Agosto 27 diferente a la aceptada solución?
    • probablemente porque hice esta solución en primer lugar, @SwiftArchitect

Dejar respuesta

Please enter your comment!
Please enter your name here