2010-01-20 3 views
27

Я использую функциональность 'swipe to delete' UITableView.iPhone UITableView - кнопка удаления

Проблема заключается в том, я использую настроенные UITableViewCell, который создается на каждый товар в

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

Мне нужно изменить положение кнопки удаления (просто переместить его вокруг 10px слева) , как я могу это сделать?

Вот мой существующий код для создания ячейки:

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSLog(@"cellForRowAtIndexPath"); 
#if USE_CUSTOM_DRAWING 
    const NSInteger TOP_LABEL_TAG = 1001; 
    const NSInteger BOTTOM_LABEL_TAG = 1002; 
    UILabel *topLabel; 
    UILabel *bottomLabel; 
#endif 

    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) 
    { 
     // 
     // Create the cell. 
     // 
     cell = 
     [[[UITableViewCell alloc] 
      initWithFrame:CGRectZero 
      reuseIdentifier:CellIdentifier] 
     autorelease]; 

#if USE_CUSTOM_DRAWING 


     const CGFloat LABEL_HEIGHT = 20; 
     UIImage *image = [UIImage imageNamed:@"trans_clock.png"]; 

     // 
     // Create the label for the top row of text 
     // 
     topLabel = 
     [[[UILabel alloc] 
      initWithFrame: 
      CGRectMake(
        image.size.width + 2.0 * cell.indentationWidth, 
        0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT), 
        aTableView.bounds.size.width - 
        image.size.width - 4.0 * cell.indentationWidth 
        , 
        LABEL_HEIGHT)] 
     autorelease]; 
     [cell.contentView addSubview:topLabel]; 

     // 
     // Configure the properties for the text that are the same on every row 
     // 
     topLabel.tag = TOP_LABEL_TAG; 
     topLabel.backgroundColor = [UIColor clearColor]; 
     topLabel.textColor = fontColor; 
     topLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0]; 
     topLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]]; 

     // 
     // Create the label for the top row of text 
     // 
     bottomLabel = 
     [[[UILabel alloc] 
      initWithFrame: 
      CGRectMake(
        image.size.width + 2.0 * cell.indentationWidth, 
        0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT) + LABEL_HEIGHT, 
        aTableView.bounds.size.width - 
        image.size.width - 4.0 * cell.indentationWidth 
        , 
        LABEL_HEIGHT)] 
     autorelease]; 
     [cell.contentView addSubview:bottomLabel]; 

     // 
     // Configure the properties for the text that are the same on every row 
     // 
     bottomLabel.tag = BOTTOM_LABEL_TAG; 
     bottomLabel.backgroundColor = [UIColor clearColor]; 
     bottomLabel.textColor = fontColor; 
     bottomLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0]; 
     bottomLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize] - 2]; 

     // 
     // Create a background image view. 
     // 
     cell.backgroundView = 
     [[[UIImageView alloc] init] autorelease]; 
     cell.selectedBackgroundView = 
     [[[UIImageView alloc] init] autorelease]; 
#endif 
    } 

#if USE_CUSTOM_DRAWING 
    else 
    { 
     topLabel = (UILabel *)[cell viewWithTag:TOP_LABEL_TAG]; 
     bottomLabel = (UILabel *)[cell viewWithTag:BOTTOM_LABEL_TAG]; 
    } 
    topLabel.text = @"Example Text"; 
    topLabel.textColor = fontColor; 

    bottomLabel.text = @"More Example Text"; 
    bottomLabel.textColor = fontColor; 

    // 
    // Set the background and selected background images for the text. 
    // Since we will round the corners at the top and bottom of sections, we 
    // need to conditionally choose the images based on the row index and the 
    // number of rows in the section. 
    // 
    UIImage *rowBackground; 
    UIImage *selectionBackground; 
    NSInteger sectionRows = [aTableView numberOfRowsInSection:[indexPath section]]; 
    NSInteger row = [indexPath row]; 
    if (row == 0 && row == sectionRows - 1) 
    { 
     rowBackground = [UIImage imageNamed:@"topAndBottomRow.png"]; 
     selectionBackground = [UIImage imageNamed:@"topAndBottomRowSelected.png"]; 
    } 
    else if (row == 0) 
    { 
     rowBackground = [UIImage imageNamed:@"topRow.png"]; 
     selectionBackground = [UIImage imageNamed:@"topRowSelected.png"]; 
    } 
    else if (row == sectionRows - 1) 
    { 
     rowBackground = [UIImage imageNamed:@"bottomRow.png"]; 
     selectionBackground = [UIImage imageNamed:@"bottomRowSelected.png"]; 
    } 
    else 
    { 
     rowBackground = [UIImage imageNamed:@"middleRow.png"]; 
     selectionBackground = [UIImage imageNamed:@"middleRowSelected.png"]; 
    } 
    ((UIImageView *)cell.backgroundView).image = rowBackground; 
    ((UIImageView *)cell.selectedBackgroundView).image = selectionBackground; 

    cell.imageView.image = [UIImage imageNamed:@"Example_Image.png"]; 
