Добавление заголовка UIButton в UITableView

У меня есть UITableView с 1 секцией и для заголовка раздела, я хотел бы сохранить все о заголовке так же, но просто добавить кнопку с правой стороны. Я не могу поместить кнопку в контроллер навигации, потому что два доступных пятна для такой кнопки уже заняты другими кнопками.

Здесь вы можете увидеть результат того, что я пытался сделать. Теперь все, что я хочу сделать, это добавить кнопку добавления в правой части заголовка, но то, что я пробовал, не работает. Я также пробовал некоторые другие решения на StackOverflow, но они не достигли того, что я хотел сделать. Кроме того, если есть лучший способ создать кнопку добавления, пожалуйста, дайте мне знать. Я попытался использовать UIBarButtonItem, но я не мог понять, как добавить его представление в фактическое представление. Спасибо!

enter image description here

Это то, что у меня есть до сих пор в моем делегате:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIButton *addButton = [[UIButton alloc] init]; //I also tried setting a frame for the
    button, but that did not seem to work, so I figured I would just leave it blank for posting       
    the question.
    addButton.titleLabel.text = @"+";
    addButton.backgroundColor = [UIColor redColor];
    [self.tableView.tableHeaderView insertSubview:addButton atIndex:0]; 
    //I feel like this is a bad idea

    return self.tableView.tableHeaderView;
}

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

Ответ 1

Проблема в том, что ваш self.tableView.tableHeaderView на данный момент nil, поэтому вы не можете его использовать. Итак, что вам нужно сделать, создайте UIView, добавьте заголовок и кнопку в него, создайте их и верните.

Это должно добавить заголовок и кнопку в заголовок раздела, вам все же нужно будет стилизовать заголовок с правильным шрифтом и размером, но даст вам представление.

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    CGRect frame = tableView.frame;

    UIButton *addButton = [[UIButton alloc] initWithFrame:CGRectMake(frame.size.width-60, 10, 50, 30)];
    [addButton setTitle:@"+" forState:UIControlStateNormal];
    addButton.backgroundColor = [UIColor redColor];

    UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 30)];
    title.text = @"Reminders";

    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
    [headerView addSubview:title];
    [headerView addSubview:addButton];

    return headerView;
}

Ответ 2

Из iOS 6 вы также можете реализовать

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section

в UITableViewDelegate. Например:

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {
    if (section == 0) {
        if ([view.subviews.lastObject isKindOfClass:[UIButton class]]) {
            return;
        }
        UIButton *button = [UIButtonbuttonWithType:UIButtonTypeSystem];
        button.frame = CGRectMake(view.frame.size.width - 160.0, 0, 160.0, view.frame.size.height); // x,y,width,height
        [button setTitle:@"My Button" forState:UIControlStateNormal];
        [button addTarget:self action:@selector(sectionHeaderButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [view addSubview:button];
    }
}

Ответ 3

Если вы заинтересованы в решении Swift:

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

    let frame = tableView.frame

    let button = UIButton(frame: CGRectMake(5, 10, 15, 15))  // create button
    button.tag = section 
    // the button is image - set image
    button.setImage(UIImage(named: "remove_button"), forState: UIControlState.Normal)  // assumes there is an image named "remove_button"
    button.addTarget(self, action: #selector(TestController.remove(_:)), forControlEvents: .TouchUpInside)  // add selector called by clicking on the button

    let headerView = UIView(frame: CGRectMake(0, 0, frame.size.width, frame.size.height))  // create custom view
    headerView.addSubview(button)   // add the button to the view

    return headerView   
}

Возможно, вы захотите указать высоту заголовка в разделе. Это должно быть синхронизировано с высотой пользовательского представления:

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

Ответ 4

У вас есть 2 варианта, оба с помощью tableView.delegate. Первый включает в себя реализацию метода делегата

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

который позволяет вам в принципе возвращать все, что угодно, в пользовательском представлении, которое будет использоваться в качестве заголовка для нужного раздела. Это может быть так же просто, как

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIButton *addButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
    [addButton addTarget:self action:@selector(SomeMethod:) forControlEvents:UIControlEventTouchUpInside];
    return addButton;
}

который поместит в качестве заголовка круглую информационную кнопку (в центре). Но, скорее всего, вы захотите создать реальный объект UIView и заполнить его своей кнопкой (и ярлыком заголовка раздела?) И выложить все, как вам нравится [см. Ответы других, как это сделать].

Однако второй подход, вероятно, лучше для общего случая простого добавления кнопки в (один из) заголовков разделов [я знаю, что вы заявили 1 раздел, но многие люди, вероятно, приземляются на этот вопрос, желая сделать аналогичный в многосекционной таблице]. Это включает в себя реализацию метода делегата

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section

и в основном добавление вашей кнопки в заголовок после факта; в частности,

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
    // Remove old button from re-used header
    if ([view.subviews.lastObject isKindOfClass:UIButton.class])
        [view.subviews.lastObject removeFromSuperview];

    if (section == MySectionNumberWithButton) {
        UIButton *addButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
        [addButton addTarget:self action:@selector(SomeMethod:) forControlEvents:UIControlEventTouchUpInside];
        [view addSubview:addButton];

        // Place button on far right margin of header
        addButton.translatesAutoresizingMaskIntoConstraints = NO; // use autolayout constraints instead
        [addButton.trailingAnchor constraintEqualToAnchor:view.layoutMarginsGuide.trailingAnchor].active = YES;
        [addButton.bottomAnchor constraintEqualToAnchor:view.layoutMarginsGuide.bottomAnchor].active = YES;
    }
}

