简体   繁体   English

带有动画 xamarin 形式的 ScrollView

[英]ScrollView with animation xamarin forms

I would like to know how to do the following horizontal scrollview with animation : so the button closer to screen center so is bigger.我想知道如何使用动画执行以下水平滚动视图:因此靠近屏幕中心的按钮更大。

And I also would like to know how to position the button like in the picture.而且我也想知道如何像图片中那样定位按钮。

带按钮的水平滚动视图

Thanks :)谢谢 :)

Query 1:查询 1:

If I understand you correctly, you want all the visible views inside the scrollview to change their scale according to their position.如果我理解正确,您希望滚动视图中的所有可见视图根据它们的位置改变它们的比例。

This can be achieved by using a custom view and binding the scrollview's Width and ScrollX to it to change the view's Scale.这可以通过使用自定义视图并将滚动视图的WidthScrollX到它来更改视图的比例来实现。

My solution working gif我的解决方案工作 gif

Created CustomView derived from ContentView .创建从ContentView派生的 CustomView 。 Added three BindableProperties each for ScrollX , Width of ScrollView and Position of the view in the scrollview.分别为ScrollX 、 ScrollView 的Width和滚动视图中的视图Position添加了三个 BindableProperties 。

For all three BindableProperty's PropertyChanged bound a single method OnScaleFactorsChange and calculated the scale of the view accordingly.对于所有三个 BindableProperty 的PropertyChanged绑定一个方法OnScaleFactorsChange并相应地计算视图的比例。

Bindable properties in CustomView CustomView 中的可绑定属性

    /// <summary>
    /// Gets or sets ScrolledPosition
    /// </summary>
    public double ScrolledPosition
    {
        get { return (double)GetValue(ScrolledPositionProperty); }
        set
        {
            SetValue(ScrolledPositionProperty, value);
        }
    }

    /// <summary>
    /// Identifies the <see cref="ScrolledPosition"/> bindable property.
    /// </summary>
    public static readonly BindableProperty ScrolledPositionProperty = BindableProperty.Create("ScrolledPosition", typeof(double), typeof(CustomView), 0d, BindingMode.TwoWay, null, OnScaleFactorsChange);

    /// <summary>
    /// Gets or sets Position
    /// </summary>
    public double Position
    {
        get { return (double)GetValue(PositionProperty); }
        set
        {
            SetValue(PositionProperty, value);
        }
    }

    /// <summary>
    /// Identifies the <see cref="Position"/> bindable property.
    /// </summary>
    public static readonly BindableProperty PositionProperty = BindableProperty.Create("Position", typeof(double), typeof(CustomView), 0d, BindingMode.TwoWay, null, OnScaleFactorsChange);

    /// <summary>
    /// Gets or sets ScrollViewWidth
    /// </summary>
    public double ScrollViewWidth
    {
        get { return (double)GetValue(ScrollViewWidthProperty); }
        set
        {
            SetValue(ScrollViewWidthProperty, value);
        }
    }

    /// <summary>
    /// Identifies the <see cref="ScrollViewWidth"/> bindable property.
    /// </summary>
    public static readonly BindableProperty ScrollViewWidthProperty = BindableProperty.Create("ScrollViewWidth", typeof(double), typeof(CustomView), 0d, BindingMode.TwoWay, null, OnScaleFactorsChange);

OnScaleFactorsChange method OnScaleFactorsChange 方法

 private static void OnScaleFactorsChange(BindableObject bindable, object oldvalue, object newValue)
        {
            (bindable as CustomView).ChangeScale();
        }

        private void ChangeScale()
        {
            var itemWd = this.Width;

            var itemPresent = this.ScrollViewWidth / this.Width;
            double ratio = 0;

            var scrolledItems = this.ScrolledPosition / this.Width;

            double totalRatio = ((this.Position - 0.5 - scrolledItems) / (itemPresent / 2));

            if (totalRatio > 0 && totalRatio < 2)
            {
                ratio = totalRatio > 1 ? 2 - totalRatio : totalRatio;
            }

            // Minimum scale 0.75 , maximum scale 1(0.75 + 0.25)
            this.Scale = 0.75 + 0.25 * ratio;
        }

