web-dev-qa-db-ja.com

スクロール時にNestedScrollViewでFABを非表示にする

いくつかのlinearlayoutsやtextviewsのようなコンテンツを含むnestedscrollviewがあります。いくつかの理由で、floatingactionbuttonライブラリも使用しています。そのため、動作を使用することはできません。動作のようにファブを動的に非表示および表示するために、scrollviewからscrollchangelistenerを処理する方法がわかりません。

スクロール中にファブを表示および非表示にする方法についての提案はありますか?

10
user4546546

以下のコードをNestedScrollViewScrollChangeListenerに追加するだけです。

NestedScrollView nsv = v.findViewById(R.id.nsv);
    nsv.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
        @Override
        public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            if (scrollY > oldScrollY) {
                fab.hide();
            } else {
                fab.show();
            }
        }
    });
33
Henrique Monte

FabScrollBehaviorクラスを作成します

public class FabScrollBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
    private int toolbarHeight;

    public FabScrollBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.toolbarHeight = AppUtil.getToolbarHeight(context);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
        return dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
        if (dependency instanceof AppBarLayout) {
            CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
            int fabBottomMargin = lp.bottomMargin;
            int distanceToScroll = fab.getHeight() + fabBottomMargin;
            float ratio = (float)dependency.getY()/(float)toolbarHeight;
            fab.setTranslationY(-distanceToScroll * ratio);
        }
        return true;
    }
}

AppUtil.getToolbarHeight(context)は-

public static int getToolbarHeight(Context context) {
        final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
                new int[]{R.attr.actionBarSize});
        int toolbarHeight = (int) styledAttributes.getDimension(0, 0);
        styledAttributes.recycle();

        return toolbarHeight;
    }

次に、レイアウトでFloatingActionButtonlayout_behaviorに追加します。

   <Android.support.design.widget.FloatingActionButton
        Android:id="@+id/fab_task_accept"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_gravity="end|bottom"
        Android:layout_margin="@dimen/fab_margin"
        Android:src="@drawable/ic_accepted"
        app:layout_behavior="pass.to.your.FabScrollBehavior.Class"
        app:theme="@style/Widget.AppTheme.Fab"/>

全体のレイアウトは次のようになります

<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:animateLayoutChanges="true"
    Android:orientation="vertical">

    <Android.support.design.widget.AppBarLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:theme="@style/Widget.AppTheme.AppBarOverlay">

        <include
            layout="@layout/include_layout_toolbar_scroll"/>

    </Android.support.design.widget.AppBarLayout>


    <include layout="@layout/include_layout_content_with_nestedscroll"/>

    <Android.support.design.widget.FloatingActionButton
        Android:id="@+id/fab_task_accept"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_gravity="end|bottom"
        Android:layout_margin="@dimen/fab_margin"
        Android:src="@drawable/ic_accepted"
        app:layout_behavior="pass.to.FabScrollBehavior.Class"
        app:theme="@style/Widget.AppTheme.Fab"/>


</Android.support.design.widget.CoordinatorLayout>

https://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling(part1)/ から実装

10

アクティビティまたはフラグメントで変数タイプintを定義して、ScrollViewから前のスクロールを設定し、このメソッドを使用してScrollViewクラスのスクロールの変更をリッスンします

 scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {

    // previousScrollY this variable is define in your Activity or Fragment
            if (scrollView.getScrollY() > previousScrollY && floatingActionButton.getVisibility() == View.VISIBLE) {
                floatingActionButton.hide();
            } else if (scrollView.getScrollY() < previousScrollY && floatingActionButton.getVisibility() != View.VISIBLE) {
                floatingActionButton.show();
            }
            previousScrollY = scrollView.getScrollY();
        }
    });

androidのすべてのバージョンで動作します

3
yousef

そのような時間を過ごした後、私はそれに対する解決策を見つけました。それはすべての状況で機能する可能性があります。これはハックですが、適切な解決策ではありませんが、これを適用してこれを機能させることができます。

ご存知のとおり、setOnScrollChangeListenerは最小API23の場合にのみ機能するため、最小APIレベルが23未満の場合はどうなりますか。

そこで、スタックオーバーフローから、getViewTreeObserver().addOnScrollChangedListenerを使用できるソリューションを見つけたので、これはすべてのデバイスと互換性のあるソリューションになります。

次に、「ネストされたスクロールビューのスクロール時にファブボタンを非表示にし、ネストされたスクロールビューが理想的な状態のときにファブボタンを表示する」という問題の最終的な解決策に移りましょう。

そのために、HandlerpostDelayedを使用して、この問題を解決できます。

  1. コンテキスト内の変数を定義する_private int previousScrollY = 0;_

  2. 次に、getViewTreeObserver().addOnScrollChangedListenerを使用してネストされたスクロールビューを次のようにします。

NESTEDSCROLLVIEW.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { new Handler().postDelayed(new Runnable() { @Override public void run() { if (NESTEDSCROLLVIEW.getScrollY() == previousScrollY) { FABBUTTON.setVisibility(View.VISIBLE); } else { FABBUTTON.setVisibility(View.INVISIBLE); } } }, 10); previousScrollY = NESTEDSCROLLVIEW.getScrollY(); } });

  1. これで、準備が整いました。
0
Jay Thummar