<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Android Developer</title><subtitle>Мои личные заметки и решения для тех или иных задач на Android/Java</subtitle><author><name>Android Developer</name></author><id>https://teletype.in/atom/android_developer</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/android_developer?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@android_developer?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=android_developer"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/android_developer?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-21T13:21:02.739Z</updated><entry><id>android_developer:8K9QCkH1Nrr</id><link rel="alternate" type="text/html" href="https://teletype.in/@android_developer/8K9QCkH1Nrr?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=android_developer"></link><title>Эффективная работа с BottomSheet</title><published>2021-11-03T18:41:41.532Z</published><updated>2021-11-03T18:41:41.532Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img2.teletype.in/files/56/ce/56cec900-59d0-4e0c-a1e5-68833c5402e6.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://lh3.googleusercontent.com/yCWRSDd6LjJJYovpQ-8ixmJnHa56UXWxlVEkHskpypfmo4XW2a0EczckNLbUVs--IAh8NLLsgfPxZUsHZuFMvyYclZ_QXuoFuQnN=w1064-v0&quot;&gt;В данной заметке пойдёт речь об организации эффективной работы с BottomSheet  компонентами на уровне Activity. </summary><content type="html">
  &lt;p id=&quot;P3oA&quot;&gt;В данной заметке пойдёт речь об организации эффективной работы с &lt;code&gt;BottomSheet &lt;/code&gt; компонентами на уровне &lt;code&gt;Activity&lt;/code&gt;. &lt;/p&gt;
  &lt;p id=&quot;dvWO&quot;&gt;Заметка представляет собой квинтэссенцию личного опыта, боли и пройденных шагов для поиска наиболее эффективного решения различных задач. &lt;/p&gt;
  &lt;h2 id=&quot;cJph&quot;&gt;Sheets: Bottom&lt;/h2&gt;
  &lt;p id=&quot;1X03&quot;&gt;Согласно Material Design, &lt;code&gt;BottomSheet&lt;/code&gt; представляет собой компоненты с дополнительным контентом, привязанные к нижней части экрана.&lt;/p&gt;
  &lt;figure id=&quot;6NKc&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://lh3.googleusercontent.com/yCWRSDd6LjJJYovpQ-8ixmJnHa56UXWxlVEkHskpypfmo4XW2a0EczckNLbUVs--IAh8NLLsgfPxZUsHZuFMvyYclZ_QXuoFuQnN=w1064-v0&quot; width=&quot;1064&quot; /&gt;
    &lt;figcaption&gt;Источник: https://material.io/components/sheets-bottom&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;viW3&quot;&gt;В общем случае работа с &lt;code&gt;BottomSheet&lt;/code&gt; не представляет собой ничего сложного. Этой теме посвящено огромное количество статей. Ознакомиться с тем, как подключить и использовать данные компоненты, вы можете, например, &lt;a href=&quot;https://habr.com/ru/post/309200/&quot; target=&quot;_blank&quot;&gt;тут&lt;/a&gt;. &lt;/p&gt;
  &lt;h2 id=&quot;azJo&quot;&gt;Проблема&lt;/h2&gt;
  &lt;p id=&quot;HSJH&quot;&gt;Во время работы над проектом передо мной возникли следующие вопросы:&lt;/p&gt;
  &lt;ul id=&quot;1AGG&quot;&gt;
    &lt;li id=&quot;M942&quot;&gt;Как эффективно организовать работу с различными &lt;code&gt;BottomSheet&lt;/code&gt; фрагментами для всех &lt;code&gt;Activity&lt;/code&gt; проекта;&lt;/li&gt;
    &lt;li id=&quot;Qr90&quot;&gt;Инкапсулировать шаблонный код работы с &lt;code&gt;BottomSheet&lt;/code&gt; в одном месте;&lt;/li&gt;
    &lt;li id=&quot;nJID&quot;&gt;Упростить отслеживание состояний &lt;code&gt;BottomSheet&lt;/code&gt;.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;u8KK&quot;&gt;Это является проблемой, когда имеется множество &lt;code&gt;Activity&lt;/code&gt;, которые должны одинаково работать с компонентами &lt;code&gt;BottomSheet&lt;/code&gt;, обрабатывать различные их состояния, реагировать на нажатие кнопки Back, показывать/скрывать дополнительный контент, иметь некоторое начальное состояние для всех &lt;code&gt;BottomSheet&lt;/code&gt;, объявленных в &lt;code&gt;Activity&lt;/code&gt;.&lt;/p&gt;
  &lt;h2 id=&quot;gzrG&quot;&gt;BottomSheetActivity&lt;/h2&gt;
  &lt;p id=&quot;yTpO&quot;&gt;Первым делом было принято решение наследовать все &lt;code&gt;Activity&lt;/code&gt;, которые будут иметь &lt;code&gt;BottomSheetBehaviour&lt;/code&gt;, от специального класса, который инкапсулирует весь обслуживающий код для &lt;code&gt;BottomSheet&lt;/code&gt; в себе.&lt;/p&gt;
  &lt;pre id=&quot;noDI&quot; data-lang=&quot;java&quot;&gt;public abstract class BottomSheetActivity 
    extends NavigateActivity implements Dependence, BottomSheet {
     
    private BottomSheetBehavior bottomSheetBehavior;
    //Активный, открытый в текущий момент bottomSheet fragment
    private Fragment activeFragment;
    //Список bottomSheet fragments, которые должны быть заблокироаны для смахивания жестом
    private HashMap&amp;lt;Integer, Boolean&amp;gt; lockedViewsForDragAndDrop;
}&lt;/pre&gt;
  &lt;p id=&quot;FoLr&quot;&gt;Класс &lt;code&gt;BottomSheetActivity&lt;/code&gt; является базовым для &lt;code&gt;Activity&lt;/code&gt;, который содержит в &lt;code&gt;BottomSheet&lt;/code&gt; компоненты.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;RADv&quot;&gt;Пояснения extends классов и интерфейсов:&lt;/p&gt;
    &lt;p id=&quot;OC7v&quot;&gt;NavigateActivity - класс, инкапсулирующий навигационный код для всех Activity и некоторые общие для всех Activity компоненты.&lt;/p&gt;
    &lt;p id=&quot;2sMm&quot;&gt;Dependence - интерфейс для работы с подписками/отписками на события различных компонентов.&lt;/p&gt;
    &lt;p id=&quot;ypdX&quot;&gt;BottomSheet - интерфейс с методами регистрации BottomSheet фрагментов.&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;slM6&quot;&gt;Интерфейс &lt;code&gt;Dependence&lt;/code&gt; обязывает класс реализовать следующие методы:&lt;/p&gt;
  &lt;pre id=&quot;Zlko&quot; data-lang=&quot;java&quot;&gt;    @Override @CallSuper
    public void createDependencies() {
        bottomSheetBehavior.addBottomSheetCallback(onBottomSheetCallback);
        registerFragments();
    }

    @Override @CallSuper
    public void deleteDependencies() {
        bottomSheetBehavior.removeBottomSheetCallback(onBottomSheetCallback);
    }&lt;/pre&gt;
  &lt;p id=&quot;zCYg&quot;&gt;&lt;code&gt;onBottomSheetCallback&lt;/code&gt; является реализацией &lt;code&gt;BottomSheetBehavior.BottomSheetCallback()&lt;/code&gt; и выполняет некоторые действия по отображению/сокрытию, а также работе с swipe по &lt;code&gt;BottomSheet&lt;/code&gt; фрагменту. Реализация &lt;code&gt;onBottomSheetCallback&lt;/code&gt; приведена ниже.&lt;/p&gt;
  &lt;pre id=&quot;X4QG&quot; data-lang=&quot;java&quot;&gt;    protected final BottomSheetBehavior.BottomSheetCallback onBottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View view, int i) {
            switch (i) {
                case BottomSheetBehavior.STATE_COLLAPSED:
                case BottomSheetBehavior.STATE_HIDDEN:
                    hideFragment(activeFragment);
                    break;
                case BottomSheetBehavior.STATE_EXPANDED:
                    break;
                case BottomSheetBehavior.STATE_DRAGGING:
                    Boolean value = lockedViewsForDragAndDrop.get(view.getId());
                    if (value != null &amp;amp;&amp;amp; value) {
                        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                    }
                    break;
                case BottomSheetBehavior.STATE_SETTLING:
                    break;
            }
        }&lt;/pre&gt;
  &lt;p id=&quot;ANtK&quot;&gt;Чтобы в момент загрузки &lt;code&gt;Activity&lt;/code&gt;, &lt;code&gt;BottomSheet&lt;/code&gt; компонент был скрыт и не отображался на экране, в методе &lt;code&gt;onCreate у Activity&lt;/code&gt;, которая будет наследовать данный класс, вызывается метод &lt;code&gt;hideBottomSheetView&lt;/code&gt;, которому передается &lt;code&gt;View&lt;/code&gt; с &lt;code&gt;BottomSheetBehavior&lt;/code&gt;.&lt;/p&gt;
  &lt;pre id=&quot;uF1U&quot; data-lang=&quot;java&quot;&gt;    protected void hideBottomSheetView(View bottomSheetView) {
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetView);
        bottomSheetBehavior.setHideable(true);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
    }&lt;/pre&gt;
  &lt;p id=&quot;zu0H&quot;&gt;Главная и единственная задача этого метода - спрятать &lt;code&gt;bottomSheetView&lt;/code&gt;. Если их несколько, этот метод вызывается для каждого &lt;code&gt;bottomSheetView&lt;/code&gt;.&lt;/p&gt;
  &lt;h2 id=&quot;zNOL&quot;&gt;Регистрация фрагментов в FragmentManager&lt;/h2&gt;
  &lt;p id=&quot;75ix&quot;&gt;Используемые в &lt;code&gt;Activity&lt;/code&gt; фрагменты необходимо зарегистрировать в &lt;code&gt;FragmentManager&lt;/code&gt; для их скрытия и отображения. Интерфейс &lt;code&gt;BottomSheet&lt;/code&gt;, который упоминался выше, обязывает &lt;code&gt;Activity&lt;/code&gt; реализовать метод &lt;code&gt;registerFragments&lt;/code&gt;. Реализация метода приведена ниже.&lt;/p&gt;
  &lt;pre id=&quot;7W45&quot; data-lang=&quot;java&quot;&gt;@Override
    public void registerFragments() {
        fragment = new ImplFragment();

        addFragmentToFragmentManager(binder.activityFragment.getRoot(), fragment, false);
    }&lt;/pre&gt;
  &lt;p id=&quot;oQ7Y&quot;&gt;Метод &lt;code&gt;addFragmentToFragmentManager&lt;/code&gt; реализован в классе &lt;code&gt;BottomSheetActivity&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;5abf&quot; data-lang=&quot;java&quot;&gt;    protected void addFragmentToFragmentManager(View rootView, Fragment fragment, boolean isLockedForDragAndDrop) {
        getSupportFragmentManager().beginTransaction()
                .add(rootView.getId(), fragment)
                .hide(fragment)
                .commit();

        lockedViewsForDragAndDrop.put(rootView.getId(), isLockedForDragAndDrop);
    }&lt;/pre&gt;
  &lt;p id=&quot;a5oq&quot;&gt;&lt;code&gt;HashMap&amp;lt;Integer, Boolean&amp;gt; lockedViewsForDragAndDrop&lt;/code&gt; выполняет функцию регистрации фрагментов, которым разрешены/запрещены операции &lt;code&gt;swipe&lt;/code&gt;.&lt;/p&gt;
  &lt;h2 id=&quot;XfG0&quot;&gt;Сокрытие и отображение BottomSheet фрагментов&lt;/h2&gt;
  &lt;p id=&quot;8O7W&quot;&gt;Для управления отображением &lt;code&gt;BottomSheet&lt;/code&gt; фрагментов в &lt;code&gt;BottomSheetActivity&lt;/code&gt; имеется вспомогательный метод &lt;code&gt;showHideFragment&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;H682&quot;&gt;Входными параметрами являются &lt;code&gt;Fragment&lt;/code&gt; и &lt;code&gt;View&lt;/code&gt;, которые требуется показать или скрыть. Решение о том, что требуется сделать, принимается внутри.&lt;/p&gt;
  &lt;pre id=&quot;Eugi&quot; data-lang=&quot;java&quot;&gt;    protected void showHideFragment(Fragment target, View view) {
        if (bottomSheetBehavior.getState() != BottomSheetBehavior.STATE_HIDDEN) {
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
        } else {
            showFragment(target, view);
        }
    }&lt;/pre&gt;
  &lt;p id=&quot;Ewhi&quot;&gt;Если &lt;code&gt;Fragment target (и его view)&lt;/code&gt; открыт в данный момент, его необходимо закрыть. Если закрыт - отобразить.&lt;/p&gt;
  &lt;p id=&quot;0mFE&quot;&gt;Реализация метода &lt;code&gt;showFragment&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;8cpm&quot; data-lang=&quot;java&quot;&gt;    private void showFragment(Fragment target, View view) {
        getSupportFragmentManager().beginTransaction()
                .show(target)
                .commit();

        bottomSheetBehavior = BottomSheetBehavior.from(view);
        bottomSheetBehavior.setHideable(true);
        bottomSheetBehavior.setSkipCollapsed(true);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        activeFragment = target;

        //Хак для решения проблем изменяющегося размера контента внутри bottomSheetBehavior (например listView загружает данные).
        activeFragment.getView().getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
        activeFragment.getView().getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
    }&lt;/pre&gt;
  &lt;p id=&quot;uE0P&quot;&gt;Метод &lt;code&gt;hideFragment&lt;/code&gt;, который вызывается при событии &lt;code&gt;onBottomSheetCallback.onStateChanged - BottomSheetBehavior.STATE_HIDDEN&lt;/code&gt;, которое описано выше.&lt;/p&gt;
  &lt;pre id=&quot;wzeS&quot; data-lang=&quot;java&quot;&gt;    private void hideFragment(Fragment target) {
        getSupportFragmentManager().beginTransaction()
                .hide(activeFragment)
                .commit();

        if (activeFragment == target) { activeFragment = null; }
    }&lt;/pre&gt;
  &lt;h3 id=&quot;qOMr&quot;&gt;Решение проблемы для случая, когда BottomSheet имеет динамический размер (данные)&lt;/h3&gt;
  &lt;p id=&quot;BQ7r&quot;&gt;Вы могли заметить выше комментарий, указывающий на решение данной проблемы. Она состоит в следующем:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;iHp4&quot;&gt;В момент вызова onCreateView у Fragment, он может изменить размер (требование данных), что приведет к тому, что Fragment не будет полностью развернут на экране.&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;2bTb&quot;&gt;Решение состоит в дополнительной установке высоты &lt;code&gt;Fragment&lt;/code&gt;. Эту задачу решает &lt;code&gt;onGlobalLayoutListener&lt;/code&gt;, на который &lt;code&gt;Fragment&lt;/code&gt; подписывается в момент вызова &lt;code&gt;showFragment&lt;/code&gt;, исполняется и затем сразу же отписывается от него.&lt;/p&gt;
  &lt;pre id=&quot;kk1G&quot; data-lang=&quot;java&quot;&gt;    private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if(activeFragment == null || activeFragment.getView() == null) {
                return;
            }
            int h = activeFragment.getView().getHeight();
            bottomSheetBehavior.setPeekHeight(h);
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            activeFragment.getView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    };&lt;/pre&gt;
  &lt;p id=&quot;YIi0&quot;&gt;Обработка закрытия &lt;code&gt;BottomSheet Fragment&lt;/code&gt; при событии &lt;code&gt;Back&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;lCdM&quot;&gt;Когда пользователь нажимает кнопку &lt;code&gt;Back&lt;/code&gt;, и &lt;code&gt;BottomSheet Fragment&lt;/code&gt; открыт, он будет закрыт, при этом событие &lt;code&gt;Back&lt;/code&gt; не должно привести к выходу из экрана. Событие &lt;code&gt;Back&lt;/code&gt; проверяет, открыт ли &lt;code&gt;Fragment&lt;/code&gt; (если открыт, закрывает его) и если &lt;code&gt;Fragment&lt;/code&gt; не открыт, то позволяет уйти из &lt;code&gt;Activity&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;7hig&quot;&gt;Метод &lt;code&gt;backClickHideBottomSheetView&lt;/code&gt;, определенный в &lt;code&gt;BottomSheetActivity&lt;/code&gt; и вызываемый по &lt;code&gt;callback onBackPressed&lt;/code&gt;, выполняет эту функцию.&lt;/p&gt;
  &lt;pre id=&quot;Ko3s&quot; data-lang=&quot;java&quot;&gt;    protected boolean backClickHideBottomSheetView() {
        if(bottomSheetBehavior.getState() != BottomSheetBehavior.STATE_HIDDEN) {
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
            return true;
        }

        return false;
    }&lt;/pre&gt;
  &lt;p id=&quot;CnBh&quot;&gt;Вызов метода &lt;code&gt;backClickHideBottomSheetView&lt;/code&gt; в &lt;code&gt;onBackPressed Activity&lt;/code&gt;.&lt;/p&gt;
  &lt;pre id=&quot;suVk&quot; data-lang=&quot;java&quot;&gt;   @Override
    public void onBackPressed() {
        if(backClickHideBottomSheetView()) return;

        getNavigationManager().back(this);
    }&lt;/pre&gt;
  &lt;h2 id=&quot;sYTO&quot;&gt;Заключение&lt;/h2&gt;
  &lt;p id=&quot;B2tc&quot;&gt;Реализация класса BottomSheetActivity и инкапсуляция логики работы с BottomSheetBehavior и множеством фрагментов позволила переместить шаблонный код в одно место и использовать его на множестве Activity. &lt;/p&gt;
  &lt;p id=&quot;qwmU&quot;&gt;При дальнейшем усложнении логики работы с BottomSheet фрагментами необходимо модифицировать только этот класс.&lt;/p&gt;
  &lt;p id=&quot;n2SK&quot;&gt;В Activity, которая будет наследоваться от BottomSheetActivity, требуется только несколько действий:&lt;/p&gt;
  &lt;ul id=&quot;SBUc&quot;&gt;
    &lt;li id=&quot;GDwo&quot;&gt;Первичное сокрытие BottomSheetView&amp;#x27;s, которые присутствуют на Activity;&lt;/li&gt;
    &lt;li id=&quot;1Muq&quot;&gt;Реализация метода registerFragments для регистрации фрагментов в FragmentManager;&lt;/li&gt;
    &lt;li id=&quot;BeCY&quot;&gt;Проверка необходимости закрыть BottomSheet фрагмент перед выходом с Activity.&lt;/li&gt;
    &lt;li id=&quot;kL06&quot;&gt;Вызов метода showHideFragment, когда требуется отобразить или скрыть Fragment.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;X7e3&quot;&gt;Полный код класса BottomSheetActivity приведён ниже. &lt;/p&gt;
  &lt;p id=&quot;eEsy&quot;&gt;Спасибо, что прочли заметку.&lt;/p&gt;
  &lt;pre id=&quot;PObu&quot; data-lang=&quot;java&quot;&gt;public abstract class BottomSheetActivity extends NavigateActivity implements Dependence, BottomSheet {

    private BottomSheetBehavior bottomSheetBehavior;
    private Fragment activeFragment;
    private HashMap&amp;lt;Integer, Boolean&amp;gt; lockedViewsForDragAndDrop;

    public BottomSheetActivity() {
        lockedViewsForDragAndDrop = new HashMap&amp;lt;&amp;gt;();
    }

    @Override @CallSuper
    public void createDependencies() {
        bottomSheetBehavior.addBottomSheetCallback(onBottomSheetCallback);
        registerFragments();
    }

    @Override @CallSuper
    public void deleteDependencies() {
        bottomSheetBehavior.removeBottomSheetCallback(onBottomSheetCallback);
    }

    protected void hideBottomSheetView(View bottomSheetView) {
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetView);
        bottomSheetBehavior.setHideable(true);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
    }

    protected void addFragmentToFragmentManager(View rootView, Fragment fragment, boolean isLockedForDragAndDrop) {
        getSupportFragmentManager().beginTransaction()
                .add(rootView.getId(), fragment)
                .hide(fragment)
                .commit();

        lockedViewsForDragAndDrop.put(rootView.getId(), isLockedForDragAndDrop);
    }

    protected void showHideFragment(Fragment target, View view) {
        if (bottomSheetBehavior.getState() != BottomSheetBehavior.STATE_HIDDEN) {
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
        } else {
            showFragment(target, view);
        }
    }

    protected boolean backClickHideBottomSheetView() {
        if(bottomSheetBehavior.getState() != BottomSheetBehavior.STATE_HIDDEN) {
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
            return true;
        }

        return false;
    }

    protected final BottomSheetBehavior.BottomSheetCallback onBottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View view, int i) {
            switch (i) {
                case BottomSheetBehavior.STATE_COLLAPSED:
                case BottomSheetBehavior.STATE_HIDDEN:
                    hideFragment(activeFragment);
                    break;
                case BottomSheetBehavior.STATE_EXPANDED:
                    break;
                case BottomSheetBehavior.STATE_DRAGGING:
                    Boolean value = lockedViewsForDragAndDrop.get(view.getId());
                    if (value != null &amp;amp;&amp;amp; value) {
                        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                    }
                    break;
                case BottomSheetBehavior.STATE_SETTLING:
                    break;
            }
        }

        @Override
        public void onSlide(@NonNull View view, float v) {

        }
    };

    private void hideFragment(Fragment target) {
        getSupportFragmentManager().beginTransaction()
                .hide(activeFragment)
                .commit();

        if (activeFragment == target) { activeFragment = null; }
    }

    private void showFragment(Fragment target, View view) {
        getSupportFragmentManager().beginTransaction()
                .show(target)
                .commit();

        bottomSheetBehavior = BottomSheetBehavior.from(view);
        bottomSheetBehavior.setHideable(true);
        bottomSheetBehavior.setSkipCollapsed(true);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        activeFragment = target;

        //Хак для решения проблем изменяющегося размера контента внутри bottomSheetBehavior (например listView загружает данные).
        activeFragment.getView().getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
        activeFragment.getView().getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
    }

    private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if(activeFragment == null || activeFragment.getView() == null) {
                return;
           }
            int h = activeFragment.getView().getHeight();
            bottomSheetBehavior.setPeekHeight(h);
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            activeFragment.getView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    };
}&lt;/pre&gt;

</content></entry></feed>