Create slidable ListView in Windows 10 UWP apps li

2019-03-05 23:45发布

I'm creating UWP Application where I need to show an array of results in a sliding menu. The sliding menu is scrollable and can be slide to change it's height like the search results in Maps Application in windows 10 mobile. I can't find any tutorial to create such an experience.

Thanks in advance

enter image description here enter image description here

3条回答
▲ chillily
2楼-- · 2019-03-06 00:24

You can use a UserControl and UIElement.RenderTransform property to do this.

Here is a sample:

UserControl "SlidableControl" xaml:

<Grid x:Name="SlidRoot" ManipulationMode="All"  HorizontalAlignment="Stretch" ManipulationStarted="SlidRoot_ManipulationStarted"
          Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" ManipulationDelta="SlidRoot_ManipulationDelta"
          ManipulationCompleted="SlidRoot_ManipulationCompleted">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="30" />
        </Grid.RowDefinitions>
        <Border x:Name="SlidArea" BorderBrush="Black" BorderThickness="1" Grid.Row="0" Height="{x:Bind maxheight}" Background="AliceBlue"
                VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Child="{x:Bind SlidChild, Mode=OneWay}">
            <Border.RenderTransform>
                <CompositeTransform x:Name="SlidAreaTransform" TranslateY="{Binding ElementName=SlidTitle, Path=RenderTransform.TranslateY, Mode=TwoWay}" />
            </Border.RenderTransform>
        </Border>
        <Grid x:Name="SlidTitle" Background="Gray" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="1">
            <Grid.RenderTransform>
                <CompositeTransform x:Name="SlidTitleTransform" />
            </Grid.RenderTransform>
            <TextBlock Text="&#xE76F;" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black" FontFamily="Segoe MDL2 Assets" FontSize="25" />
        </Grid>
</Grid>

UserControl "SlidableControl" code behind:

private double maxheight;
private double Y;
private double finalY;

public SlidableControl()
{
    this.InitializeComponent();
    maxheight = Window.Current.Bounds.Height / 3;
    SlidArea.Visibility = Visibility.Collapsed;
}

private void SlidRoot_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
    SlidArea.Visibility = Visibility.Visible;
    SlidTitleTransform.TranslateY = -maxheight;
}

private void SlidRoot_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    Y = e.Delta.Translation.Y;
    finalY = SlidTitleTransform.TranslateY + Y;
    if (Y >= 0 && finalY <= 0)
    {
        if (finalY < maxheight)
            SlidTitleTransform.TranslateY = finalY;
        else
            SlidTitleTransform.TranslateY = 0;
    }
    else if (Y < 0 && finalY >= -maxheight)
    {
        if (finalY > -maxheight)
            SlidTitleTransform.TranslateY = finalY;
        else
        {
            SlidTitleTransform.TranslateY = -maxheight;
        }
    }
}

private void SlidRoot_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
    if (finalY <= -maxheight)
    {
        SlidArea.Visibility = Visibility.Collapsed;
        SlidTitleTransform.TranslateY = 0;
    }
}

public static readonly DependencyProperty ChildProperty = DependencyProperty.Register("SlidChild", typeof(UIElement), typeof(SlidableControl), new PropertyMetadata(null));

public UIElement SlidChild
{
    get { return (UIElement)GetValue(ChildProperty); }
    set { SetValue(ChildProperty, value); }
}

You can see from my code, that I expose the SlidChild property, so you can add any other control to this "SlidableControl" for example like this:

<local:SlidableControl VerticalAlignment="Top">
    <local:SlidableControl.SlidChild>
        <ListView x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding txt}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </local:SlidableControl.SlidChild>
</local:SlidableControl>

This is a very early version of control, you can expose some other properties, like control's height.

Here is my demo, you can have a test.

This is the rendering image of my test: enter image description here

查看更多
祖国的老花朵
3楼-- · 2019-03-06 00:31

We Are looking to make modify on the behavior of your example in above, we want to change the behavior as the following image (the list should be on the map (blue Section) and the list motion from bottom to top as the image), what we should to change to do it?

enter image description here

查看更多
做个烂人
4楼-- · 2019-03-06 00:36

Also you can use UserControl to do this.

XAML:

<ScrollViewer x:Name="scrollViewer" HorizontalAlignment="Stretch" ScrollViewer.VerticalScrollMode="Disabled" VerticalScrollBarVisibility="Hidden">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="20" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Border x:Name="Area1" Grid.Row="0" Height="{x:Bind childheight}" HorizontalAlignment="Stretch" Background="AliceBlue"></Border>
        <Grid x:Name="SlidButton" Background="Gray" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="1"
              ManipulationStarted="SlidButton_ManipulationStarted" ManipulationCompleted="SlidButton_ManipulationCompleted" 
              ManipulationMode="All" ManipulationDelta="SlidButton_ManipulationDelta">
            <TextBlock Text="&#xE76F;" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black" FontFamily="Segoe MDL2 Assets" FontSize="15" />
        </Grid>
        <Border x:Name="Area2" Grid.Row="2" Height="{x:Bind childheight}" HorizontalAlignment="Stretch" Background="Transparent"></Border>
    </Grid>
</ScrollViewer>

code behind:

private double height;
private double childheight;

public SlidableView()
{
    this.InitializeComponent();
    height = Window.Current.Bounds.Height * 2 - 40;
    childheight = Window.Current.Bounds.Height - 40;
}

private void SlidButton_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
    scrollViewer.VerticalScrollMode = ScrollMode.Enabled;
}

private void SlidButton_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
    scrollViewer.VerticalScrollMode = ScrollMode.Disabled;
}

private static double Y;

private void SlidButton_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    Y = Y + e.Delta.Translation.Y;
    scrollViewer.ChangeView(null, -Y, null);
}

This is a very simple version works on mobile, when it is applied on PC, please change the "height" and "childheight" like this:

height = Window.Current.Bounds.Height * 2 - 20;
childheight = Window.Current.Bounds.Height - 20;

And when I say this is a very simple version, because I didn't expose any property of this usercontrol, you can expose the both child property of two Border controls as it in my last answer.

查看更多
登录 后发表回答