Wednesday, 15 February 2012

c# - Animate (smoothly) ScrollViewer programatically -



c# - Animate (smoothly) ScrollViewer programatically -

is there way smoothly animate scrollviewers vertical offset in windows phone 8.1 runtime?

i have tried using scrollviewer.changeview() method , alter of vertical offset not animated no matter if set disableanimation parameter true or false.

for example: myscrollviewer.changeview(null, myscrollviewer.verticaloffset + p, null, false); offset changed without animation.

i tried using vertical offset mediator:

/// <summary> /// mediator forwards offset property changes on scrollviewer /// instance enable animation of horizontal/verticaloffset. /// </summary> public sealed class scrollvieweroffsetmediator : frameworkelement { /// <summary> /// scrollviewer instance forwards offset changes on to. /// </summary> public scrollviewer scrollviewer { { homecoming (scrollviewer)getvalue(scrollviewerproperty); } set { setvalue(scrollviewerproperty, value); } } public static readonly dependencyproperty scrollviewerproperty = dependencyproperty.register("scrollviewer", typeof(scrollviewer), typeof(scrollvieweroffsetmediator), new propertymetadata(null, onscrollviewerchanged)); private static void onscrollviewerchanged(dependencyobject o, dependencypropertychangedeventargs e) { var mediator = (scrollvieweroffsetmediator)o; var scrollviewer = (scrollviewer)(e.newvalue); if (null != scrollviewer) { scrollviewer.scrolltoverticaloffset(mediator.verticaloffset); } } /// <summary> /// verticaloffset property forwards scrollviewer. /// </summary> public double verticaloffset { { homecoming (double)getvalue(verticaloffsetproperty); } set { setvalue(verticaloffsetproperty, value); } } public static readonly dependencyproperty verticaloffsetproperty = dependencyproperty.register("verticaloffset", typeof(double), typeof(scrollvieweroffsetmediator), new propertymetadata(0.0, onverticaloffsetchanged)); public static void onverticaloffsetchanged(dependencyobject o, dependencypropertychangedeventargs e) { var mediator = (scrollvieweroffsetmediator)o; if (null != mediator.scrollviewer) { mediator.scrollviewer.scrolltoverticaloffset((double)(e.newvalue)); } } /// <summary> /// multiplier scrollableheight property forwards scrollviewer. /// </summary> /// <remarks> /// 0.0 means "scrolled top"; 1.0 means "scrolled bottom". /// </remarks> public double scrollableheightmultiplier { { homecoming (double)getvalue(scrollableheightmultiplierproperty); } set { setvalue(scrollableheightmultiplierproperty, value); } } public static readonly dependencyproperty scrollableheightmultiplierproperty = dependencyproperty.register("scrollableheightmultiplier", typeof(double), typeof(scrollvieweroffsetmediator), new propertymetadata(0.0, onscrollableheightmultiplierchanged)); public static void onscrollableheightmultiplierchanged(dependencyobject o, dependencypropertychangedeventargs e) { var mediator = (scrollvieweroffsetmediator)o; var scrollviewer = mediator.scrollviewer; if (null != scrollviewer) { scrollviewer.scrolltoverticaloffset((double)(e.newvalue) * scrollviewer.scrollableheight); } } }

and can animate verticaloffset property doubleanimation:

storyboard sb = new storyboard(); doubleanimation da = new doubleanimation(); da.enabledependentanimation = true; da.from = mediator.scrollviewer.verticaloffset; da.to = da.from + p; da.duration = new duration(timespan.frommilliseconds(300)); da.easingfunction = new exponentialease() { easingmode = easingmode.easeout }; storyboard.settarget(da, mediator); storyboard.settargetproperty(da, "(mediator.verticaloffset)"); sb.children.add(da); sb.begin();

mediator declared in xaml. animation not smooth on device (lumia 930).

you should stick changeview scrolling animations regardless of whether info virtualization on or not.

without seeing code changeview doesn't work, it's bit hard guess what's going on there couple of things can try.

first approach add together task.delay(1) before calling changeview, give os time finish off other concurrent ui tasks.

await task.delay(1); scrollviewer.changeview(null, scrollviewer.scrollableheight, null, false);

the sec approach bit more complex. i've noticed that, when have many complex items in listview, scrolling animation first item lastly (from changeview method) isn't smooth @ all.

this because listview first needs realize/render many items along way due info virtualization , animated scrolling. not efficient imho.

what came - first, utilize non-animated listview.scrollintoview scroll lastly item realized. then, phone call changeview move offset size of actualheight * 2 of listview animation disabled (you can alter whatever size want based on app's scrolling experience). finally, phone call changeview 1 time again scroll end, animation time. doing give much improve scrolling experience 'cause scrolling distance actualheight of listview.

keep in mind when item want scroll realized on ui, don't want above. calculate distance between item , top of scrollviewer , phone call changeview scroll it.

i wrapped logic above in answer's update 2 section (thanks question realized initial reply doesn't work when virtualization on :p). allow me know how go.

c# windows-runtime winrt-xaml windows-phone-8.1

No comments:

Post a Comment