Query 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.
Created CustomView derived from ContentView
. Added three BindableProperties each for ScrollX
, Width
of ScrollView and Position
of the view in the scrollview.
For all three BindableProperty's PropertyChanged
bound a single method OnScaleFactorsChange
and calculated the scale of the view accordingly.
Bindable properties in 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
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.
Sample page 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
The button position can be achieved by many ways. I have listed a few below.
1:Using Grid column
<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
<Grid>
<Button
BackgroundColor="LightCoral"
VerticalOptions="Center"
HorizontalOptions="Center"
Text="Hi there"/>
</Grid>
3:Using AbsoluteLayout
<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
: https://github.com/AndreiMisiukevich/CardView
Download the sample code from the GitHub. In CoverFlowSampleXamlView
, the sample use the custom control PanCardView
. The part of CoverFlowView
could do the horizontal scrollview. In the sample code, it use the image, you could change it to the ImageButton
.
CoverFlowSampleXamlView.xaml
Change:
<ffimage:CachedImage Source="{Binding Source}" Aspect="AspectFill"/>
To:
<ImageButton Source="{Binding Source}"></ImageButton>
CardsSampleViewModel.cs
Change the source. I add five images in the Resources/drawable folder.
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:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.