效果如何找出它所附加到的 UIImageView 的显示大小?



在Xamarin.Forms中,Effect可以附加到View。就我而言,视图显示Image。效果是在图像的可见像素周围产生彩色"发光"。XAML:

<Image Source="{Binding LogoImage}" ...>
<Image.Effects>
<effects:GlowEffect Radius="5" Color="White" />
</Image.Effects>
</Image>

效果实现为RoutingEffect的子类:

public class GlowEffect : Xamarin.Forms.RoutingEffect
{
public GlowEffect() : base("Core.ImageGlowEffect")
{
}
...
}

在每个平台上,都有一个实现效果的PlatformEffect。对于 iOS:

using ...
[assembly: ExportEffect(typeof(Core.Effects.ImageGlowEffect), "ImageGlowEffect")]
namespace Core.Effects
{
public class ImageGlowEffect : PlatformEffect
{
protected override void OnAttached()
{
ApplyGlow();
}
protected override void OnElementPropertyChanged( PropertyChangedEventArgs e )
{
base.OnElementPropertyChanged( e );
if (e.PropertyName == "Source") {
ApplyGlow();
}
}
private void ApplyGlow()
{
var imageView = Control as UIImageView;
if (imageView.Image == null)
return;
var effect = (GlowEffect)Element.Effects.FirstOrDefault(e => e is GlowEffect);
if (effect != null) {
CGRect outSize = AVFoundation.AVUtilities.WithAspectRatio( new CGRect( new CGPoint(), imageView.Image.Size ), imageView.Frame.Size );
...
}
}
...
}
}

如果动态更改Source,则上面的代码有效:在Source更改时,UIImageView(BoundsFrame(具有大小。但是,如果在 XAML 中静态设置源,则该逻辑不会运行:因此对ApplyGlow的唯一调用是在OnAttach期间。不幸的是,在OnAttach期间,UIImageView的大小(0, 0)

如何让这种效果在 iOS 上使用静态Source

注意:等效的 Android 效果通过附加到ImageView.ViewTreeObserver.PreDraw的处理程序工作 - 此时大小已知。因此,如果存在iOS等效事件,那将是一种解决方法。


更多详情:

原始
  • 实现使用原始图像大小(imageView.Image.Size( - 在OnAttach期间可用。这可以"工作",但并不令人满意:发光应用于全尺寸图像。如果图像明显大于视图区域,则发光的半径会变得太小(iOS 在渲染时缩小图像+发光(:它没有所需的外观。

  • ApplyGlow可以选择将色调应用于图像。该色调与发光颜色不同。我提到这一点是因为它限制了可能的解决方案:AFAIK,不能只在图像上设置选项并让 iOS 弄清楚如何渲染它 - 需要显式调整图像大小并在模糊版本(发光(上绘制调整大小的有色图像。这段代码都有效 -如果imageView.Bounds.Size(或imageView.Frame.Size(可用(且非零(。

  • 使用OnElementPropertyChanged中的断点,我已经检查了 imageView 大小是否已知对于始终设置的任何属性。不;如果未动态设置任何属性,则属性更改全部发生在 imageView 具有大小之前。

也许这是一种解决方法,我不知道您是否可以接受。

OnAttached中呼叫ApplyGlow();之前添加一点延迟。延迟后,您将获得imageView.Frame.SizeimageView.Bounds.Size

protected override async void OnAttached()
{
await Task.Delay(TimeSpan.FromSeconds(0.3));// it can be 0.2s,0.1s, depending on you
ApplyGlow();
}

如果您设置了WidthRequestHeightRequest,则可以毫不拖延地到达那里:

private void ApplyGlow()
{
var imageView = Control as UIImageView;
if (imageView.Image == null)
return;
Console.WriteLine(imageView.Image.Size.Width);
Console.WriteLine(imageView.Image.Size.Height);
CoreGraphics.CGSize rect = imageView.Bounds.Size;
CoreGraphics.CGSize rect2 = imageView.Frame.Size;
Console.WriteLine(rect);
Console.WriteLine(rect2);
double width = (double)Element.GetValue(VisualElement.WidthRequestProperty);
double height = (double)Element.GetValue(VisualElement.HeightRequestProperty);
Console.WriteLine(width);
Console.WriteLine(height);
double width2 = (double)Element.GetValue(VisualElement.WidthProperty);
double height2 = (double)Element.GetValue(VisualElement.HeightProperty);
Console.WriteLine(width2);
Console.WriteLine(height2);
}

最新更新