15

Ho un frammento che utilizza il nuovo paradigma CoordinatorLayout/AppBarLayout/CollapsingToolbarLayout e vorrei essere in grado di rilevare quando la barra degli strumenti comprendente è completamente espansa in modo da poter eseguire un'operazione sull'intero frammento in cui si trova, ad es popping il frammento dallo stack e andare a uno nuovo, che respinge il frammento. Ho il codice di congedo di lavoro, ho solo bisogno di sapere quando e quando non usarlo.Rilevamento quando AppBarLayout/CollapsingToolbarLayout è completamente espanso

Ho sperimentato un po 'con AppBarLayout.OnOffsetChangedListener, ma non ha avuto molta fortuna. C'è un modo di usarlo per determinare quando le cose sono completamente espanse, o c'è un metodo più preferito qualcuno conosce?

Grazie in anticipo!

MODIFICA: Vedo anche che ci sono un paio di implementazioni per AppBarLayout.setExpanded(...), tuttavia non AppBarLayout.getExpanded() o qualcosa di simile, quindi sono anche lì perplesso.

+0

forse appBarLayout.addOnOffsetChangedListener potrebbe aiutare ma ho trovato buggy propably non ha attuato correttamente. – mstrengis

+0

Hai trovato una soluzione per questo? Ho avuto lo stesso problema cercando di impedire un ScrollRefreshLayout di aggiornamento quando la barra degli strumenti è parzialmente compressa. – Jimeux

risposta

26

Non sembra che ci sia qualcosa nelle API, ma quanto segue sembra funzionare per me. Potrebbe aver bisogno di test.

boolean fullyExpanded = 
    (appBarLayout.getHeight() - appBarLayout.getBottom()) == 0; 

Edit: La soluzione di cui sopra sembra funzionare, ma da quando ho voluto mettere alla prova questa condizione quando l'appbar è stato fatto scorrere, ho finito per usare la seguente soluzione con OnOffsetChangedListener.

class Frag extends Fragment implements AppBarLayout.OnOffsetChangedListener { 

    private boolean appBarIsExpanded = true; 
    private AppBarLayout appBarLayout; 

    @Override 
    public void onActivityCreated(Bundle state) { 
     super.onActivityCreated(state); 
     appBarLayout = (AppBarLayout) getActivity().findViewById(R.id.app_bar); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     appBarLayout.addOnOffsetChangedListener(this); 
    } 

    @Override 
    public void onStop() { 
     super.onStop(); 
     appBarLayout.removeOnOffsetChangedListener(this); 
    } 

    @Override 
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { 
     appBarIsExpanded = (verticalOffset == 0); 
    } 

} 
+0

Ho finito per abbandonare il concetto alla base del perché volevo farlo in primo luogo, ma accetterò la tua risposta dal momento che tu dici che sta funzionando per te. Grazie! –

+0

neanche questo funziona per me. aggiunta l'implementazione dell'interfaccia ma non sembra essere chiamata –

+1

@ user1232726 È necessario collegare il listener all'AppBarLayout. Ho aggiornato il codice con un modo per farlo. Se non ti preoccupi delle potenziali perdite, semplicemente usando 'appBarLayout.setOnScrollChangeListener (this)' farà il lavoro. – Jimeux

6

La mia soluzione è basata sulla creazione di una vista personalizzata. In primo luogo creare una classe che estende l'AppBarLayout origini:

public class CustomAppBar extends AppBarLayout { .... 

Poi all'interno della classe impostare un addOnOffsetChangedListener come questo:

this.addOnOffsetChangedListener... 

È possibile fare quanto sopra impostando nel costruttore o forse chiamando un metodo all'interno il costruttore. Quindi è necessario il costruttore, ricordarsi di utilizzare il costruttore con 2 params per essere in grado di aggiungere alla xml:

public CustomAppBar(Context context, AttributeSet attrs) { 
     super(context, attrs); 
//You can set the listener here or maybe call the method that set the listener 
} 

allora dobbiamo avere accesso allo stato della vista, in modo da creare un valore booleano privato all'interno della vostra classe di visualizzazione personalizzata, e impostarlo su true o false se la vista iniziale espanso o compresso, in questo caso il mio punto di vista è per default ampliato:

private boolean isExpanded = true; 

Ora è necessario aggiornare lo stato di quel booleano:

this.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { 
      @Override 
      public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { 
       if (verticalOffset == 0) { 
        isExpanded = true; 
       } else { 
        isExpanded = false; 
       } 
      } 
     }); 

passo successivo è quello di ottenere lo stato del booleano utilizzando un getter all'interno della classe CustomAppBar

public boolean isExpanded() { 
     return isExpanded; 
    } 

Il prossimo è andare al tuo XML, utilizzare la visualizzazione personalizzata lì, poi nel acivity o frammento ottenere la vista e utilizzare il metodo di conoscere lo stato AppBar

+0

Sembra un overkill quando puoi semplicemente aggiungere un 'OnOffsetChangedListener' direttamente all'istanza' AppBarLayout'. –

+0

Se userai solo AppBarLayout una volta sola: sì lo è. Ma se più di un'attività ha bisogno di conoscere lo stato AppBarLayout, allora: questa è una soluzione DRY – cutiko

0

so, che forse un po 'tardi, ma esplorando il codice sorgente del AppBArLayout ho trovato, che la AppBarLayout.OnOffsetChangedListener solo traduce il valore della int getTopAndBottomOffset() del Ap pBar's Behaviour.

Quindi, in qualsiasi momento si può semplicemente utilizzare questo codice per definire se un AppBarLayout ampliato o no:

public boolean isAppBArExpanded(AppBarLayout abl) { 
    final CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) abl.getLayoutParams()).getBehavior(); 
    return (behavior instanceof AppBarLayout.Behavior) ? (((AppBarLayout.Behavior) behavior).getTopAndBottomOffset() == 0) : false; 
}