How to avoid the flickering effect when dynamicall

2019-08-15 09:04发布

问题:

I have set of images and I am replacing the image source in a button click event. I am getting the flickering effect when replacing the image source. How to resolve this ?

Sample

     <StackPanel>

            <StackPanel Orientation="Horizontal">
                <Image x:Name="image1" Height="200" Width="200" Source="ms-appx:///Assets/custom200.png"/>
                <Image x:Name="image2" Height="200" Width="200" Source="ms-appx:///Assets/custom201.png"/>
                <Image x:Name="image3" Height="200" Width="200" Source="ms-appx:///Assets/custom202.png"/>
                <Image x:Name="image4" Height="200" Width="200" Source="ms-appx:///Assets/custom203.png"/>
            </StackPanel>



            <Button Height="50" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
                Content="Replace OSM" x:Name="replaceOSM" Click="replace_Click" Margin="5"/>


        </StackPanel>



 private void replace_Click(object sender, RoutedEventArgs e)
        {
            image1.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM200.png", 
                UriKind.RelativeOrAbsolute));
            image2.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM201.png",
              UriKind.RelativeOrAbsolute));
            image3.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM202.png",
              UriKind.RelativeOrAbsolute));
            image4.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM203.png",
              UriKind.RelativeOrAbsolute));

        }

回答1:

For the flickering effect is changed fast. And it does the code that cost too long in UI thread.

You can use bitmapImage.SetSourceAsync to wait for the image load.

    private async Task SetSourceAsync(Image image, Uri uri)
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
        {
            var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
            var bitmapImage = new BitmapImage();
            await bitmapImage.SetSourceAsync(await file.OpenAsync(FileAccessMode.Read));
            image.Source = bitmapImage;
        });
    }

You can change your code

        image1.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM200.png",
            UriKind.RelativeOrAbsolute));
        image2.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM201.png",
          UriKind.RelativeOrAbsolute));
        image3.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM202.png",
          UriKind.RelativeOrAbsolute));
        image4.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM203.png",
          UriKind.RelativeOrAbsolute));
        image5.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM210.png",
          UriKind.RelativeOrAbsolute));
        image6.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM211.png",
          UriKind.RelativeOrAbsolute));
        image7.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM212.png",
          UriKind.RelativeOrAbsolute));
        image8.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM213.png",
          UriKind.RelativeOrAbsolute));
        image9.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM220.png",
          UriKind.RelativeOrAbsolute));
        image10.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM221.png",
          UriKind.RelativeOrAbsolute));
        image11.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM222.png",
          UriKind.RelativeOrAbsolute));
        image12.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM223.png",
          UriKind.RelativeOrAbsolute));

To

    private async void Replace_Click(object sender, RoutedEventArgs e)
    {

       await  SetSourceAsync(image1, new Uri("ms-appx:///Assets/OSM200.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image2, new Uri("ms-appx:///Assets/OSM201.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image3, new Uri("ms-appx:///Assets/OSM202.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image4, new Uri("ms-appx:///Assets/OSM203.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image5, new Uri("ms-appx:///Assets/OSM210.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image6, new Uri("ms-appx:///Assets/OSM211.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image7, new Uri("ms-appx:///Assets/OSM212.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image8, new Uri("ms-appx:///Assets/OSM213.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image9, new Uri("ms-appx:///Assets/OSM220.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image10, new Uri("ms-appx:///Assets/OSM221.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image11, new Uri("ms-appx:///Assets/OSM222.png",
            UriKind.RelativeOrAbsolute));
        await SetSourceAsync(image12, new Uri("ms-appx:///Assets/OSM223.png",
            UriKind.RelativeOrAbsolute));
    }

But it always is flickering when the code run in some poor GPU.

I think the other way is Hide and Show the Image or making an animation.

The hide and show way is make some panel that will show one of the panel.

      <StackPanel x:Name="custom">
               <StackPanel Orientation="Horizontal">
                   <Image x:Name="image1" Height="200" Width="200" Source="ms-appx:///Assets/custom200.png"/>
                   <Image x:Name="image2" Height="200" Width="200" Source="ms-appx:///Assets/custom201.png"/>
                   <Image x:Name="image3" Height="200" Width="200" Source="ms-appx:///Assets/custom202.png"/>
                   <Image x:Name="image4" Height="200" Width="200" Source="ms-appx:///Assets/custom203.png"/>
               </StackPanel>
               <StackPanel Orientation="Horizontal">
                   <Image x:Name="image5" Height="200" Width="200" Source="ms-appx:///Assets/custom210.png"/>
                   <Image x:Name="image6" Height="200" Width="200" Source="ms-appx:///Assets/custom211.png"/>
                   <Image x:Name="image7" Height="200" Width="200" Source="ms-appx:///Assets/custom212.png"/>
                   <Image x:Name="image8" Height="200" Width="200" Source="ms-appx:///Assets/custom213.png"/>
               </StackPanel>
               <StackPanel Orientation="Horizontal">
                   <Image x:Name="image9"  Height="200" Width="200" Source="ms-appx:///Assets/custom220.png"/>
                   <Image x:Name="image10" Height="200" Width="200" Source="ms-appx:///Assets/custom221.png"/>
                   <Image x:Name="image11" Height="200" Width="200" Source="ms-appx:///Assets/custom222.png"/>
                   <Image x:Name="image12" Height="200" Width="200" Source="ms-appx:///Assets/custom223.png"/>
               </StackPanel>
        </StackPanel>

        <StackPanel x:Name="Osm" Visibility="Collapsed">
            <StackPanel Orientation="Horizontal">
                <Image Height="200" Width="200" Source="ms-appx:///Assets/OSM200.png"/>
                <Image  Height="200" Width="200" Source="ms-appx:///Assets/OSM201.png"/>
                <Image Height="200" Width="200" Source="ms-appx:///Assets/OSM202.png"/>
                <Image  Height="200" Width="200" Source="ms-appx:///Assets/OSM203.png"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Image  Height="200" Width="200" Source="ms-appx:///Assets/OSM210.png"/>
                <Image  Height="200" Width="200" Source="ms-appx:///Assets/OSM211.png"/>
                <Image  Height="200" Width="200" Source="ms-appx:///Assets/OSM212.png"/>
                <Image  Height="200" Width="200" Source="ms-appx:///Assets/OSM213.png"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Image   Height="200" Width="200" Source="ms-appx:///Assets/OSM220.png"/>
                <Image  Height="200" Width="200" Source="ms-appx:///Assets/OSM221.png"/>
                <Image  Height="200" Width="200" Source="ms-appx:///Assets/OSM222.png"/>
                <Image  Height="200" Width="200" Source="ms-appx:///Assets/OSM223.png"/>
            </StackPanel>
        </StackPanel>

And you can write some button and click

        <StackPanel Orientation="Horizontal">
            <Button Height="50" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
                    Content="ReplaceCustom"  Click="ShowCustom_OnClick" Margin="5"/>

            <Button Height="50" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
                    Content="Replace OSM"  Click="ShowReplace_OnClick" Margin="5"/>


        </StackPanel>

You can show the panel when the button is clicked.

    private void ShowCustom_OnClick(object sender, RoutedEventArgs e)
    {
        custom.Visibility = Visibility.Visible;
        Osm.Visibility = Visibility.Collapsed;
    }

    private void ShowReplace_OnClick(object sender, RoutedEventArgs e)
    {
        custom.Visibility = Visibility.Collapsed;
        Osm.Visibility = Visibility.Visible;
    }