Подтвердить что ты не робот

NullPointerException с AppCompat BottomSheets

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

bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetViewgroup);

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

У меня есть этот код в моем onCreate() и я получаю исключение NPE ниже, когда выполняется последняя строка:

Вызывается: java.lang.NullPointerException: попытка вызвать виртуальный метод 'java.lang.Object java.lang.ref.WeakReference.get()' для пустой ссылки на объект в android.support.design.widget.BottomSheetBehavior.setState( BottomSheetBehavior.java:440)

4b9b3361

Ответ 1

В то время как ответ Sanf0rds верен, он не позволяет определять значение BottomSheet как расширенное по умолчанию. Проблема вызвана тем, что WeakReference не устанавливается до последней строки onLayoutChild.

Решение состоит в том, чтобы предоставить наш собственный класс, который расширяет 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"

Ответ 2

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;
    }
  }
}

Ответ 3

Проблема с вашим кодом заключается в том, что вы пытаетесь вызвать метод setState непосредственно внутри onCreate. Это будет генерировать nullPointer, потому что WeakReference еще не инициализирован. Он будет инициализирован, когда планировщик Координатора собирается разместить дочерний вид.

onLayoutChild (координаторLayout parent, V child, int layoutDirection)

Вызывается, когда родительский координаторLayout представляет собой с учетом детского просмотра.

Таким образом, наилучшим подходом является высота заглядывания до 0 и отображение/скрытие внутри прослушивателя onItemClick.

Я ответил на этот вопрос здесь: fooobar.com/questions/189194/...

Ответ 4

Я нашел решение, но до сих пор не знаю, почему это происходит. Решение положено этой последней строкой на вызов пользователя сразу после запуска этой операции. Пример: в обратном вызове contextMenu или в любом OnClickListener.

Ответ 5

Вы также можете рассмотреть возможность прослушивания глобального события макета, таким образом, вы будете уверены, что нижняя панель была выложена при настройке состояния свертывания.

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);
        }
    });