2013-04-18 24 views
17

Sto visualizzando immagini abbastanza grandi in un UITableView. Mentre l'utente scorre, mi piacerebbe che la vista tabella scatti sempre al centro la foto più centrale. Cioè, quando il tavolo è in uno stato di riposo, avrà sempre uno UITableViewCell scattato al centro.Vuoi UITableView su "snap alla cella"

Come si fa?

+0

si può fare questo modificando contentOffset del tavolo. –

+0

puoi usare, scrollview metodo delegate e contentoffset di UITableview, come suggerito da Nishant :) – Mangesh

risposta

29

È possibile utilizzare i metodi UIScrollViewDelegate su UITableView per fare questo:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { 
    // if decelerating, let scrollViewDidEndDecelerating: handle it 
    if (decelerate == NO) { 
     [self centerTable]; 
    } 
} 

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 
    [self centerTable]; 
} 

- (void)centerTable { 
    NSIndexPath *pathForCenterCell = [self.tableView indexPathForRowAtPoint:CGPointMake(CGRectGetMidX(self.tableView.bounds), CGRectGetMidY(self.tableView.bounds))]; 

    [self.tableView scrollToRowAtIndexPath:pathForCenterCell atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; 
} 
+0

Grazie! Il pezzo che stavo cercando era come individuare quale cella fosse il più centrale (il metodo centerTable). – VaporwareWolf

+0

Funzionerà, ma causerà uno strano scroll dopo che la vista tabella si sarà fermata. –

+0

D'accordo con Jesse Rusak. Alla ricerca di un attimo durante la pergamena. – quantumpotato

14

C'è un metodo delegato UIScrollView appositamente per questo!

La vista tabella (che è una vista di scorrimento) chiamerà - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset quando l'utente interrompe lo scorrimento. Puoi impostare manipolare lo targetContentOffset per assicurarti che finisca dove vuoi, e decelererà fino alla fine in quella posizione (proprio come un UIScrollView di impaginazione).

Per esempio, se le cellule erano alti tutti i 100 punti, si potrebbe fare:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { 
    targetContentOffset->y = 100 * (int)targetContentOffset->y/100; 
} 

Naturalmente, è anche possibile ispezionare il targetContentOffset passato per vedere dove stava andando a terra, e poi trovare la cellula che si trova e la modifica in modo appropriato.

+0

Grazie. Anche questo è utile. – VaporwareWolf

+0

Il tuo codice lancia un avviso in Xcode 6.3 con iOS 8. Ho dovuto usare il seguente codice, ma non sta facendo nulla. targetContentOffset-> x = 100 * (int) targetContentOffset/100; Qualche idea del perché? – user3344977

+0

Hey Jesse Ho notato il tuo commento sulla risposta sopra "Questo funzionerà, ma causerà uno strano piccolo scroll dopo che la vista tabella si sarà fermata". - Se riesco a far funzionare la risposta, produrrà più di un effetto paging/snap per scorrere? Apprezzo davvero l'aiuto. – user3344977

-3

UITableView estende UIScrollView ...

myTableView.pagingEnabled = YES 
5

Compilare da quello @jszumski postato, se si desidera che lo snap si verifichi metà trascinare, utilizzare questo codice:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { 
    [self centerTable]; 
} 

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { 
    [self centerTable]; 
} 

- (void)centerTable { 
    NSIndexPath *pathForCenterCell = [self.tableView indexPathForRowAtPoint:CGPointMake(CGRectGetMidX(self.tableView.bounds), CGRectGetMidY(self.tableView.bounds))]; 

    [self.tableView scrollToRowAtIndexPath:pathForCenterCell atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; 
} 
+1

Non sono sicuro di cosa significhi questa risposta con "trascinamento medio", ma dopo averlo implementato, ho verificato che esso attende fino a quando non si assesta il momento di resistenza prima di eseguire lo snap in posizione. Questo ha senso, poiché didEndDragging e willBeginDecelerating non vengono chiamati fino ad allora. È molto più vicino se si annulla lo scorrimento continuo utilizzando questo metodo: http://stackoverflow.com/a/3421387/111243, quindi si blocca non appena si interrompe il trascinamento, ma non ancora lo snap mid-drag. – SimplGy

5

estensione @ Jesse-rusak di rispondi sopra, questo è il codice che dovresti aggiungere alla sottoclasse UITableViewController se hai celle con altezze variabili. Ciò eviterà il problema del doppio scorrimento nella risposta accettata.

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { 
    NSIndexPath *pathForTargetTopCell = [self.tableView indexPathForRowAtPoint:CGPointMake(CGRectGetMidX(self.tableView.bounds), targetContentOffset->y)]; 
    targetContentOffset->y = [self.tableView rectForRowAtIndexPath:pathForTargetTopCell].origin.y; 
} 
0

per il capolino veloci

override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) 
{ 
    if decelerate == false 
    { 
     self.centerTable() 
    } 
} 

override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 
    self.centerTable() 
} 

func centerTable() 
{ 
    let midX:CGFloat = self.tableView.bounds.midX 
    let midY:CGFloat = self.tableView.bounds.midY 
    let midPoint:CGPoint = CGPoint(x: midX, y: midY) 

    if let pathForCenterCell:IndexPath = self.tableView .indexPathForRow(at: midPoint) 
    { 
     self.tableView.scrollToRow(at: pathForCenterCell, at: .middle, animated: true) 
    } 
}//eom