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

bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetViewgroup); 

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

Ich habe diesen Code in meiner Tätigkeit des onCreate() -Methode, und ich bin die unten NPE Ausnahme erhalten, wenn die letzte Zeile ausgeführt wird:NullPointerExeption mit AppCompat BottomSheets

Verursacht durch: java.lang. NullPointerException: Versuch, die virtuelle Methode 'java.lang.Object java.lang.ref.WeakReference.get()' für einen Nullobjektverweis unter android.support.design.widget.BottomSheetBehavior.setState (BottomSheetBehavior.java:440)

+0

Haben Sie 'app: layout_behavior =" @ string/bottom_sheet_behavior "' zu Ihrem LinearLayout hinzugefügt? – RafaelC

+0

Ja, ich folgte diesem Tutorial http://www.materialdoc.com/bottom-sheets/ – Sanf0rd

+1

fügen Sie eine NPE-Prüfung hinzu, bevor Sie die letzte Zeile anrufen – Elltz

Antwort

12

Während die Antwort von Sanf0rds korrekt ist, ist es nicht möglich, das BottomSheet standardmäßig als erweitert zu definieren. Das Problem wird dadurch verursacht, dass die WeakReference erst in der letzten Zeile von onLayoutChild festgelegt wird.

Die Lösung besteht darin, eine eigene Klasse bereitzustellen, die BottomSheetBehavior erweitert, aber den Status in einem überschriebenen onLayoutChild festlegt. Der Code ist unten angegeben.

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 der Layoutdatei Referenzreferenz Ihre neue benutzerdefinierte Verhalten.

ändern

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

Um

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

Schön, das hat perfekt funktioniert. * Sehr * naiv!Sie sollten auch erwähnen, dass Sie das von 'from()' zurückgegebene Objekt umwandeln müssen. So etwas wie - 'bottomSheetBehavior = (HiddenBottomSheetBehavior) HiddenBottomSheetBehavior.from (bottomSheet);' –

+0

@guy Warum spielt das Casting eine Rolle? – ZakTaccardi

+1

Tolle Lösung! Wenn Sie (wie ich) beim Öffnen und Schließen Änderungen an der Ansicht vornehmen, müssen Sie in der überschriebenen Verhaltensklasse ein Flag setzen und das Dummy-Speichern/Wiederherstellen des Zustands nur beim ersten Mal durchführen. Andernfalls wird die Schublade immer wieder auf den hier definierten Ausgangszustand zurückgesetzt. – Groovee60

1

Ich habe eine Lösung gefunden, aber ich weiß immer noch nicht, warum das passiert. Die Lösung wird diese letzte Zeile zum Benutzeraufruf direkt nach dem Ausführen der Aktivität gesetzt. Bsp .: in einem ContextMenu Callback oder in einem beliebigen OnClickListener.

1

Das Problem mit dem Code ist, dass Sie versuchen, die setState Methode direkt in onCreate zu nennen. Dies wird einen NullPointer werfen, da die WeakReference noch nicht initialisiert ist. Es wird initialisiert, wenn das Coordinator-Layout die untergeordnete Ansicht ablegen soll.

onLayoutChild (CoordinatorLayout Eltern, V Kind, int layout)

aufgerufen, wenn die Eltern CoordinatorLayout über das Layout ist der gegeben Kind Blick.

Der beste Ansatz ist, die Peek-Höhe auf 0 zu setzen und innerhalb des onItemClick-Listeners ein-/auszublenden.

Ich habe diese Frage beantwortet: https://stackoverflow.com/a/36236743/1314796

1

Sie auch auf das globale Layout Ereignis hören betrachten kann, auf diese Weise können Sie sicher sein werden, dass die bottomsheet aufgebahrt wurde, wenn die zusammengeklappten Zustand zu versetzen.

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

dies versucht, aber alles, was ich bekommen ist java.lang.RuntimeException: Kann Aktivität starten: java.lang.NullPointerException: Der Versuch, virtuelle Methode ‚android.view.ViewTreeObserver android.view aufzurufen. View.getViewTreeObserver() 'auf einem Nullobjekt Referenz bei android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2946) verursacht durch: java.lang.NullPointerException: Versuch, virtuelle Methode' android.view.ViewTreeObserver android aufrufen .view.View.ViewViewTreeObserver() 'für eine Nullobjektverweis – kilokahn

Verwandte Themen