26

Un'app che sto sviluppando visualizza una griglia di immagini. Quando tocchi un'immagine, questa entra nella vista dettagli. La vista dettagli contiene un ViewPager che consente di scorrere ogni immagine nella griglia. Questo viene fatto passando un elenco di percorsi (contenente ogni immagine nella griglia), insieme a un offset dell'immagine che è stata toccata in modo che il ViewPager possa essere impostato per mostrare inizialmente quella pagina.Frammenti ViewPager - Transizioni elemento condiviso

Qual è il modo migliore per avere una transizione di elemento condiviso all'interno del frammento della pagina di offset corrente in ViewPager? L'immagine della griglia (RecyclerView) dovrebbe espandersi nell'immagine a schermo intero nella pagina corrente. Ho visto la possibilità di posticipare e riprendere le transizioni di attività, quindi l'app aspetterebbe di visualizzare la transizione dell'elemento condiviso fino a quando l'immagine non viene caricata dal disco. Ma voglio essere in grado di farlo animare alla pagina corretta nel pager della vista, e anche di uscire a qualunque sia la pagina corrente quando l'utente torna (dato che puoi scorrere tra le pagine). Se passi rapidamente a una pagina diversa, la pagina iniziale è ciò che torna alla griglia.

Attualmente, assegno ogni immagine nei Frammenti del cercapersone di visualizzazione con un nome di transizione nel formato "immagine_ [indice]". Quando avvio l'attività di dettaglio, utilizzo lo stesso transitionName con l'indice come offset.

In relazione a questo, mi chiedevo anche come far funzionare le increspature con le lunghe pressioni. Quando si modifica lo stato attivato di una vista, sembra annullare l'ondulazione. Voglio un effetto simile a Gmail, in cui l'ondulazione ricomincia e termina rapidamente dopo che è stata completata una pressione lunga e attiva lo stato attivato.

+0

Si potrebbe voler porre la seconda domanda sul ripple in un post separato. Inoltre, posso dare una risposta più approfondita alla tua domanda sul visualizzatore di pagine e sugli elementi condivisi domani quando avrò più tempo, ma per ora puoi dare un'occhiata [questo progetto di esempio] (https://github.com/alexjlockwood/activity -transitions). L'ho scritto poche settimane fa e sembra che faccia quasi esattamente quello che stai descrivendo. : P –

+0

@AlexLockwood buon punto. E wow, hai ragione, l'ho appena eseguito ed è praticamente esattamente ciò di cui ho bisogno; Dovrò guardarlo nei prossimi giorni, grazie! – afollestad

+0

Ciao questo non funziona per me .. quello che sto provando è che ho una lista in un frammento di viewpager e al clic di qualsiasi oggetto voglio trasformare l'immagine nel suo frammento di dettaglio .. ho provato ogni possibile soluzione che ho qui ..ma niente sta funzionando..questo aiuto sarà apprezzato.grazie in anticipo. - –

risposta

34

Da quello che posso dire (e correggermi se ho torto), quello che stai cercando di ottenere è fondamentalmente qualcosa del genere: Supponi di avere uno MainActivity, uno DetailsActivity e un insieme arbitrario di immagini. Lo MainActivity visualizza il set di immagini in una griglia e lo DetailsActivity visualizza lo stesso set di immagini in un ViewPager orizzontale. Quando l'utente seleziona un'immagine nello MainActivity, quell'immagine deve passare dalla sua posizione nella griglia alla pagina corretta nel ViewPager della seconda attività.

Il problema che vogliamo risolvere è "cosa succede se l'utente cambia le pagine all'interno dello DetailsActivity"? Se ciò accade, vogliamo cambiare l'immagine condivisa che verrà utilizzata durante la transizione di ritorno. Per impostazione predefinita, il framework di transizione attività utilizzerà l'elemento condiviso che è stato utilizzato durante la transizione di invio ... ma la pagina del pager della vista è cambiata, quindi ovviamente vogliamo in qualche modo sovrascrivere questo comportamento.Per fare questo, avremo bisogno di impostare un SharedElementCallback nei vostri MainActivity e DetailsActivity l' onCreate() metodi e l'override del metodo onMapSharedElements() in questo modo:

private final SharedElementCallback mCallback = new SharedElementCallback() { 
    @Override 
    public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) { 
     if (mCurrentImagePosition != mOriginalImagePosition) { 
      View sharedView = getImageAtPosition(mCurrentImagePosition); 
      names.clear(); 
      sharedElements.clear(); 
      names.add(sharedView.getTransitionName()); 
      sharedElements.put(sharedView.getTransitionName(), sharedView); 
     } 
    } 

    /** 
    * Returns the image of interest to be used as the entering/returning 
    * shared element during the activity transition. 
    */ 
    private View getImageAtPosition(int position) { 
     // ... 
    } 
}; 

Per una soluzione più completa, ho creato un sample project on GitHub che permetterà di conseguire questo effetto (c'è troppo codice da pubblicare in una singola risposta StackOverflow).

+0

Questo è perfetto, grazie per il vostro aiuto! – afollestad

+0

Ciao questo non funziona per me .. quello che sto provando è che ho una lista in un frammento di viewpager e al clic di qualsiasi oggetto voglio trasformare l'immagine nel suo frammento di dettaglio .. ho provato ogni possibile soluzione che ho qui ..ma niente sta funzionando..questo aiuto sarà apprezzato.grazie in anticipo. - –

+0

Grazie, molto utile! – schwertfisch

3

Suppongo che tu stia utilizzando Fragment Transitions e che non stai animando tra le Attività. È possibile in Transizioni di attività e Transizioni di frammenti, ma il codice specifico è leggermente diverso. Tuttavia, il posticipo non è disponibile su Fragment Transitions.

addSharedElement accetta un secondo parametro. Se conosci il nome specifico nel frammento di destinazione quando lo chiami, puoi semplicemente scegliere il nome nel frammento di dettagli da utilizzare. Se non lo fai, puoi scegliere il nome che desideri e rimapparlo con il set SharedElementCallback sul frammento.

fragment.setEnterSharedElementCallback(new SharedElementCallback() { 
    @Override 
    public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) { 
     sharedElements.put("detailView", mTargetDetailView); 
    } 
}); 

Se non corrisponde al ritorno, viene effettuata la stessa chiamata per rimapparlo. Probabilmente questo sarà sia nel frammento chiamante che nel frammento chiamato - sul frammento chiamante, si usa setExitSharedElementCallback. Mi aspetto che questo avvenga nella tua app.

Allo stesso modo, in Transizioni di attività, si imposta lo stesso SharedElementCallback e si utilizza la stessa mappatura, ma lo si fa invece sull'attività.

+0

Questo è sicuramente un progresso verso ciò che voglio fare, il problema è che ci sono due attività. Uno mostra Frammenti che contengono griglie di immagini. L'altro contiene un ViewPager che contiene frammenti di dettaglio. – afollestad

+0

Stai utilizzando le transizioni di attività e succede solo che le tue viste siano in frammenti. Probabilmente dovrai posticipare la transizione di invio o eseguire la transazione frammento in sospeso su onCreate. Quali problemi stai vedendo ora? –

Problemi correlati