#else 
    cell.text = @"Example"; 
#endif 
    return cell; 
} 

ответ

23

Код Iwat для меня не работает. Но это работает.

- (void)willTransitionToState:(UITableViewCellStateMask)state { 

    [super willTransitionToState:state]; 

    if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask) { 

     for (UIView *subview in self.subviews) { 

      if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellDeleteConfirmationControl"]) {    

       subview.hidden = YES; 
       subview.alpha = 0.0; 
      } 
     } 
    } 
} 

- (void)didTransitionToState:(UITableViewCellStateMask)state { 

    [super didTransitionToState:state]; 

    if (state == UITableViewCellStateShowingDeleteConfirmationMask || state == UITableViewCellStateDefaultMask) { 
     for (UIView *subview in self.subviews) { 

      if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellDeleteConfirmationControl"]) { 

       UIView *deleteButtonView = (UIView *)[subview.subviews objectAtIndex:0]; 
       CGRect f = deleteButtonView.frame; 
       f.origin.x -= 20; 
       deleteButtonView.frame = f; 

       subview.hidden = NO; 

       [UIView beginAnimations:@"anim" context:nil]; 
       subview.alpha = 1.0; 
       [UIView commitAnimations]; 
      } 
     } 
    } 
}
+0

Спасибо за ваш ответ, один вопрос (я еще не тестировал код), но что это за линия subview.hidden = NO; ** –

+1

Извините. Я новичок в stackoverflow. Я просто хочу сделать этот кусок кода жирным. Когда я нажал на жирную кнопку, ** был добавлен до конца. – nonamelive

+0

Привет, я, наконец, заработал, и он работает очень хорошо! – nonamelive

1

Я не знаю ни одного способа «переместить кнопку Удалить 10px влево». Тем не менее, вы можете анимировать пользовательское содержимое ячейки таблицы вокруг статической позиции кнопки неподвижного удаления, прослушивая сообщение willTransitionToState: из подкласса UITableViewCell, см. here.

Процитирует документы:

Подклассов UITableViewCell могут реализовать этот метод, чтобы оживить дополнительных изменений в клетку, когда она меняется состоянием. UITableViewCell вызывает этот метод всякий раз, когда ячейка переходит между состояниями, такими как из нормального состояния (по умолчанию) в режим редактирования . Пользовательская ячейка может установить и позиционировать любые новые виды, которые появляются с новым состоянием. Затем ячейка получает сообщение layoutSubviews (UIView), в котором оно может позиционировать эти новые виды в своих окончательных местах для нового состояния. Подкласс должен всегда называть супер, когда переопределяет этот метод.

То, что вы ищете, это значение UITableViewCellStateShowingDeleteConfirmationMask. Это один из тех случаев, когда создание подкласса UITableViewCell может быть лучше, поэтому из контроллера вы просто создаете экземпляр своей пользовательской ячейки. Затем ячейка может просто настроить себя как animateLeft и animateRight и обрабатывать внутренние работы по настройке собственных подзонов.

+0

Я считал, что подклассификация UITableViewCell в первую очередь была причиной, по которой я решил реализовать ее по коду потому что я не хотел управлять 3 пользовательскими объектами UITableViewCell (сверху, снизу и середине); и теперь для удовлетворения моих потребностей потребуется создать 4 (дополнительный для удаления), если я не ошибаюсь? –

2

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

Заканчивать следующий член UITableViewDelegate протокола:

- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath 

Кроме того, вы можете обнаружить, когда кнопка удаления, что отображается на подклассы UITableViewCell и перекрывая следующее:

- (void)willTransitionToState:(UITableViewCellStateMask)state 
- (void)didTransitionToState:(UITableViewCellStateMask)state 

Для любая из них, маска состояния будет UITableViewCellStateShowingDeleteConfirmationMask, когда отображается кнопка удаления.

