ScrollingAnimation works in PREVIEW but broken in BUILD on iOS

Fuse 0.25.0 (build 7511)
Uno 0.35.6 (build 3582) OS X 10.11 i386 a76249a

<ScrollingAnimation From="{startShift}" To="{endShift}">
     <Move Target="fixedYearHeader" Y="-1" RelativeTo="Size" RelativeNode="yearHeader"/>
</ScrollingAnimation>

I have posted a project on Dropbox Veckoappen_toDucker.zip and I think the issue should be visible there. I have used ScrollingAnimation to create a section header effect similar to what you get on native iOS. It works flawlessly in preview, but nothing happens in a build on iOS.

Just a hunch, does it work better if you replace the databound parameters to ScrollingAnimation with fixed values?

I tried your suggestion. Appears to be a scoping issue in builds that don’t show up in preview. Below is the relevant code. In preview the fixedYearHeader StackPanel is moved in the expected way, but on builds it moves the parent panel instead. So perhaps it is a bug in preview that allowed be to do it in the first place? But normally you would get an error if you try to target something that isn’t available.

<Panel ClipToBounds="true" Height="30" Alignment="Top">
                <StackPanel ux:Name="fixedYearHeader">
                    <Each Items="{listData}">

                        <Deferred>

                            <Match Value="{type}">
                                <Case String="month">
                                
                                    <Panel ux:Name="yearHeader" Height="30" HitTestMode="LocalBoundsAndChildren">
                                        <Text Color="#fff" Value="{year_nr}" Alignment="CenterLeft" Margin="10,5,10,0" />
                                        <Text Color="#fff" Value="{month_label}" Alignment="CenterLeft" Margin="50,5,10,0" />
                                        <Rectangle Color="#ddd" Height="1" Alignment="Bottom" Opacity="0.95" />
                                        <Rectangle Color="#aaa" Height="100%" Alignment="Bottom" Opacity="0.95" />
                                    </Panel>
                                    
                                </Case>
                            </Match>

                        </Deferred>

                    </Each>
                </StackPanel>
            </Panel>

            
            <ScrollView ux:Name="view">

                <ScrollViewMotion GotoDuration="1" GotoType="Elastic" />

                <StackPanel Color="#ddd" ItemSpacing="1">
                
                    <Each Items="{listData}">

                        <Panel>

                            <Match Value="{type}">
                                <Case String="month">
                                    <Panel ux:Name="yearHeader" Color="#aaa" Height="30">
                                        <Text Color="#fff" Value="{year_nr}" Alignment="CenterLeft"  Margin="10,5,10,0" />
                                        <Text Color="#fff" Value="{month_label}" Alignment="CenterLeft" Margin="50,5,10,0" />
                                        <ScrollingAnimation From="500" To="530">
                                            <Move Target="fixedYearHeader" Y="-1" RelativeTo="Size" RelativeNode="yearHeader"/>
                                        </ScrollingAnimation>
                                    </Panel>
                                </Case>

Nothing is moved when changing back to using Observables instead of fixed values so perhaps it is both a scoping issue and and issue with binding to Observables.

I am having issues uploading images in the editor, but I have screenshots.

Hmm, yeah.

You are refering to yearHeader inside an Each from within another Each. What object this resolves to is clearly ambiguous. The UX compiler should have given an error message.

Preview has a more pragmatic name resolving so you probably just got lucky, it is relying on the UX compiler giving error messages at an earlier stage.

The way to solve cases like this is just to use a single Each, and use AlternateRoot to inject pieces of UI elsewhere in the tree. This allows all objects that need to know about each other to be inside the same Each-scope.

I’m making an internal issue to look into why the UX compiler didn’t give an error message (as it should).

Thanks for reporting!

Just for the record. The target of the move is fixedYearHeader not yearHeader

Yeah but you are still saying RelativeNode="yearHeader". You probably just got lucky because they are all the same size, and preview just gave you a random one.

Aha, I thought that was taken care of by closest having precedence.

Pro tip: Instead of

<Each Items="{listData}">
	<Deferred>
		<Match Value="{type}">
			<Case String="month">
				<Panel ...

Do

<Each Items="{listData}" MatchKey="type">
	<Deferred ux:Template="month">
		<Panel ...

:slight_smile:

Less code, and avoids instantiating all the templates you won’t use.

Great! The .ux file is getting a bit bloated…

I’ve got AlternateRoot working in Preview, but still not in build. Trying to narrow down on the issue, but having to compile each time makes progress slow ofc.

I have spent six hours trying lots of different variations using AlternateRoot without any success. When I move the elements out of the ScrollView (with AlternateRoot) the ScrollAnimation doesn’t trigger at all.

To me the most intuitive solution would be to keep the ScrollingAnimation declared with the headers in the ScrollView. Then let the Move target the StackPanel, containing a mirror of the headers, which is declared outside the ScrollView (to give them fixed positioning). That way I can move the mirrored headers in concert with the headers in the list achieving a list section header effect. Obviously it requires binding From and To values to predetermined values for each header based on where they will end up in the list.

Again, this works perfectly in Preview, but not in Build. It feels like a bug either in Preview or in Build. But I would prefer if it was the latter, because this is an awesome feature and sticky section headers are used all over in iOS.

Currently the ScrollingAnimation must be kept within the ScrollView to work, it can’t be part of the thing that has an alternate root. This may be something we can fix in an upcoming version.

As for sticky headers, this is one of many ScrollView-related features we are currenlty working on sleeker solutions for. Calculating UI-related properties in JS is never going to be best practice in Fuse.

I’ve updated our internal tickets for this. Thanks for your input.

Awesome! I’ll be watching this closely because I have an app I would like to release at some point this fall which requires this. Will stick to having the feature working in Preview for now.

If one can bind the To/From value to the vertical/horisontal position of each element in ScrollView that triggers the transitions, and target a container outside the ScrollView with the Move, then we are all set :slight_smile: and it could be used for a lot of other cool things too!

On a side note, I almost got this working by keeping the sticky container in the ScrollView and moving it down while scrolling. But it is really hard to stop it from wandering slightly…

For the record, I got sticky headers working by placing the sticky container in the ScrollView in a Panel and then having two animations, in and out of view. It requires knowing the position of each header in the list relative to the top of the list. It works both in Preview and in iOS builds.