gpt4 book ai didi

wpf - Scrollviewer 边缘模糊效果,opacitymask 无法正常工作

转载 作者:行者123 更新时间:2023-12-04 13:39:48 25 4
gpt4 key购买 nike

我想在不使用滚动条的情况下为触摸屏应用程序创建自定义滚动查看器控件。为了让用户知道他们可以滚动内容,我使用 opacitymask 以线性渐变淡化滚动查看器的底部和顶部。这一切都很好,除了应用于文本块和滚动查看器的不透明掩码的问题!

我的意思是,我希望淡入淡出效果适用于滚动查看器的顶部 1% 和底部 1%,然后滚动查看器的中间将可见。然而,问题是,即使我在文本块上设置了 OpacityMask="{x:Null}",这种效果也会发生在滚动查看器中的控件上。

我也尝试将 opacitymask 应用到滚动查看器的外部,但发生了同样的问题。 Opacitymask 属性是否也适用于 child ?有没有更好的方法来实现这种褪色效果?

这是我正在使用的代码:

<Grid Width="200" Height="130">
<ScrollViewer BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Padding="2"
HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Hidden" >
<ScrollViewer.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="Transparent" Offset="0" />
<GradientStop Color="Black" Offset="0.1" />
<GradientStop Color="Black" Offset="0.9" />
<GradientStop Color="Transparent" Offset="1" />
</LinearGradientBrush>
</ScrollViewer.OpacityMask>
<TextBlock Margin="0,10" Style="{StaticResource textSmall}" TextWrapping="Wrap">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
</TextBlock>
</ScrollViewer>
</Grid>

最佳答案

我知道这是一个较旧的问题,但我遇到了这个问题,因为我试图做类似的事情;所以我想我会为下一个人发布我的解决方案。对我的解决方案的任何反馈表示赞赏。

在我们的应用程序中,我们的大多数 ScrollViewer 控件都位于非滚动纹理的顶部,因此我们希望可滚动内容在 ScrollViewer 的边缘淡入该背景,但前提是该方向有更多内容。此外,我们至少有一个 2 轴可滚动区域,用户可以在其中向各个方向平移。它也必须在这种情况下工作。我们的应用程序也没有真正的滚动条,但我已经把它排除在我在这里提出的解决方案之外(它不会影响解决方案)。

