Personally I created a PARALLAX effect in my application, but within the effect (PARALLAX) I have a LISTVIEW that shows my content! only when the effect ends, the ListView SCROLL does not work and does not load all the content!
My Code
ParallaxControl.cs
public class ParallaxControl : ScrollView
{
public ParallaxControl()
{
Scrolled += (sender, e) => Parallax();
}
public static readonly BindableProperty ParallaxViewProperty =
BindableProperty.Create(nameof(ParallaxControl), typeof(View), typeof(ParallaxControl), null);
public View ParallaxView
{
get { return (View)GetValue(ParallaxViewProperty); }
set { SetValue(ParallaxViewProperty, value); }
}
double height;
public void Parallax()
{
if (ParallaxView == null || Device.RuntimePlatform == "Windows" || Device.RuntimePlatform == "WinPhone")
return;
if (height <= 0)
height = ParallaxView.Height;
ParallaxView.IsEnabled = false;
var y = -(int)((float)ScrollY / 2.5f);
if (y < 0)
{
//Move a imagem no eixo Y em uma fração da posição Y do ScrollView.
ParallaxView.Scale = 1;
ParallaxView.TranslationY = y;
}
else if (Device.RuntimePlatform == "iOS")
{
//Calcula uma escala que iguala a altura x scroll.
double newHeight = height + (ScrollY * -1);
ParallaxView.Scale = newHeight / height;
ParallaxView.TranslationY = -(ScrollY / 2);
}
else
{
ParallaxView.Scale = 1;
ParallaxView.TranslationY = 0;
}
}
}
Menu.XAML
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DeLivre.Controls"
xmlns:cardView="clr-namespace:DeLivre"
xmlns:local1="clr-namespace:DeLivre.Controls"
xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin"
x:Class="DeLivre.Views.Cardapio_Menu">
<ContentPage.ToolbarItems>
<ToolbarItem Name="MenuItem1" Order="Primary" Icon="ic_Carrinho" Clicked="MenuItem1_Clicked" Text="Carrinho" Priority="0" />
</ContentPage.ToolbarItems>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="200" x:Name="Row1Header"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid RowSpacing="0" ColumnSpacing="0" x:Name="HeaderView">
<StackLayout Padding="5,5,5,0" BackgroundColor="White" Orientation="Vertical">
<SearchBar x:Name="CardapioPesquisa" Placeholder="Pesquise por um lanche!" HeightRequest="40" BackgroundColor="White" TextChanged="CardapioPesquisa_TextChanged" />
<cardView:CardView x:Name="CardEstabelecimento" BackgroundColor="White" CardViewHasShadow="True" HeightRequest="220">
<cardView:CardView.CardViewContent>
<StackLayout x:Name="Stack"
Padding="2"
HorizontalOptions="Center"
Spacing="2"
VerticalOptions="Center">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<controls:CircleImage x:Name="ImagemEstab"
Grid.Column="1"
BorderColor="#EF5350"
BorderThickness="2"
Margin="1,0,1,0"
WidthRequest="100"
HeightRequest="100"
Aspect="AspectFit"/>
<Label x:Name="lblEntrega"
Grid.Column="0"
Text="ENTREGA"
TextColor="{StaticResource asphaltPrimary}"
FontSize="16" FontAttributes="Bold"/>
<Label x:Name="EstabLocal"
Grid.Column="0"
Margin="0,20"
TextColor="{StaticResource asphaltPrimary}"
FontSize="13"/>
<Label x:Name="EstabEntrega"
Grid.Column="0"
TextColor="{StaticResource asphaltPrimary}"
Margin="-15,35,0,0"
FontSize="13"
HorizontalTextAlignment="End"/>
<Label x:Name="EstabFuncionamento"
TextColor="{StaticResource asphaltPrimary}"
Grid.Column="2"
FontSize="13"/>
<Label x:Name="EstabFrete"
Grid.Column="2"
TextColor="{StaticResource asphaltPrimary}"
Margin="0,15,0,0"
FontSize="13" />
</Grid>
<Label x:Name="Descricao"
Text="Teste"
HorizontalTextAlignment="Center"
TextColor="{StaticResource asphaltPrimary}"
Margin="0,15,0,0"
FontSize="13" />
</StackLayout>
</cardView:CardView.CardViewContent>
</cardView:CardView>
</StackLayout>
</Grid>
<local:ParallaxControl x:Name="MainScroll" Grid.RowSpan="2">
<Grid RowSpacing="0" ColumnSpacing="0" >
<Grid.RowDefinitions>
<RowDefinition Height="200"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackLayout Grid.Row="1">
<ListView x:Name="ListaCardapio"
BackgroundColor="White"
SeparatorColor="{StaticResource grayPrimary}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
ItemSelected="ListaCardapio_ItemSelected"
ItemsSource="{Binding Cardapios}"
CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout >
<StackLayout Orientation="Horizontal">
<controls:CircleImage x:Name="ImagemEstab"
Grid.Column="1"
Source="{Binding Icon_Lanche}"
BorderColor="#EF5350"
BorderThickness="2"
Margin="1,0,1,0"
WidthRequest="100"
HeightRequest="100"
Aspect="AspectFit"/>
<Label x:Name="NomeLanche" Text="{Binding Tipo}"
FontSize="13"
Margin="-5,7"
TextColor="{StaticResource asphaltPrimary}" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>
</local:ParallaxControl>
</Grid>
Menu.XAML.CS
public Cardapio_Menu()
{
InitializeComponent ();
MainScroll.ParallaxView = HeaderView;
}
The effect works, the problem is that when the effect ends, the Listview scroll does not work and does not show the rest of my data!
Please Help
What you can do is replace the Xamarin.Forms
ListView
with the RepeaterView
RepeaterView
is a control that inherits from stacklayout and works very much like ListView but does not have its own scroll, since you already have a scroll it should work great for you.
public class RepeaterView<T> : StackLayout where T : class
{
public static readonly BindableProperty HeaderTemplateProperty = BindableProperty.Create(nameof(HeaderTemplate), typeof(DataTemplate), typeof(RepeaterView<T>), default(DataTemplate));
public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(nameof(ItemTemplate), typeof(DataTemplate), typeof(RepeaterView<T>), default(DataTemplate));
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable<T>), typeof(RepeaterView<T>), null, defaultBindingMode: BindingMode.OneWay, propertyChanged: ItemsChanged);
public RepeaterView()
{
Spacing = 0;
}
public IEnumerable<T> ItemsSource
{
get { return (IEnumerable<T>)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public DataTemplate ItemTemplate
{
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
}
public DataTemplate HeaderTemplate
{
get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
set { SetValue(HeaderTemplateProperty, value); }
}
protected virtual View ViewFor(T item)
{
View view = null;
if (ItemTemplate != null)
{
var content = ItemTemplate.CreateContent();
view = (content is View) ? content as View : ((ViewCell)content).View;
view.BindingContext = item;
}
return view;
}
protected View HeaderView()
{
View view = null;
if (HeaderTemplate != null)
{
var content = HeaderTemplate.CreateContent();
view = (content is View) ? content as View : ((ViewCell)content).View;
view.BindingContext = this.BindingContext;
}
return view;
}
private static void ItemsChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = bindable as RepeaterView<T>;
if (control == null)
return;
control.Children.Clear();
IEnumerable<T> items = (IEnumerable<T>)newValue;
if (items.Any())
{
var header = control.HeaderView();
if (header != null)
control.Children.Add(header);
foreach (var item in items)
control.Children.Add(control.ViewFor(item));
}
}
}
For better understanding of how this control works you can check the guide here
Feel free to revert if you have queries