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

Кнопка плавающего действия не отображается при прокрутке после обновления библиотеки поддержки и дизайна Google

Я пробовал обновлять com.android.support:appcompat и com.android.support:design от: 25.0.1 до 25.1.0 следующим образом:

compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.android.support:design:25.0.1'

в

compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:design:25.1.0'

но я обнаружил, что моя кнопка с плавающим действием больше не появляется при прокрутке активности. Мое поведение FAB определяется следующим образом:

public class MyFabBehavior extends FloatingActionButton.Behavior {

    public MyFabBehavior(Context context, AttributeSet attrs) {
        super();
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
                                       FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {

        // Ensure we react to vertical scrolling
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
                || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);

    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
                               View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {

        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        if (dyConsumed < 0) {
            // User scrolled up -> hide the FAB
            animateFab(child, View.GONE);
        } else if (dyConsumed > 0) {
            // User scrolled down -> show the FAB
            animateFab(child, View.VISIBLE);
        }
    }

    static public void animateFab(FloatingActionButton fab, int visibility) {
        // ignore visibility passed in, and just make fab visible regardless
        if (fab.getVisibility() != View.VISIBLE) {
            fab.show();
        }
    }
}

и мой макет выглядит следующим образом:

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"  >

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/main_scrollview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="8dp" >

        ...

    </android.support.v4.widget.NestedScrollView>

    <android.support.design.widget.FloatingActionButton
        app:layout_behavior="com.example.MyFabBehavior"
        android:id="@+id/fab"
        app:fabSize="normal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_marginBottom="@dimen/fab_margin"
        android:layout_marginRight="@dimen/fab_margin"
        android:onClick="saveButton"
        app:elevation="6dp"
        app:pressedTranslationZ="12dp"
        app:backgroundTint="@color/colorPrimary"
        android:src="@drawable/ic_done_white_24dp" />

</android.support.design.widget.CoordinatorLayout>
4b9b3361

Ответ 1

Обновление из поддержки lib 25.0.1 до 25.1.0 изменяет метод onNestedScroll CoordinatorLayout тем, что вызов пропускается для представлений, чья видимость установлена ​​на View.GONE.

Вызов child.hide() в кнопке с плавающим действием устанавливает видимость вида View.GONE, что означает теперь (начиная с 25.1.0), вызов метода onNestedScroll будет пропущен для кнопки плавающего действия в будущем ( потому что он пропускает все представления, видимость которых GONE).

Обходным путем для этого было бы установить видимость вида INVISIBLE всякий раз, когда вы его скроете. Таким образом, onNestedScroll не будет пропускать представление в следующий раз, когда выполняется вложенная прокрутка.

Чтобы достичь этого, вы можете позвонить

child.hide(new FloatingActionButton.OnVisibilityChangedListener() {
            /**
             * Called when a FloatingActionButton has been hidden
             *
             * @param fab the FloatingActionButton that was hidden.
             */
            @Override
            public void onHidden(FloatingActionButton fab) {
                super.onShown(fab);
                fab.setVisibility(View.INVISIBLE);
            }
        });

в вашем методе onNestedScroll.

Изменить: этот вопрос был отправлен в AOSP Issue Tracker по адресу https://code.google.com/p/android/issues/detail?id=230298

Ответ 2

в CoordinatorLayout 25.1.0 (

   for (int i = 0; i < childCount; i++) {
            final View view = getChildAt(i);
            if (view.getVisibility() == GONE) {
                // If the child is GONE, skip...
                continue;
            }

в 25.0.1

for (int i = 0; i < childCount; i++) {
            final View view = getChildAt(i);
            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
            if (!lp.isNestedScrollAccepted()) {
                continue;
            }

            final Behavior viewBehavior = lp.getBehavior();
            if (viewBehavior != null) {
                viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed,
                        dxUnconsumed, dyUnconsumed);
                accepted = true;

        }

Ответ 3

Поведение изменилось с версии поддержки lib 25.1.0.

Это должно быть RecyclerView (Поведение), которое вызывает изменение видимости FAB.

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

Ниже приведена ссылка на diff, которая показывает изменения, необходимые для выполнения обновления:

https://github.com/chrisbanes/cheesesquare/compare/master...ianhanniballake:scroll_aware_fab