Also call the scale changing method in SizeChanged event

        public CustomView()
        {
            InitializeComponent();
            this.SizeChanged += CustomView_SizeChanged;
        }

        private void CustomScrollView_SizeChanged(object sender, EventArgs e)
        {
            ChangeScale();
        }

Finally use it inside ScrollView 's BindableLayout 's ItemTemplate and bind the properties.最后在ScrollViewBindableLayoutItemTemplate使用它并绑定属性。

Sample page XAML示例页面 XAML

The Position is given in the Model of the Item.位置在项目的模型中给出。

<ScrollView
    Grid.Row="1"
    Orientation="Horizontal"
    x:Name="scrollview">
    <StackLayout
        Padding="0"
        Spacing="0"
        Orientation="Horizontal"
    BindableLayout.ItemsSource="{Binding CustomItems}">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <local:CustomView
                WidthRequest="50"
                Padding="20"
                BackgroundColor="#aaff0000"
                Position="{Binding Position}"
                ScrolledPosition="{Binding Source={x:Reference scrollview}, Path=ScrollX}"
                ScrollViewWidth="{Binding Source={x:Reference scrollview}, Path=Width}">
                    <Grid Padding="20" BackgroundColor="#aaf000aa">
                        <Label Text="{Binding Position}"/>
                    </Grid>
                </local:CustomView>
        </DataTemplate>
    </BindableLayout.ItemTemplate>
        </StackLayout>
</ScrollView>

This might be a long way around but this is the only way I was able to achieve this.这可能还有很长的路要走,但这是我能够实现这一目标的唯一方法。

Please do ask if any clarification is required.请务必询问是否需要澄清。

Query 2查询 2

The button position can be achieved by many ways.按钮位置可以通过多种方式实现。 I have listed a few below.我在下面列出了一些。

1:Using Grid column 1:使用网格列

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Button
            Grid.Column="1"
            BackgroundColor="LightCoral"
            Text="Hi there"/>
</Grid>

2:Using Vertical and Horizontal option 2:使用垂直和水平选项

    <Grid>
            <Button
                BackgroundColor="LightCoral"
                VerticalOptions="Center"
                HorizontalOptions="Center"
                Text="Hi there"/>
        </Grid>

3:Using AbsoluteLayout 3:使用绝对布局

<AbsoluteLayout>
                <Button
                    BackgroundColor="LightCoral"
                    AbsoluteLayout.LayoutFlags="All"
                    AbsoluteLayout.LayoutBounds="0.5,0.5,0.2,0.2"
                    Text="Hi there">
                </Button>
            </AbsoluteLayout>

Tried to achieve it in the simple binding but later found that a custom view could to be to achieve it easier hence posted this.试图在简单绑定中实现它,但后来发现自定义视图可以更容易地实现它,因此发布了这个。

Hope this could help you.希望这可以帮助你。

You could use CardsView to do that.你可以使用CardsView来做到这一点。

CardsView : https://github.com/AndreiMisiukevich/CardView CardsViewhttps : //github.com/AndreiMisiukevich/CardView

Download the sample code from the GitHub.从 GitHub 下载示例代码。 In CoverFlowSampleXamlView , the sample use the custom control PanCardView .CoverFlowSampleXamlView ,示例使用自定义控件PanCardView The part of CoverFlowView could do the horizontal scrollview. CoverFlowView的部分可以做水平滚动视图。 In the sample code, it use the image, you could change it to the ImageButton .在示例代码中,它使用图像,您可以将其更改为ImageButton

CoverFlowSampleXamlView.xaml CoverFlowSampleXamlView.xaml

Change:改变:

<ffimage:CachedImage Source="{Binding Source}" Aspect="AspectFill"/>

To:到:

<ImageButton Source="{Binding Source}"></ImageButton>

CardsSampleViewModel.cs CardsSampleViewModel.cs

Change the source.改变来源。 I add five images in the Resources/drawable folder.我在 Resources/drawable 文件夹中添加了五个图像。

Items = new ObservableCollection<object>
                 {
            new { Source = "a.jpg" },
            new { Source = "b.jpg" },
            new { Source = "dog.jpg" },
            new { Source = "c.jpg" },
            new { Source = "d.jpg" }
        };

Result:结果:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM