在 Xamarin.Forms 中,一个 Effect
可以附加到 View
。在我的例子中, 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
(Bounds
或 Frame
) 有一个尺寸。但是,如果在 XAML 中静态设置源,则该逻辑不会运行:因此对 ApplyGlow
的唯一调用是在 OnAttach
期间。不幸的是,在 OnAttach
期间,UIImageView
的大小为 (0, 0)
。
如何使用静态 Source
在 iOS 上实现这种效果?
注意:等效的 Android 效果通过附加到 ImageView.ViewTreeObserver.PreDraw
的处理程序工作 - 此时大小已知。因此,如果有 iOS 等效事件,那将是一种解决方法。
更多详情:
原始实现使用原始图像大小 (imageView.Image.Size) - 这在
OnAttach
期间可用。这可以“工作”,但并不令人满意:发光应用于全尺寸图像。如果图像明显大于 View 区域,发光的半径会变得太小(iOS 在渲染时缩小图像 + 发光):它没有所需的外观。ApplyGlow
有一个选项可以将色调颜色应用到图像。该色调颜色不同于发光颜色。我提到这个是因为它限制了可能的解决方案:AFAIK,不能只在图像上设置选项并让 iOS 弄清楚如何渲染它 - 需要明确调整图像大小并在模糊版本的顶部绘制调整大小的着色图像(光辉)。此代码全部有效 - ifimageView.Bounds.Size
(或imageView.Frame.Size
)可用(且非零)。通过
OnElementPropertyChanged
中的断点,我检查了 imageView 大小是否已知任何始终设置的属性。不;如果没有动态设置属性,则属性更改全部发生在 imageView 具有大小之前。
最佳答案
也许这是一种解决方法,我不知道您是否可以接受。
在 OnAttached
中调用 ApplyGlow();
之前添加一点延迟。延迟后,您将获得 imageView.Frame.Size
或 imageView.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();
}
如果你设置了WidthRequest
, HeightRequest
,你可以毫不拖延地到达那里:
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);
}
关于ios - 效果如何找出它所附加的 UIImageView 的显示大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59759475/