Я пытаюсь сделать то, что, по моему мнению, будет хорошим эффектом для приложения - серия изображений (думаю, обои) будет постоянно прокручиваться на заднем плане во время просмотра. Я начал создавать прототипы в Xamarin.Forms, создавая собственный элемент управления. Запланировано по диагональному переводу, но началось с самого простого подхода и все же довольно быстро столкнулось с некоторыми проблемами, а именно, что оно не совсем гладкое, так как оно становится немного прерывистым здесь и там (даже при использовании кэширования и всего лишь 10-килобайтного изображения) и 2 ) если пользователь выполняет более сложное действие, это может привести к задержке, и изображения будут отображаться ближе друг к другу, чем следовало бы. Есть ли способ исправить этот подход так, чтобы он был как можно более плавным и не мешал (или не мешал) другим элементам пользовательского интерфейса, или есть куда более превосходный подход для чего-то подобного - кто-нибудь когда-нибудь занимался этим? Пожалуйста, дайте мне знать, спасибо.
FlyingImageBackground.cs
public class FlyingImageBackground : ContentView
{
public static readonly BindableProperty FlyingImageProperty =
BindableProperty.Create(nameof(FlyingImage), typeof(ImageSource), typeof(FlyingImageBackground), default(ImageSource), BindingMode.TwoWay, propertyChanged: OnFlyingImageChanged);
public ImageSource FlyingImage
{
get => (ImageSource)GetValue(FlyingImageProperty);
set => SetValue(FlyingImageProperty, value);
}
private AbsoluteLayout canvas;
public FlyingImageBackground()
{
this.canvas = new AbsoluteLayout()
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
this.canvas.SizeChanged += Canvas_SizeChanged;
Content = this.canvas;
}
~FlyingImageBackground() => this.canvas.SizeChanged -= Canvas_SizeChanged;
private static void OnFlyingImageChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (FlyingImageBackground)bindable;
control.BringToLife();
}
private void BringToLife()
{
if (this.canvas.Width <= 0 || this.canvas.Height <= 0)
return;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
Device.BeginInvokeOnMainThread(async () =>
{
await SendImageWave();
});
return this.canvas.IsVisible;
});
}
private async Task SendImageWave()
{
var startingX = -100;
var endingX = this.canvas.Width;
if (endingX <= 0)
return;
endingX += 100;
var yPositions = Enumerable.Range(0, (int)this.canvas.Height).Where(x => x % 90 == 0).ToList();
var imgList = new List<CachedImage>();
foreach (var yPos in yPositions)
{
var img = new CachedImage
{
Source = FlyingImage,
HeightRequest = 50
};
imgList.Add(img);
this.canvas.Children.Add(img, new Point(startingX, yPos));
}
await Task.WhenAll(
imgList.Select(x => x.TranslateTo(endingX, 0, 10000)));
//.Concat(imgList.Select(x => x.TranslateTo(startingX, 0, uint.MinValue))));
imgList.ForEach(x =>
{
this.canvas.Children.Remove(x);
x = null;
});
imgList = null;
}
private void Canvas_SizeChanged(object sender, EventArgs e)
{
BringToLife();
}
}
Пример использования:
Просто поместите его в таблицу в ContentPage вместе с основным содержимым:
e.g.:
<ContentPage.Content>
<Grid>
<controls:FlyingImageBackground FlyingImage="fireTruck.png" />
<StackLayout HorizontalOptions="Center">
<Button
Text="I'm a button!" />
<Label
FontAttributes="Bold,Italic"
Text="You're a good man, old sport!!!"
TextDecorations="Underline" />
</StackLayout>
</Grid>
</ContentPage.Content>