2016-03-25 22 views
8

Sto utilizzando foglio di fondo dalla libreria di supporto Android come questo:Supporto Android BottomSheetBehavior non può essere dinamico?

XML:

<LinearLayout 
    android:id="@+id/bottomSheetLinearLayout" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:background="@color/fourth_white" 
    android:orientation="vertical" 
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior" /> 

aggiungo viste bambino per LinearLayout:

bottomSheet.addView(actionButtonView); 

Dopo che ho finito l'aggiunta di vista del bambino , Inizializzo BottomSheetBehavior ed espanderlo:

BottomSheetBehavior sheetBehavior = BottomSheetBehavior.from(bottomSheet); 
sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); 

Questo non funziona Niente mostra. Anche se preimposta l'altezza LinearLayout all'interno di XML, è solo tutto bianco.

Se aggiungo tutte le viste figlio all'interno di LinearLayout in XML, quindi tutto funziona correttamente. Semplicemente non funziona quando provo ad aggiungere dinamicamente le viste in modo programmatico.

Qualcuno ha avuto problemi simili?

+0

Mostra il codice per una migliore comprensione ... – Vickyexpert

+1

Potresti pubblicare il codice completo come si aggiungono le viste al 'BottomSheet'? Perché ho appena provato a riprodurre, e non ho avuto quel problema. – rom4ek

+0

puoi pubblicare il codice per il viewgroup esterno a cui stai aggiungendo il foglio inferiore? Se possibile, inserisci il codice completo isolato per riprodurre questo comportamento. Perché come @ rom4ek ha detto che non sono in grado di riprodurre il suddetto numero –

risposta

1

Problemi con contenuti dinamici su BottomSheetBehavior relative all'attuazione di esso è espansa calcolo delle dimensioni. BottomSheetBehavior calcola le dimensioni espanse nel metodo onLayoutChild. Ma quando si modifica il contenuto del processo di layout del foglio viene avviato in modo asincrono. Anche se chiami RequestLayout o qualcosa di simile. Quindi conseguenza di chiamate è simile a questo:

  1. BottomSheetBehavior hanno vecchio formato espanso (nel tuo caso penso che sia pari a zero)
  2. si aggiunge il contenuto al BottomSheet. La dimensione espansa è ancora vecchia.
  3. Si chiama SetState su EXPANDED. BottomSheetBehavior ricorda ancora le vecchie dimensioni espanse e avvia l'animazione a quella dimensione. Stato modificato in STATE_SETTLING!
  4. onLayoutChild chiamato e BottomSheetBehavior calcola la nuova dimensione espansa. Ma l'animazione è già in corso e lo stato è STATE_SETTLING quindi BottomSheetBehavior non modifica la sua dimensione
  5. Animazione terminata. La dimensione di BottomSheet è vecchia. Stato modificato in EXPANDED ma BottomSheetBehavior "dimenticato" che la dimensione espansa è stata modificata durante l'animazione.

È sicuramente il bug dell'implementazione di BottomSheetBehaviour.

Nel mio progetto ho trovato tale soluzione:

private void showPanel(final View panelContent) { 
    if (panelBehavior.getState()!=BottomSheetBehavior.STATE_EXPANDED) { 
     panelBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { 
      @Override 
      public void onStateChanged(final View bottomSheet, int newState) { 
       if (newState==BottomSheetBehavior.STATE_EXPANDED) { 
        panelBehavior.setBottomSheetCallback(null); 
        contentView.removeAllViews(); 
        contentView.addView(panelContent); 
        panelView.setVisibility(View.VISIBLE); 

       } 
      } 

      @Override 
      public void onSlide(View bottomSheet, float slideOffset) { 

      } 
     }); 
     panelBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); 
     return; 
    } 
    contentView.removeAllViews(); 
    contentView.addView(panelContent); 
    panelView.setVisibility(View.VISIBLE); 
} 

private void hidePanel() { 
    panelBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); 
    panelView.setVisibility(View.GONE); 
    contentView.removeAllViews(); 
} 

Così, quando è necessario mostrare BottomSheet con nuove ShowPanel chiamata di contenuto. Quando è necessario nascondere completamente la chiamata BottomSheet hidePanel (se è necessario nasconderlo nel progetto, altrimenti è possibile rimuovere setVisibility dai metodi).

L'idea di soluzione alternativa è di non modificare mai il contenuto di BottomSheet quando BottomSheetBehavior non è in stato espanso. Se lo stato non è espanso, basta cambiarlo in espanso, attendere che l'animazione sia terminata e solo successivamente modificare il contenuto.

1

tenta di registrare eseguibile a coda di messaggi di vista:

bottomSheet.post(new Runnable() { 
    @Override 
    public void run() { 
     bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); 
    } 
}); 

O con retrolambda:

bottomSheet.post(() -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED));