Search code examples
androidlistviewxamarin.androidandroid-coordinatorlayoutandroid-nestedscrollview

NestedScrollView not listening while scrolling


I'm building an app with Xamarin.Android and when I'm scrolling the listener is not working, it's just being ignored since nothing happens. Why do I need the NestedScrollView? Because I want to hide or show a floating button on scroll:

NestedScrollView

I have tried to versions:

  1. This one is perfectly working in my other view that doesn't contain any ListView:

    view.FindViewById<NestedScrollView>(Resource.Id.nsvMain).ScrollChange += Nsv_ScrollChange;
    private void Nsv_ScrollChange(object sender, NestedScrollView.ScrollChangeEventArgs e)
    {
        if (e.ScrollY > e.OldScrollX)
        {
            FabIdea.Hide();
        }
        else
        {
            FabIdea.Show();
        }
    }
    
  2. This is my second idea because the previous one didn't work:

    view.FindViewById<NestedScrollView>(Resource.Id.nsvMain).SetOnScrollChangeListener(new NestedScrollViewListener());
    
    public class NestedScrollViewListener : Java.Lang.Object, IOnScrollChangeListener
    {
        public IntPtr Handle { get; set; }
    
        public void Dispose()
        {
    
        }
    
        public void OnScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
        {
            throw new NotImplementedException();
        }
    }
    

This is my XML code:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v4.widget.NestedScrollView
        android:id="@+id/nsvMain"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <EditText
                  android:id="@+id/txtSearch"
                  android:hint="@string/txtSearch"
                  android:layout_height="wrap_content"
                  android:layout_width="match_parent"
                  android:paddingLeft="10dp"
                  android:paddingRight="10dp" />
            <ListView
                android:nestedScrollingEnabled="true"
                android:divider="@null"
                android:dividerHeight="0dp"
                android:layout_margin="8dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/lstRuins" />
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabFilter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@drawable/filter" />
</android.support.design.widget.CoordinatorLayout>

My only guessing is connected to the ListView, but my App is strictly for API 21+ and I already enabled it as android:nestedScrollingEnabled="true". Also, I'm using this from a Fragment.

I triggered the event of scrolling just for testing purposes from the ViewTreeObserver and I noticed that the ScrollY is always 0:

preview


Solution

  • This is my final implementation, I needed to change the logic in a significant way:

    XML:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <android.support.design.widget.TextInputLayout
                android:layout_margin="4dp"
                android:id="@+id/txtSearch_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
              <EditText
                android:drawableStart="@drawable/magnify"
                android:drawableLeft="@drawable/magnify"
                android:id="@+id/txtSearch"
                android:hint="@string/txtSearch"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:paddingLeft="10dp"
                android:drawablePadding="5dp"
                android:paddingRight="10dp" />
            </android.support.design.widget.TextInputLayout>
            <ListView
                android:divider="@null"
                android:dividerHeight="0dp"
                android:layout_margin="8dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/lstRuins" />
        </LinearLayout>
    
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fabFilter"
            android:layout_width="wrap_content"
            android:tint="@android:color/white"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            app:srcCompat="@drawable/filter" />
    </FrameLayout>
    

    I needed to implement a new class that implements: IOnScrollListener

    C#:

    public class AbsListViewListener : Java.Lang.Object, IOnScrollListener
    {
        public MayanListFragment MayanListFragment { get; set; }
        private static int lastItem = 0;
    
        public AbsListViewListener(MayanListFragment mayanListFragment)
        {
            MayanListFragment = mayanListFragment;
        }
    
        public void OnScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
        {
            if (MayanListFragment.FabFilter == null)
                return;
    
            if (lastItem > (firstVisibleItem + visibleItemCount) || firstVisibleItem == 0)
            {
                MayanListFragment.FabFilter.Show();
            }
            else
            {
                MayanListFragment.FabFilter.Hide();
            }
            lastItem = firstVisibleItem + visibleItemCount;
        }
    
        public void OnScrollStateChanged(AbsListView view, [GeneratedEnum] ScrollState scrollState)
        {
    
        }
    }
    
    
    LstRuins.SetOnScrollListener(new AbsListViewListener(this));
    

    And then it generally works.