library - implementation com android support design




Установить состояние BottomSheetDialogFragment расширенным (6)

«Обратите внимание, что вы не можете вызвать метод перед просмотром макетов».

Приведенный выше текст является ключом.

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

Итак, в onCreateDialog() вашего модального нижнего листа ( BottomSheetFragment ) непосредственно перед возвратом диалогового окна (или в любом месте, когда у вас есть ссылка на диалоговое окно), вызовите

// This listener's onShow is fired when the dialog is shown
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
    @Override
    public void onShow(DialogInterface dialog) {

        // In a previous life I used this method to get handles to the positive and negative buttons
        // of a dialog in order to change their Typeface. Good ol' days.

        BottomSheetDialog d = (BottomSheetDialog) dialog;

        // This is gotten directly from the source of BottomSheetDialog
        // in the wrapInBottomSheet() method
        FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);

        // Right here!
        BottomSheetBehavior.from(bottomSheet)
            .setState(BottomSheetBehavior.STATE_EXPANDED);
    }
});

В моем случае мой пользовательский BottomSheet оказался:

@SuppressWarnings("ConstantConditions")
public class ShareBottomSheetFragment extends AppCompatDialogFragment {

    @NonNull @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        BottomSheetDialog dialog =
                new BottomSheetDialog(getActivity(), R.style.Haute_Dialog_ShareImage);

        dialog.setContentView(R.layout.dialog_share_image);

        dialog.findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });

        dialog.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                BottomSheetDialog d = (BottomSheetDialog) dialog;

                FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        });

        SwitchCompat switchview = (SwitchCompat) dialog.findViewById(R.id.switchview);
        switchview.setTypeface(FontCache.get(dialog.getContext(), lookup(muli, NORMAL)));

        return dialog;
    }
}

Позвольте мне знать, если это помогает.

ОБНОВИТЬ

Обратите внимание, что вы также можете переопределить BottomSheetDialogFragment как:

public class SimpleInitiallyExpandedBottomSheetFragment extends BottomSheetDialogFragment {

    @NonNull @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);

        dialog.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                BottomSheetDialog d = (BottomSheetDialog) dialog;

                FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        });

        // Do something with your dialog like setContentView() or whatever
        return dialog;
    }
}

Но я действительно не понимаю, почему кто-то хотел бы сделать это, так как базовый BottomSheetFragment не делает ничего, кроме как возвращает BottomSheetDialog .

ОБНОВЛЕНИЕ ДЛЯ ANDROIDX

При использовании AndroidX ресурс, ранее находившийся на android.support.design.R.id.design_bottom_sheet теперь можно найти на com.google.android.material.R.id.design_bottom_sheet .

Как установить состояние фрагмента, расширяющего BottomSheetDialogFragment с помощью BottomSheetBehavior#setState(STATE_EXPANDED) с помощью библиотеки проектирования поддержки Android (v23.2.1)?

https://code.google.com/p/android/issues/detail?id=202396 говорит:

Нижние листы сначала устанавливаются в STATE_COLLAPSED. Вызовите BottomSheetBehavior # setState (STATE_EXPANDED), если вы хотите его расширить. Обратите внимание, что вы не можете вызвать метод перед просмотром макетов.

Предлагаемая практика требует сначала надувать представление, но я не уверен, как я установлю BottomSheetBehaviour на фрагмент ( BottomSheetDialogFragment ).

View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);  
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);  

Все результаты с использованием onShow () вызывают случайную ошибку рендера при отображении программной клавиатуры. Смотрите скриншот ниже - диалоговое окно BottomSheet находится не внизу экрана, а расположено так, как отображалась клавиатура. Эта проблема встречается не всегда, а довольно часто.

ОБНОВИТЬ

Мое решение с отражением частного члена не требуется. Использование postDelayed (около 100 мс) для создания и отображения диалога после скрытия программной клавиатуры - лучшее решение. Тогда вышеуказанные решения с onShow () в порядке.

Utils.hideSoftKeyboard(this);
mView.postDelayed(new Runnable() {
    @Override
    public void run() {
        MyBottomSheetDialog dialog = new MyBottomSheetDialog();
        dialog.setListener(MyActivity.this);
        dialog.show(getSupportFragmentManager(), TAG_BOTTOM_SHEET_DLG);
    }
}, 100);