此解决方案的特点:

  • 如果 ScrollViewer 的那一侧有当前不可见的内容,则淡化 ScrollViewer 中内容的边缘。
  • 当您滚动到内容边缘时,降低淡入淡出效果的强度。
  • 对褪色边缘的外观进行一些控制。具体来说,您可以控制:
  • 褪色边缘厚度
  • 内容在最外边缘的不透明程度(或淡入淡出的“强度”)
  • 当您在边缘附近滚动时淡化效果消失的速度

  • 基本思想是控制 ScrollViewer 模板中可滚动内容的不透明蒙版。不透明蒙版包含一个透明的外边框和一个不透明的内边框,其中应用了 BlurEffect 以获得边缘的渐变效果。然后,当您滚动时控制内边框的边距,以控制渐变沿特定边缘出现的“深度”。

    此解决方案继承了 ScrollViewer,并要求您指定对 ScrollViewer 模板的更改。 ScrollContentPresenter 需要包装在名为“PART_ScrollContentPresenterContainer”的 Border 中。

    FadingScrollViewer 类
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Effects;

    namespace ScrollViewerTest
    {
    public class FadingScrollViewer : ScrollViewer
    {
    private const string PART_SCROLL_PRESENTER_CONTAINER_NAME = "PART_ScrollContentPresenterContainer";

    public double FadedEdgeThickness { get; set; }
    public double FadedEdgeFalloffSpeed { get; set; }
    public double FadedEdgeOpacity { get; set; }

    private BlurEffect InnerFadedBorderEffect { get; set; }
    private Border InnerFadedBorder { get; set; }
    private Border OuterFadedBorder { get; set; }



    public FadingScrollViewer()
    {
    this.FadedEdgeThickness = 20;
    this.FadedEdgeFalloffSpeed = 4.0;
    this.FadedEdgeOpacity = 0.0;

    this.ScrollChanged += FadingScrollViewer_ScrollChanged;
    this.SizeChanged += FadingScrollViewer_SizeChanged;
    }



    private void FadingScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
    if (this.InnerFadedBorder == null)
    return;

    var topOffset = CalculateNewMarginBasedOnOffsetFromEdge(this.VerticalOffset); ;
    var bottomOffset = CalculateNewMarginBasedOnOffsetFromEdge(this.ScrollableHeight - this.VerticalOffset);
    var leftOffset = CalculateNewMarginBasedOnOffsetFromEdge(this.HorizontalOffset);
    var rightOffset = CalculateNewMarginBasedOnOffsetFromEdge(this.ScrollableWidth - this.HorizontalOffset);

    this.InnerFadedBorder.Margin = new Thickness(leftOffset, topOffset, rightOffset, bottomOffset);
    }



    private double CalculateNewMarginBasedOnOffsetFromEdge(double edgeOffset)
    {
    var innerFadedBorderBaseMarginThickness = this.FadedEdgeThickness / 2.0;
    var calculatedOffset = (innerFadedBorderBaseMarginThickness) - (1.5 * (this.FadedEdgeThickness - (edgeOffset / this.FadedEdgeFalloffSpeed)));

    return Math.Min(innerFadedBorderBaseMarginThickness, calculatedOffset);
    }



    private void FadingScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
    {
    if (this.OuterFadedBorder == null || this.InnerFadedBorder == null || this.InnerFadedBorderEffect == null)
    return;

    this.OuterFadedBorder.Width = e.NewSize.Width;
    this.OuterFadedBorder.Height = e.NewSize.Height;

    double innerFadedBorderBaseMarginThickness = this.FadedEdgeThickness / 2.0;
    this.InnerFadedBorder.Margin = new Thickness(innerFadedBorderBaseMarginThickness);
    this.InnerFadedBorderEffect.Radius = this.FadedEdgeThickness;
    }



    public override void OnApplyTemplate()
    {
    base.OnApplyTemplate();

    BuildInnerFadedBorderEffectForOpacityMask();
    BuildInnerFadedBorderForOpacityMask();
    BuildOuterFadedBorderForOpacityMask();
    SetOpacityMaskOfScrollContainer();
    }



    private void BuildInnerFadedBorderEffectForOpacityMask()
    {
    this.InnerFadedBorderEffect = new BlurEffect()
    {
    RenderingBias = RenderingBias.Performance,
    };
    }



    private void BuildInnerFadedBorderForOpacityMask()
    {
    this.InnerFadedBorder = new Border()
    {
    Background = Brushes.Black,
    HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
    VerticalAlignment = System.Windows.VerticalAlignment.Stretch,
    Effect = this.InnerFadedBorderEffect,
    };
    }



    private void BuildOuterFadedBorderForOpacityMask()
    {
    byte fadedEdgeByteOpacity = (byte)(this.FadedEdgeOpacity * 255);

    this.OuterFadedBorder = new Border()
    {
    Background = new SolidColorBrush(Color.FromArgb(fadedEdgeByteOpacity, 0, 0, 0)),
    ClipToBounds = true,
    Child = this.InnerFadedBorder,
    };
    }



    private void SetOpacityMaskOfScrollContainer()
    {
    var opacityMaskBrush = new VisualBrush()
    {
    Visual = this.OuterFadedBorder
    };

    var scrollContentPresentationContainer = this.Template.FindName(PART_SCROLL_PRESENTER_CONTAINER_NAME, this) as UIElement;

    if (scrollContentPresentationContainer == null)
    return;

    scrollContentPresentationContainer.OpacityMask = opacityMaskBrush;
    }
    }
    }

    这是使用控件的 XAML,对所需的默认 ScrollViewer 模板(它是 ScrollContentPresenter 周围的边框)进行了最少的更改。
    <local:FadingScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" Margin="10" FadedEdgeThickness="20" FadedEdgeOpacity="0" FadedEdgeFalloffSpeed="4">
    <local:FadingScrollViewer.Template>
    <ControlTemplate TargetType="{x:Type ScrollViewer}">
    <Grid x:Name="Grid" Background="{TemplateBinding Background}">
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <Border x:Name="PART_ScrollContentPresenterContainer">
    <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
    </Border>

    <ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
    <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
    </Grid>
    </ControlTemplate>
    </local:FadingScrollViewer.Template>


    <!-- Your content here -->

    </local:FadingScrollViewer>

    请注意 FadedScrollViewer 上的这些附加属性:FadedEdgeThickness、FadedEdgeOpacity 和 FadedEdgeFalloffSpeed
  • FadedEdgeThickness:您希望淡入淡出的厚度(以像素为单位)
  • FadedEdgeOpacity:您希望淡入淡出的最外边缘有多不透明。 0 = 边缘完全透明,1 = 边缘完全不褪色
  • FadedEdgeFalloffSpeed:控制渐变边缘在您靠近时消失的速度。值越高,淡出越慢。
  • 关于wpf - Scrollviewer 边缘模糊效果,opacitymask 无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1901709/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com