Search code examples
c#listviewmobilexamarin.formsparallax

Parallax Work, But ListView in PARALLAX not Work - Xamarin Forms


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


Solution

  • 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