Надеемся, эти подсказки укажут вас в правильном направлении.

0

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

// subclass UITableViewCell 

- (void)willTransitionToState:(UITableViewCellStateMask)state 
{ 
    [super willTransitionToState:state]; 

    if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableCellStateShowingDeleteConfirmationMask) 
    { 
     for (UIView *subview in self.subviews) 
     { 
      if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellDeleteConfirmationControl"]) 
      { 
       subview.hidden = YES; 
       subview.alpha = 0; 
      } 
     } 
    } 
} 

- (void)didTransitionToState:(UITableViewCellStateMask)state 
{ 
    [super willTransitionToState:state]; 

    if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableCellStateShowingDeleteConfirmationMask) 
    { 
     for (UIView *subview in self.subviews) 
     { 
      if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellDeleteConfirmationControl"]) 
      { 
       subview.frame = CGRectMake(subview.frame.origin.x - 10, subview.frame.origin.y, subview.frame.size.width, subview.frame.size.height); 
       subview.hidden = NO; 

       [UIView beginAnimations:@"anim" context:nil]; 
       subview.alpha = 1; 
       [UIView commitAnimations]; 
      } 
     } 
    } 
} 
+0

Как использовать это в swift –

58

Для меня лучший способ решить это переопределение -(void)layoutSubviews в MyCell:UITableViewCell

Здесь вы можете посмотреть не только на кнопку Удалить пользовательскую позицию, но и репозиционирование Edit и Reorder управления для Edit режим

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 

    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationBeginsFromCurrentState:YES]; 
    [UIView setAnimationDuration:0.0f]; 

    for (UIView *subview in self.subviews) { 


     if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellDeleteConfirmationControl"]) { 
      CGRect newFrame = subview.frame; 
      newFrame.origin.x = 200; 
      subview.frame = newFrame; 
     } 
     else if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellEditControl"]) {    
      CGRect newFrame = subview.frame; 
      newFrame.origin.x = 100; 
      subview.frame = newFrame; 
     } 
     else if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellReorderControl"]) {    
      CGRect newFrame = subview.frame; 
      newFrame.origin.x = 200; 
      subview.frame = newFrame; 
     } 
    } 
    [UIView commitAnimations]; 
} 
+4

Лучшее решение, чем принятое, так как здесь нет искусственной задержки в анимации кнопок. – Morrowless

+0

Отличное решение, отлично. – tarnfeld

+0

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

2

Я использую решение, которое на первый взгляд выглядит вроде Hacky, но делает трюк и не полагаясь на недокументированных APIs:

/** 
* Transition to state 
*/ 
-(void)willTransitionToState:(UITableViewCellStateMask)state { 

    if(state & UITableViewCellStateShowingDeleteConfirmationMask) 
     _deleting = YES; 
    else if(!(state & UITableViewCellStateShowingDeleteConfirmationMask)) 
     _deleting = NO; 
    [super willTransitionToState:state]; 

} 

/** 
* Reset cell transformations 
*/ 
-(void)resetCellTransform { 

    self.transform = CGAffineTransformIdentity; 
    _background.transform = CGAffineTransformIdentity; 
    _content.transform = CGAffineTransformIdentity; 
} 

/** 
* Move cell around if we are currently in delete mode 
*/ 
-(void)updateWithCurrentState { 

    if(_deleting) { 

     float x = -20; 
     float y = 0; 
     self.transform = CGAffineTransformMakeTranslation(x, y); 
     _background.transform = CGAffineTransformMakeTranslation(-x, -y); 
     _content.transform = CGAffineTransformMakeTranslation(-x, -y); 
    } 
} 

-(void)setFrame:(CGRect)frame { 

    [self resetCellTransform]; 
    [super setFrame:frame]; 
    [self updateWithCurrentState]; 
} 

-(void)layoutSubviews { 

    [self resetCellTransform]; 
    [super layoutSubviews]; 
    [self updateWithCurrentState]; 
} 

В основном это сдвигает положение ячейки и корректирует видимые части. WillTransitionToState просто устанавливает переменную экземпляра, указывающую, находится ли ячейка в режиме удаления. Переопределение setFrame было необходимо для поддержки поворота телефона на пейзаж и наоборот. Где _background - это фоновый вид моей ячейки, а _content - это представление, добавленное в contentView ячейки, хранение всех меток и т. Д.