Hopeless Hopeless - 3 months ago 20
Android Question

Many nested scrolling callbacks are not fired/called?

I'm still fairly new to advanced customization in Android UI. What I'm trying to achieve is create something like a

SwipeRefreshLayout
- This layout is not good as what I want (about how flexibile it is, because we cannot easily change the refreshing indicator which means we seem to have to stick to what it provides - the default loading circle indicator).

Also trying to recreate that kind of layout is good for learning, so I really need to do it myself. The problem here is about nested scrolling callbacks, they are
DispatchNestedScroll
,
OnNestedScrollAccepted
,
OnStartNestedScroll
,
OnStopNestedScroll
, ... They are all not fired/called no matter what I've tried.

Here is a snippet of my code:

public class PullToRefreshLayout : ViewGroup, Android.Support.V4.View.INestedScrollingChild, Android.Support.V4.View.INestedScrollingParent
{
public PullToRefreshLayout(Context context) : this(context, null, 0) {

}
public PullToRefreshLayout(Context context, Android.Util.IAttributeSet attrs) : this(context, attrs, 0)
{
NestedScrollingEnabled = true;
}
public PullToRefreshLayout(Context context, Android.Util.IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
{
nsChildHelper = new NestedScrollingChildHelper(this);
nsParentHelper = new NestedScrollingParentHelper(this);
NestedScrollingEnabled = true;
}
NestedScrollingChildHelper nsChildHelper;
NestedScrollingParentHelper nsParentHelper;
protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
{
if (ChildCount > 0)
{
var content = GetChildAt(0);
content.Layout(left, top, right, bottom);
}
}
public override bool NestedScrollingEnabled
{
get
{
//return base.NestedScrollingEnabled;
return nsChildHelper.NestedScrollingEnabled;
}

set
{
nsChildHelper.NestedScrollingEnabled = value;
}
}
//Here are just some included callbacks which are never called
public override void OnNestedScrollAccepted(View child, View target, [GeneratedEnum] ScrollAxis axes)
{
base.OnNestedScrollAccepted(child, target, axes);
}
public override void OnNestedPreScroll(View target, int dx, int dy, int[] consumed)
{
base.OnNestedPreScroll(target, dx, dy, consumed);
}
public override void OnNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)
{
base.OnNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
}
//and more ...
}


The custom view wraps a simple
ListView
(like as how we use the
SwipeRefreshLayout
), something like this:

<CustomViews.PullToRefreshLayout
android:id="@+id/refreshLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="@+id/listView1"/>
</CustomViews.PullToRefreshLayout>


So I expect that when scrolling the ListView back and forth, at least some of the nested scrolling callbacks should be fired, but none of them.

Before I can fulfil the feature of my own pull-to-refresh layout, I need to make some appropriate callbacks be triggered at the right moment.

I hope someone here can figure out what's wrong or simply give me some possible suggestions to solve the problem with your experience. Finally the code is run against a Visual Studio Emulator running Android 6.0 (I believe the problem is still present on lower versions of Android).

Thank you for your help!

Answer

ListView does not support nested scroll, since ListView does not implement NestedScrollingChild. So nested scrolling callbacks will never be fired/called.

I recommend you to use RecyclerView, NestedScrollView or other views that implements NestedScrollingChild instead of ListView

NOTE:

SwipeRefreshLayout supports ListView by implements onTouchEvent , not by nested scroll. Here is source code