Is there a way to make a long_running_task
snap to a row while scrolling?
It seems that applying the known fixes for a views.py
does not suffice for a tasks.py
.
答案 0 :(得分:0)
Note: This code was tested for API 23
Note: ALTER TABLE claim
ADD EXCLUDE ( claim_number WITH =,
line_id WITH IS NOT DISTINCT FROM);
, and ERROR: syntax error at or near "IS"
for my IS NOT DISTINCT FROM
. Couldn't find where this is set, may be default (didn't see it in the style referenced by listPaddingTop == 11
in the below constructor chain (which points to listPaddingBottom == 10
/GridView
in res/values/styles.xml). Need to check source.
Note: Calling Android.Resource.Attribute.GridViewStyle
in constructor has no effect on listPaddingTop (Bottom).
Widget.GridView
Example of exception case noted above
If user scrolls down, from very top, by exactly the padding amount, and Widget.AbsListView
is called with the resulting value calculated below (which is SetPadding(0,0,0,0)
since public class SnapScrollGridView : GridView,
//View.IOnScrollChangeListener
AbsListView.IOnScrollListener
{
private bool _bSnapScroll;
public new int FirstVisiblePosition { get; set; }
// ctor chain
public SnapScrollGridView(Context context) : this(context, null) { }
public SnapScrollGridView(Context context, IAttributeSet attrs) : this(context, attrs, Android.Resource.Attribute.GridViewStyle) { }
public SnapScrollGridView(Context context, IAttributeSet attrs, int defaultStyleAttr) : this(context, attrs, defaultStyleAttr,0) { }
public SnapScrollGridView(Context context, IAttributeSet attrs, int defaultStyleAttr, int defStyleRes) : base(context, attrs, defaultStyleAttr, defStyleRes)
{
_bSnapScroll = false;
FirstVisiblePosition = 0;
//SetOnScrollChangeListener(this);
SetOnScrollListener(this);
// no effect on listPaddingTop (or bottom)
// SetPadding(0, 0, 0, 0);
}
void AbsListView.IOnScrollListener.OnScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// firstVisibleItem and visibleItemCount not accurate
}
protected override void OnOverScrolled(int scrollX, int scrollY, bool clampedX, bool clampedY)
{
// - would be very useful, however is called after OnScrollStateChanged()
// - may be able to refactor OnScrollStateChanged to work in conjuction with this
base.OnOverScrolled(scrollX, scrollY, clampedX, clampedY);
}
void AbsListView.IOnScrollListener.OnScrollStateChanged(AbsListView view, [GeneratedEnum] ScrollState scrollState)
{
switch (scrollState)
{
case ScrollState.TouchScroll:
case ScrollState.Fling:
break;
case ScrollState.Idle:
if (_bSnapScroll)
{
_bSnapScroll = false;
}
else
{
View item = view.GetChildAt(0);
int top = System.Math.Abs(item.Top);
int btm = System.Math.Abs(item.Bottom);
// OVERSCROLL TOP ("topping out")
// - user tried scrolling up (swiping down) past top
if (top == view.ListPaddingTop && view.FirstVisiblePosition == 0)
{
this.FirstVisiblePosition = 0;
return;
}
// OVERSCROLL BOTTOM ("bottoming out")
// - for now, user needs to hit bottom to force snap when last row wont like "normal"
// - this happens for certain GridView height and item/row height combinations
// - could smooth scroll in the same manner as below, but requires more code
// nRows, curRow round down (floor() not needed)
int nRows = view.Count / NumColumns;
int curRow = view.LastVisiblePosition / NumColumns;
if (curRow == nRows)
{
View item2 = view.GetChildAt(view.LastVisiblePosition-view.FirstVisiblePosition);
int top2 = System.Math.Abs(item2.Top);
int btm2 = System.Math.Abs(item2.Bottom);
if (btm2 == view.Height - view.ListPaddingBottom)
{
//view.SetSelection(view.LastVisiblePosition);
this.FirstVisiblePosition = view.LastVisiblePosition;
return;
}
}
// EXCEPTION CASE: smore info below
if (item.Top == 0)
{
view.SetSelection(0);
this.FirstVisiblePosition = 0;
return;
}
_bSnapScroll = true;
// Compensate for ListPaddingTop
// - initially gives a positive offset (11 for me),
// observed when attempting to scroll upward from top
// (swipe downward while at very top)
// (break point will show item.Top = 11)
// - if scrolling down a tiny bit, item.Top lessens,
// eventually becoming zero, then negative after that
int scrollBy = item.Top > 0
? top >= btm ? btm - view.ListPaddingTop : -(view.ListPaddingTop - top)
: top >= btm ? btm - view.ListPaddingTop : -(view.ListPaddingTop + top);
// ALTERNATIVE SYNTAX - debug friendly (less cool)
//int scrollBy = 0;
//if (item.Top > 0)
// scrollBy = top >= btm ? btm - view.ListPaddingTop : -(view.ListPaddingTop - top);
//else
// scrollBy = top >= btm ? btm - view.ListPaddingTop : -(view.ListPaddingTop + top);
if (scrollBy <= 0)
{
this.FirstVisiblePosition = view.FirstVisiblePosition;
}
else
{
this.FirstVisiblePosition = view.FirstVisiblePosition + NumColumns;
}
view.Post(() => { view.SmoothScrollBy(scrollBy, 1000); });
}
break;
default: break;
}
}
), no scrolling occurs for some reason (leaving _bSnapScroll inconsistent since SmoothScrollBy()
subsequently misfires).
-view.ListPaddingTop
Usage
item.Top == 0
Positing grid to bottom after adding a new item (to end)
OnScrollStateChanged()