2014-11-05 15 views
12

Ho un UITableView in cui l'utente può scorrere verso sinistra per rivelare azioni (come nella posta di iOS 8). Tutto funziona come previsto. Voglio attivarlo quando l'utente tocca una determinata parte della cella. Come posso richiamare questa azione di diapositiva a livello di programmazione?UITableView invoca le azioni di scorrimento programmaticamente

Comportamento corrente: l'utente deve scorrere la cella verso sinistra per rendere noti i pulsanti di azione.

Comportamento desiderato: l'utente tocca (un pulsante azioni) sulla cella. La cella scorre per rivelare i pulsanti di azione.

+0

Hai mai trovato un modo programmatico per farlo diverso dalla tua soluzione alternativa? Grazie – rwyland

+0

Non l'ho fatto. Non penso che ci sia un'API pubblica per questo in questo momento. Forse iOS 9? – VaporwareWolf

+0

Un modo per mostrare UITableViewRowAction senza scorrere ma facendolo programmatelly per mostrare l'interazione dell'utente? –

risposta

10

Beh, non sono riuscito a trovare un modo per farlo a livello di codice, ma ho trovato questa soluzione alternativa. Quando l'utente tocca la cella, l'ho animato (pan) a sinistra per rivelare momentaneamente un pulsante "Swipe Me" afake. Questo viene rapidamente invertito in modo che la cella ritorni alla normalità. Questo fornisce un segnale visivo per far sapere all'utente che è possibile far scorrere la cella:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 

    __block UILabel *swipeLabel = [[UILabel alloc]initWithFrame:CGRectMake(cell.bounds.size.width, 
                    0, 
                    200, 
                    cell.bounds.size.height)]; 

    swipeLabel.text = @" Swipe Me"; 
    swipeLabel.backgroundColor = [UIColor greenColor]; 
    swipeLabel.textColor = [UIColor whiteColor]; 
    [cell addSubview:swipeLabel]; 

    [UIView animateWithDuration:0.3 animations:^{ 
     [cell setFrame:CGRectMake(cell.frame.origin.x - 100, cell.frame.origin.y, cell.bounds.size.width, cell.bounds.size.height)]; 
    } completion:^(BOOL finished) { 
     [UIView animateWithDuration:0.3 animations:^{ 
      [cell setFrame:CGRectMake(cell.frame.origin.x + 100, cell.frame.origin.y, cell.bounds.size.width, cell.bounds.size.height)]; 
     } completion:^(BOOL finished) { 
      [swipeLabel removeFromSuperview]; 
      swipeLabel = nil; 
     }]; 
    }]; 
} 

Spero che questo aiuti qualcuno.

Nota che è necessario impostare il tipo di selezione di TableViewCell su none. Altrimenti la barra grigia la oscurerà.

Aggiornamento . ho pensato di postare un più Swifty versione:

func previewActions(forCellAt indexPath: IndexPath) { 
    guard let cell = tableView.cellForRow(at: indexPath) else { 
     return 
    } 

    let label: UILabel = { 
     let label = UILabel(frame: CGRect.zero) 
     label.text = " Swipe Me " 
     label.backgroundColor = .blue 
     label.textColor = .white 
     return label 
    }() 

    // Figure out the best width and update label.frame 
    let bestSize = label.sizeThatFits(label.frame.size) 
    label.frame = CGRect(x: cell.bounds.width - bestSize.width, y: 0, width: bestSize.width, height: cell.bounds.height) 
    cell.insertSubview(label, belowSubview: cell.contentView) 

    UIView.animate(withDuration: 0.3, animations: { 
     cell.transform = CGAffineTransform.identity.translatedBy(x: -label.bounds.width, y: 0) 
     label.transform = CGAffineTransform.identity.translatedBy(x: label.bounds.width, y: 0) 
    }) { (finished) in 
     UIView.animateKeyframes(withDuration: 0.3, delay: 0.25, options: [], animations: { 
      cell.transform = CGAffineTransform.identity 
      label.transform = CGAffineTransform.identity 
     }, completion: { (finished) in 
      label.removeFromSuperview() 
     }) 
    } 
} 

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
    previewActions(forCellAt: indexPath) 
    return 
} 
+1