Поэтому я реализую другое решение, но оно требует использования отражения, потому что BottomSheetDialog имеет все члены как частные. Но это решает ошибку рендера. Класс BottomSheetDialogFragment является только AppCompatDialogFragment с методом onCreateDialog, который создает BottomSheetDialog. Я создаю собственный дочерний элемент AppCompatDialogFragment, который создает мой класс, расширяет BottomSheetDialog и который разрешает доступ к закрытому элементу поведения, и устанавливает его в методе onStart в состояние STATE_EXPANDED.

public class ExpandedBottomSheetDialog extends BottomSheetDialog {

    protected BottomSheetBehavior<FrameLayout> mBehavior;

    public ExpandedBottomSheetDialog(@NonNull Context context, @StyleRes int theme) {
        super(context, theme);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            Field privateField = BottomSheetDialog.class.getDeclaredField("mBehavior");
            privateField.setAccessible(true);
            mBehavior = (BottomSheetBehavior<FrameLayout>) privateField.get(this);
        } catch (NoSuchFieldException e) {
            // do nothing
        } catch (IllegalAccessException e) {
            // do nothing
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (mBehavior != null) {
            mBehavior.setSkipCollapsed(true);
            mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        }
    }
}


public class AddAttachmentBottomSheetDialog extends AppCompatDialogFragment {

    ....

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new ExpandedBottomSheetDialog(getContext(), getTheme());
    }

    ....
}

Ответ efeturi отличный, однако, если вы хотите использовать onCreateView () для создания своего BottomSheet, а не использовать onCreateDialog () , вот код, который вам нужно будет добавить в метод onCreateView () :

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            BottomSheetDialog d = (BottomSheetDialog) dialog;
            View bottomSheetInternal = d.findViewById(android.support.design.R.id.design_bottom_sheet);
            BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
        }
    });
    return inflater.inflate(R.layout.your_bottomsheet_content_layout, container, false);
}

Применение состояния BottomsheetDialogFragment в OnResume решит эту проблему

    @Override
    public void onResume() {
        super.onResume();
        if(mBehavior!=null)
           mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    }

onShow (диалог DialogInterface) и postDelayed могут вызвать сбой анимации


Я думаю, что выше, тем лучше. К сожалению, я не нашел эти решения, прежде чем я решил. Но напиши мое решение. довольно похоже на все.

================================================== ================================

Я сталкиваюсь с той же проблемой. Это то, что я решил. Поведение скрыто в BottomSheetDialog, который доступен для определения поведения. Если вы не хотите менять свой родительский макет на CooridateLayout, вы можете попробовать это.

ШАГ 1: настроить BottomSheetDialogFragment

open class CBottomSheetDialogFragment : BottomSheetDialogFragment() {
   //wanna get the bottomSheetDialog
   protected lateinit var dialog : BottomSheetDialog 
   override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
      dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
      return dialog
   }

   //set the behavior here
   fun setFullScreen(){
      dialog.behavior.state = STATE_EXPANDED
   }
}

ШАГ 2: заставьте свой фрагмент расширить этот фрагмент

class YourBottomSheetFragment : CBottomSheetDialogFragment(){

   //make sure invoke this method after view is built
   //such as after OnActivityCreated(savedInstanceState: Bundle?)
   override fun onStart() {
      super.onStart()
      setFullScreen()//initiated at onActivityCreated(), onStart()
   }
}

Я написал подкласс BottomSheetDialogFragment для обработки этого:

public class NonCollapsableBottomSheetDialogFragment extends BottomSheetDialogFragment {

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    final BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);

    bottomSheetDialog.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            FrameLayout bottomSheet = bottomSheetDialog.findViewById(android.support.design.R.id.design_bottom_sheet);

            BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
            behavior.setSkipCollapsed(true);
            behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        }
    });
    return bottomSheetDialog;
}

}

Поэтому расширьте этот класс вместо BottomSheetDialogFragment чтобы создать свой собственный нижний лист.

Измените com.google.android.material.R.id.design_bottom_sheet на android.support.design.R.id.design_bottom_sheet если в вашем проекте используются старые библиотеки поддержки Android.





android-support-design