Xamarin Forms CollectionView OnScroll Hide/Show 元素
Xamarin Forms CollectionView OnScroll Hide/Show Element
我正在尝试创建一个滚动感知 header,它根据向上或向下滚动来隐藏或显示 header。
我有一个带有 header 菜单和 collection 视图的网格:
<Grid RowDefinitions="Auto, *">
<ContentView x:Name="Header"> ... </ContentView>
<CollectionView Grid.Row="1"
Scrolled="CollectionView_OnScrolled" ... />
</Grid>
在滚动事件中,我尝试执行类似的操作:
void OperationList_Scrolled(object sender, ItemsViewScrolledEventArgs e)
{
if (Header.IsVisible && e.VerticalDelta > 0)
{
Header.IsVisible = false;
}
else if (!Header.IsVisible && e.VerticalDelta < 0)
{
Header.IsVisible = true;
}
}
但是不是很流畅,一直闪。您有什么想法可以正确完成此操作吗?
您可以使用动画来模拟 header 可见或不可见以避免闪烁。
Xaml:
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<CollectionView x:Name="collectionView" ItemsSource="{Binding Monkeys}" AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All" Scrolled="CollectionView_OnScrolled">
<CollectionView.Header>
<ContentView>
<StackLayout x:Name="HeaderView" />
</ContentView>
</CollectionView.Header>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}" FontSize="Large"></Label>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Frame
x:Name="HeaderLabelView"
Margin="16,8,16,8"
Padding="3"
AbsoluteLayout.LayoutBounds="0.5, 0, AutoSize, AutoSize"
AbsoluteLayout.LayoutFlags="PositionProportional"
CornerRadius="6"
HasShadow="True">
<Label HorizontalOptions="FillAndExpand" />
</Frame>
</AbsoluteLayout>
后面的代码:
public partial class Page10 : ContentPage
{
public Page10()
{
InitializeComponent();
this.BindingContext = new MonkeyViewModel();
}
private void CollectionView_OnScrolled(object sender, ItemsViewScrolledEventArgs e)
{
var transY = Convert.ToInt32(HeaderLabelView.TranslationY);
if (transY == 0 &&
e.VerticalDelta > 15)
{
var trans = HeaderLabelView.Height + HeaderLabelView.Margin.Top;
Task.WhenAll(
HeaderLabelView.TranslateTo(0, -(trans), 200, Easing.CubicIn),
HeaderLabelView.FadeTo(0.25, 200));
}
else if (transY != 0 &&
e.VerticalDelta < 0 &&
Math.Abs(e.VerticalDelta) > 10)
{
Task.WhenAll(
HeaderLabelView.TranslateTo(0, 0, 200, Easing.CubicOut),
HeaderLabelView.FadeTo(1, 200));
}
}
}
public class MonkeyViewModel
{
public ObservableCollection<Monkey> Monkeys { get; set; }
public MonkeyViewModel()
{
Monkeys = new ObservableCollection<Monkey>()
{
new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"},
new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="g"},
};
}
}
public class Monkey
{
public string Name { get; set; }
}
我正在尝试创建一个滚动感知 header,它根据向上或向下滚动来隐藏或显示 header。
我有一个带有 header 菜单和 collection 视图的网格:
<Grid RowDefinitions="Auto, *">
<ContentView x:Name="Header"> ... </ContentView>
<CollectionView Grid.Row="1"
Scrolled="CollectionView_OnScrolled" ... />
</Grid>
在滚动事件中,我尝试执行类似的操作:
void OperationList_Scrolled(object sender, ItemsViewScrolledEventArgs e)
{
if (Header.IsVisible && e.VerticalDelta > 0)
{
Header.IsVisible = false;
}
else if (!Header.IsVisible && e.VerticalDelta < 0)
{
Header.IsVisible = true;
}
}
但是不是很流畅,一直闪。您有什么想法可以正确完成此操作吗?
您可以使用动画来模拟 header 可见或不可见以避免闪烁。
Xaml:
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<CollectionView x:Name="collectionView" ItemsSource="{Binding Monkeys}" AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All" Scrolled="CollectionView_OnScrolled">
<CollectionView.Header>
<ContentView>
<StackLayout x:Name="HeaderView" />
</ContentView>
</CollectionView.Header>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}" FontSize="Large"></Label>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Frame
x:Name="HeaderLabelView"
Margin="16,8,16,8"
Padding="3"
AbsoluteLayout.LayoutBounds="0.5, 0, AutoSize, AutoSize"
AbsoluteLayout.LayoutFlags="PositionProportional"
CornerRadius="6"
HasShadow="True">
<Label HorizontalOptions="FillAndExpand" />
</Frame>
</AbsoluteLayout>
后面的代码:
public partial class Page10 : ContentPage
{
public Page10()
{
InitializeComponent();
this.BindingContext = new MonkeyViewModel();
}
private void CollectionView_OnScrolled(object sender, ItemsViewScrolledEventArgs e)
{
var transY = Convert.ToInt32(HeaderLabelView.TranslationY);
if (transY == 0 &&
e.VerticalDelta > 15)
{
var trans = HeaderLabelView.Height + HeaderLabelView.Margin.Top;
Task.WhenAll(
HeaderLabelView.TranslateTo(0, -(trans), 200, Easing.CubicIn),
HeaderLabelView.FadeTo(0.25, 200));
}
else if (transY != 0 &&
e.VerticalDelta < 0 &&
Math.Abs(e.VerticalDelta) > 10)
{
Task.WhenAll(
HeaderLabelView.TranslateTo(0, 0, 200, Easing.CubicOut),
HeaderLabelView.FadeTo(1, 200));
}
}
}
public class MonkeyViewModel
{
public ObservableCollection<Monkey> Monkeys { get; set; }
public MonkeyViewModel()
{
Monkeys = new ObservableCollection<Monkey>()
{
new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"},
new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="D"}, new Monkey(){ Name="A"},
new Monkey(){ Name="B"},
new Monkey(){ Name="C"},
new Monkey(){ Name="g"},
};
}
}
public class Monkey
{
public string Name { get; set; }
}