Fantastico. Per la seconda parte ho usato un ritardo invece così il testo si presenta per una frazione di secondo '[UIView animateWithDuration: 0.5 ritardo: 0.5 opzioni: 0 animazioni:^{ [SETFRAME cella: CGRectMake (cell.frame.origin .x + 100, cell.frame.origin.y, cell.bounds.size.width, cell.bounds.size.height)]; } completamento:^(BOOL terminato) { [swipeLabel removeFromSuperview]; swipeLabel = nil; }]; ' – CyberMew

+0

Ottimo! Assicurati anche che "Clip to bounds" sia disabilitato o che l'etichetta non sia visibile. – rstewart22

4

Per chi è alla ricerca della versione Swift della risposta di VaporwareWolf, eccolo:

func animateRevealHideActionForRow(tableView: UITableView, indexPath: NSIndexPath) { 
    let cell = tableView.cellForRowAtIndexPath(indexPath); 

    // Should be used in a block 
    var swipeLabel: UILabel? = UILabel.init(frame: CGRectMake(cell!.bounds.size.width, 
     0, 
     200, 
     cell!.bounds.size.height)) 

    swipeLabel!.text = " Swipe Me"; 
    swipeLabel!.backgroundColor = UIColor.init(red: 255/255, green: 41/255, blue: 53/255, alpha: 1) // Red 
    swipeLabel!.textColor = UIColor.whiteColor() 
    cell!.addSubview(swipeLabel!) 

    UIView.animateWithDuration(0.3, animations: { 

     cell!.frame = CGRectMake(cell!.frame.origin.x - 100, cell!.frame.origin.y, cell!.bounds.size.width + 100, cell!.bounds.size.height) 

    }) { (finished) in 
     UIView.animateWithDuration(0.3, animations: { 

      cell!.frame = CGRectMake(cell!.frame.origin.x + 100, cell!.frame.origin.y, cell!.bounds.size.width - 100, cell!.bounds.size.height) 

      }, completion: { (finished) in 
       swipeLabel?.removeFromSuperview() 
       swipeLabel = nil; 
     }) 

    } 
} 
0

E per una versione di Swift 3 in cui si voglio chiamare questa funzione per ogni riga.

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

    let cell = tableView.cellForRow(at: indexPath); 
    UIView.animate(withDuration: 0.3, animations: { 

     cell!.frame = CGRect(x: cell!.frame.origin.x - 100, y: cell!.frame.origin.y, width: cell!.bounds.size.width + 100, height: cell!.bounds.size.height) 

    }) { (finished) in 
     UIView.animate(withDuration: 0.3, animations: { 

      cell!.frame = CGRect(x: cell!.frame.origin.x + 100, y: cell!.frame.origin.y, width: cell!.bounds.size.width - 100, height: cell!.bounds.size.height) 

     }, completion: { (finished) in 
     }) 
    } 
} 
0

Swift 3 Equivalente della risposta di Burak. È possibile attivare questa chiamata programmaticamente dove vuoi, l'ho messa in una funzione di supporto in modo che qualsiasi visualizzazione tabella possa mostrarlo. E la prima volta che un utente usa la mia app lo faccio scorrere (ho sentito che era necessario un tempo di animazione più lungo).

class func animateRevealHideActionForRow(tableView: UITableView, indexPath: NSIndexPath) { 
    let cell = tableView.cellForRow(at: indexPath as IndexPath); 

    // Should be used in a block 
    var swipeLabel: UILabel? = UILabel.init(frame: CGRect.init(x: cell!.bounds.size.width, y: 0, width: 200, height: cell!.bounds.size.height)) 

    swipeLabel!.text = " Swipe Me"; 
    swipeLabel!.backgroundColor = UIColor.red 
    swipeLabel!.textColor = UIColor.white 
    cell!.addSubview(swipeLabel!) 

    UIView.animate(withDuration: 1.0, animations: { 
     cell!.frame = CGRect.init(x: cell!.frame.origin.x - 100, y: cell!.frame.origin.y, width: cell!.bounds.size.width + 100, height: cell!.bounds.size.height) 
    }) { (finished) in 
     UIView.animate(withDuration: 1.0, animations: { 
      cell!.frame = CGRect.init(x: cell!.frame.origin.x + 100, y: cell!.frame.origin.y, width: cell!.bounds.size.width - 100, height: cell!.bounds.size.height) 
     }, completion: { (finished) in 
      swipeLabel?.removeFromSuperview() 
      swipeLabel = nil; 
     }) 
    } 
} 
Problemi correlati