image_id
我在我的活动的onCreate()方法中有这个代码,并且在执行最后一行时我得到了以下的NPE异常:
引起:java.lang.NullPointerException: 尝试调用虚方法' java.lang.Object java.lang.ref.WeakReference.get()'在null对象引用上 在android.support.design.widget.BottomSheetBehavior.setState(BottomSheetBehavior.java:440)
答案 0 :(得分:14)
虽然Sanf0rds的答案是正确的,但它不允许默认情况下将BottomSheet定义为扩展。问题是由于onLayoutChild的最后一行没有设置WeakReference引起的。
解决方案是提供我们自己的类,它扩展了BottomSheetBehavior,但在重写的onLayoutChild中设置状态。代码如下所示。
英国/ AC / QUB / quibe /杂项/ 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
*/
}
}
在布局文件参考中引用您的新自定义行为。
更改
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
要
app:layout_behavior="uk.ac.qub.quibe.misc.ExpandedBottomSheetBehavior"
答案 1 :(得分:4)
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) {
return super.onLayoutChild(parent, child, layoutDirection);
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
try {
return super.onInterceptTouchEvent(parent, child, event);
} catch (NullPointerException ignored) {
return false;
}
}
}
答案 2 :(得分:2)
您的代码的问题是您尝试直接在onCreate中调用setState方法。这将抛出一个nullPointer,因为WeakReference尚未初始化。当协调器布局即将放置其子视图时,它将被初始化。
onLayoutChild(CoordinatorLayout parent,V child,int layoutDirection)
当父级CoordinatorLayout关于布局时调用 给予孩子观点。
因此,最佳方法是将peek height设置为0并在onItemClick侦听器中显示/隐藏。
我在这里回答了这个问题: https://stackoverflow.com/a/36236743/1314796
答案 3 :(得分:1)
我找到了一个解决方案,但我仍然不知道为什么会这样。在活动运行后,解决方案将最后一行放在用户调用中。例如:在contextMenu回调或任何OnClickListener中。
答案 4 :(得分:1)
您还可以考虑收听全局布局事件,这样您就可以确保在设置折叠状态时已经布置了底片。
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);
}
});