Обратите внимание: поскольку таблицаView повторно использует заголовки, в таблице с несколькими разделами вы должны обязательно удалить любую кнопку, которую вы могли бы добавить ранее, иначе вы в конечном итоге получите кнопки в нежелательных разделах. Затем, если это правильный раздел, добавьте кнопку в существующий заголовок. Заметьте, я использую NSLayoutAnchor (iOS 9+) для макета кнопки для краткости; вы можете сделать то же самое с NSLayoutConstraint (iOS 6 +)

Этот подход имеет явное преимущество - просто добавив кнопку - вам не нужно воссоздавать обычный макет, чтобы соответствовать всем другим (без кнопки) заголовкам, или беспокоиться о изменении полей при повороте устройства и т.д. В частности, заголовок заголовка не затронут и сохранит любые глобальные параметры внешнего вида, которые вы, возможно, определили для заголовков таблиц (например, шрифт, цвет и т.д.), Все из которых вы имели бы грязную работу по воссозданию, если бы вы взяли подход tableView:viewForHeaderInSection:.

Ответ 5

Вы можете сделать это, используя приведенный ниже код, вы можете поместить любой тип представления в представление заголовка, но вы должны указать его для него.

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *view=[[UIView alloc]init];
    UIButton *addButton=[UIButton buttonWithType:UIButtonTypeContactAdd];
    addButton.frame=CGRectMake(250, 0, 100, 50);
    [view addSubview:addButton];
    [tblView.tableHeaderView insertSubview:view atIndex:0];
    //I feel like this is a bad idea

    return view;
}

Ответ 6

Если вы хотите использовать Interface Builder для создания заголовка раздела, вы можете использовать UITableViewCell в качестве заголовка. Создайте ячейку-прототип для вашего заголовка в UITableView, настройте ее так же, как любую другую ячейку, включая добавление меток, кнопок и ограничений.

Вы можете создать экземпляр в вашем UITableViewController лениво:

lazy var headerCell: MyHeaderTableViewCell = {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Header") as! MyHeaderTableViewCell
    return cell
}()

Чтобы сделать его заголовком:

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

Ответ 7

Swift 4:

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

    let frame = tableView.frame
    let button = UIButton(frame: CGRect(x: 5, y: 10, width: 15, height: 15))
    button.tag = section
    button.setImage(UIImage(named: "remove_button"), for: UIControl.State.normal)
    button.addTarget(self,action:#selector(buttonClicked),for:.touchUpInside)

    let headerView = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height))
    headerView.addSubview(button)

    return headerView
}

Эта функция обрабатывает нажатие кнопки:

@objc func buttonClicked(sender:UIButton)
{
    if(sender.tag == 1){

       //Do something for tag 1
    }
    print("buttonClicked")
}