10
LinearLayout bottomSheetViewgroup = (LinearLayout) findViewById(R.id.bottomSheet); 

bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetViewgroup); 

bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); //this line 

Ho questo codice all'interno del metodo onCreate() della mia attività e sto ricevendo il seguito eccezione NPE quando viene eseguita l'ultima riga:NullPointerExeption con AppCompat BottomSheets

causati da: java.lang. NullPointerException: Tentativo di richiamare il metodo virtuale 'java.lang.Object java.lang.ref.WeakReference.get()' su un oggetto nullo di riferimento su android.support.design.widget.BottomSheetBehavior.setState (BottomSheetBehavior.java:440)

+0

Hai aggiunto 'app: layout_behavior =" @ string/bottom_sheet_behavior "' al tuo LinearLayout? – RafaelC

+0

sì, ho seguito questo tutorial http://www.materialdoc.com/bottom-sheets/ – Sanf0rd

+1

aggiungere un controllo NPE prima di chiamare l'ultima riga – Elltz

risposta

12

Mentre la risposta di Sanfrds è corretta, non consente la possibilità di definire il Foglio di base come espanso per impostazione predefinita. Il problema è causato dal fatto che WeakReference non è impostato fino all'ultima riga di onLayoutChild.

La soluzione è fornire la nostra classe che estende BottomSheetBehavior, ma imposta lo stato all'interno di overLidden suLayoutChild. Il codice è fornito di seguito.

uk/ac/qub/quibe/misc/ExpandedBottomSheetBehavior.java

package uk.ac.qub.quibe.misc; 

import android.content.Context; 
import android.support.design.widget.CoordinatorLayout; 
import android.util.AttributeSet; 
import android.view.View; 

/** 
* Created by mcp on 15/03/16. 
*/ 
public class ExpandedBottomSheetBehavior<V extends View> extends android.support.design.widget.BottomSheetBehavior<V> { 

    public ExpandedBottomSheetBehavior(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    @Override 
    public boolean onLayoutChild(final CoordinatorLayout parent, final V child, final int layoutDirection) { 
     SavedState dummySavedState = new SavedState(super.onSaveInstanceState(parent, child), STATE_EXPANDED); 
     super.onRestoreInstanceState(parent, child, dummySavedState); 
     return super.onLayoutChild(parent, child, layoutDirection); 
     /* 
      Unfortunately its not good enough to just call setState(STATE_EXPANDED); after super.onLayoutChild 
      The reason is that an animation plays after calling setState. This can cause some graphical issues with other layouts 
      Instead we need to use setInternalState, however this is a private method. 
      The trick is to utilise onRestoreInstance to call setInternalState immediately and indirectly 
     */ 
    } 

} 

In riferimento riferimento file di layout il nuovo comportamento personalizzato.

Change

app:layout_behavior="android.support.design.widget.BottomSheetBehavior" 

Per

app:layout_behavior="uk.ac.qub.quibe.misc.ExpandedBottomSheetBehavior" 
+1

Bello che ha funzionato perfettamente. * Molto * ingenuo!Dovresti anche dire che devi lanciare l'oggetto restituito da 'from()'. Qualcosa di simile - 'bottomSheetBehavior = (HiddenBottomSheetBehavior) HiddenBottomSheetBehavior.from (bottomSheet);' –

+0

@guy perché il casting è importante? – ZakTaccardi

+1

Ottima soluzione! Se (come me) state apportando modifiche alla vista mentre si apre e si chiude, sarà necessario impostare un flag nella classe di comportamento sottoposto a override ed eseguire il salvataggio/ripristino fittizio dello stato solo alla prima volta. In caso contrario, il cassetto continuerà a tornare allo stato iniziale definito qui. – Groovee60

1

Ho trovato una soluzione ma ancora non so perché questo accada. La soluzione è mettere questa ultima linea alla chiamata dell'utente direttamente dopo l'esecuzione dell'attività. Es: in un contestoMenu richiamata o in qualsiasi OnClickListener.

1

Il problema con il codice è che si sta tentando di chiamare il metodo setState direttamente all'interno onCreate. Ciò causerà un nullPointer perché il WeakReference non è ancora inizializzato. Verrà inizializzato quando il layout di Coordinator sta per posizionare la sua vista figlio.

onLayoutChild (CoordinatorLayout genitore, V bambino, int layoutDirection)

Chiamato quando il genitore CoordinatorLayout è circa il layout del determinata vista bambino.

Quindi l'approccio migliore è impostare l'altezza di sbirciare su 0 e mostrare/nascondere all'interno del listener onItemClick.

Ho risposto a questa domanda qui: https://stackoverflow.com/a/36236743/1314796

1

Si può anche considerare l'ascolto della manifestazione layout globale, in questo modo sarete sicuri che il bottomsheet è stato allestito durante l'impostazione stato compresso.

final View bottomSheet = findViewById(R.id.bottom_sheet); 
bottomSheet.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
      bottomSheet.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
      bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet); 
      bottomSheetBehavior.setPeekHeight(300); 
      bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); 
     } 
    }); 
+0

provato questo, ma tutto quello che ottiene è java.lang.RuntimeException: Impossibile avviare l'attività: java.lang.NullPointerException: Tentativo di richiamare il metodo virtuale 'android.view.ViewTreeObserver android.view. View.getViewTreeObserver() 'su un riferimento oggetto nullo su android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2946) Causato da: java.lang.NullPointerException: tentativo di richiamare il metodo virtuale' android.view.ViewTreeObserver android .view.View.getViewTreeObserver() 'su un riferimento a oggetti null – kilokahn