Support
Quality
Security
License
Reuse
kandi has reviewed spruce-android and discovered the below as its top functions. This is intended to give you an instant insight into spruce-android implemented functionality, and help decide if they suit your requirements.
NORMAL_MODE: This mode should be used when you have view groups like Constraint/Frame/Relative/Linear Layouts. We feed a list of ids to be excluded to the SpruceBuilder.
R_L_MODE: This mode is used when we have ListView/RecyclerView. The only difference with the first mode is that we pass in the positions to be excluded instead of Ids.
Gradle
repositories {
maven {
url "https://dl.bintray.com/bfears/maven"
}
}
Basic Usage
Animator spruceAnimator = new Spruce
.SpruceBuilder(parentViewGroup)
.sortWith(new Default(/*interObjectDelay=*/50L))
.animateWith(new Animator[] {DefaultAnimations.shrinkAnimator(parentViewGroup, /*duration=*/800)})
.start();
Running the Animation
Animator spruceAnimator = new Spruce
.SpruceBuilder(parentViewGroup)
.sortWith(new DefaultSort(/*interObjectDelay=*/50L))
.animateWith(animators)
.start();
Using a SortFunction
LinearSort sort = new LinearSort(/*interObjectDelay=*/100L, /*reversed=*/false, LinearSort.Direction.TOP_TO_BOTTOM);
The SortFunction Interface
public abstract class SortFunction {
public abstract List<SpruceTimedView> getViewListWithTimeOffsets(ViewGroup parent, List<View> children);
}
View Exclusion Feature
Animator spruceAnimator = new Spruce
.SpruceBuilder(parentViewGroup)
.sortWith(new LinearSort(/*interObjectDelay=*/100L, /*reversed=*/false, LinearSort.Direction.TOP_TO_BOTTOM))
.excludeViews(getExcludedViewIds(), NORMAL_MODE)
//or
.excludeViews(getExcludedViewPosition(), R_L_MODE)
.start();
Sort Function Interpolators
Animator spruceAnimator = new Spruce
.SpruceBuilder(parentViewGroup)
.sortWith(new LinearSort(/*interObjectDelay=*/100L, /*reversed=*/false, LinearSort.Direction.TOP_TO_BOTTOM))
.addInterpolator(new LinearInterpolator())
.start();
Spruce Dynamics
Animator spruceAnimator = new Spruce
.SpruceBuilder(parentViewGroup)
.sortWith(new LinearSort(/*interObjectDelay=*/100L, /*reversed=*/false, LinearSort.Direction.TOP_TO_BOTTOM))
.animateWith(DefaultAnimations.dynamicTranslationUpwards(parent))
.start();
QUESTION
Xamarin.Forms animation inside Listview stops working if collection changes
Asked 2022-Mar-22 at 05:34I am having a hard time figuring what's going on with my animation.
Viewmodel is composed of an ObservableCollection and every item contains a child ObservableCollection.
Parents
collection is bound to a BindableLayout. The ItemTemplate of that layout contains a Listview to display child's elements.
<StackLayout BindableLayout.ItemsSource ="{Binding Parents}">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="models:ParentRows">
<StackLayout>
<Grid BackgroundColor="White" >
<!-- Some bindable content there -->
</Grid>
<ListView ItemsSource="{Binding Childs}" CachingStrategy="RecycleElementAndDataTemplate" RowHeight="50">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:ChildRows">
<ViewCell>
<StackLayout BackgroundColor="White">
<controls:AnimatedGrid Refresh="{Binding Animation}"
<!-- Some bindable content there -->
</controls:AnimatedGrid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
I am using an AnimatedGrid on the child listview, this control is inherinting from Grid. It has an extra BindableProperty nammed Refresh and an Animation code that gets called whenever Refresh property changes.
private async void AnimateItem()
{
await Device.InvokeOnMainThreadAsync(() =>
{
this.RotateTo(360,500);
});
}
Everything works fine until i start filtering the list. Once i filter the list, subsequent call of AnimateItem will have no effect. To be more precise, if parent item got removed from list, and then added again, childs of this parent will never animate again. Filtering the List consist of Removing/Inserting parents to the observable collection (myCollection.Remove(item), myCollection.Insert(index, item), using Collection methods from framework).
This does not seems to be an observable collection binding issue, as values inside parent and childs collection still update perfectly find. Changing CachingStrategy also have no impact on the issue.
I found that, if i replace the ListView control by a CollectionView, the problem disappear. However, i realy want to find a solution that would alow me to keep the listview control as switching to CollectionView would introduce to many other undesirable effect.
Edit 22/02/2022 : I made a sample project to reproduce the issue on github.
Edit 15/03/2022 : I am still not able to figure what's wrong. However, for test purpose, i added in the control constructor, a task.delay followed by an animation call, and this call is working on filtered items. That's beyond my understanding.
ANSWER
Answered 2022-Mar-22 at 05:16In your AnimatedGrid class, add an isAttached flag, and add the following lines to your OnPropertyChanged override:
bool isAttached = false;
protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == "Renderer")
{
isAttached = !isAttached;
if (!isAttached) this.RemoveBinding(RefreshProperty);
}
if (propertyName == nameof(Refresh))
{
...
Disclaimer: it took me a long time to figure out what was going on here, and although i was able to fix the problem, i would not claim that i completely and perfectly understand it. I believe this is a bug in Xamarin, and in your case i would file an issue in Github (although maybe MAUI will have this corrected...)
When a ChildItem
is removed (do Filter), the old ChildItem-AnimatedGrid's Refresh
property remains bound to the ChildItem
's AnimationInt
property.
When a ChildItem
is added again (remove Filter), a new view is created.
Now the problem is evident: when the ChildItem
's AnimationInt
property changes (tap on ROTATE RANDOM button) the old ChildItem-AnimatedGrid's Refresh
is notified, and then the old View is rotated, but the new ramains unchanged (it does not rotate).
Once the problem is understood, we need to figure out how to remove the binding of the old view when the view is dettached: well, to do this i used the fact that the VisualElement's Renderer
property is set/modified when the element is attached and again when it is detached: The fist time it is called i set the isAttached
flag to true
. The second time it is called i set the flag to false
, and i remove the binding. Removing the binding of the old View allows the new View to be correctly bound.
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
No vulnerabilities reported
Save this library and start creating your kit
Explore Related Topics
Save this library and start creating your kit