Im trying to get an image to be animated the moment the page is loaded but my approach doesnt seem to work on startup. But i have tested it with a button and it plays the animation no bother.
This is my constructor for my MainPage
public MainPage()
{
InitializeComponent();
CreatePanel();
var storyboard = new Animation();
var enterTop = new Animation
(
callback: d => bannerIcon.TranslationY = d,
start: -100,
end: 0,
easing: Easing.BounceOut
);
storyboard.Add(0, 1, enterTop);
storyboard.Commit(bannerIcon, "Banner", length: 1000);
Content = layout;
}
Should I have this code in the OnAppearing method or am I just coming at this completely wrong?
SOLUTION
Just had to move the animation code into the OnAppearing() method.
protected override void OnAppearing()
{
base.OnAppearing();
banner.IsVisible = false;
// animations
menuAnimations.FlyIn(banner, 1000);
menuAnimations.Rotate(btnSocial, 360);
menuAnimations.Rotate(btnVideo, 360);
menuAnimations.Rotate(btnSchedule, 360);
menuAnimations.Rotate(btnLunchMenu, 360);
menuAnimations.Rotate(btnContact, 360);
menuAnimations.Rotate(btnDetails, 360);
}
Your running the animation before you Content is even set (Possible Animation is finished before you can even view it which help with argument of the animation working on button click I would also do as you suggested and move the animation.commit inside the OnAppearing method and set the animation to a longer length for testing purposes
Related
I'm trying to make an animation for my page. I want that animation to get fired only when the page is first loaded.
My animation code is working, sample:
public async Task BackgroundFlyUp()
{
var destinationRect = new Rectangle(0, Application.Current.MainPage.Height * (1 - FoodViewsConstants.FLY_UP_END),
Application.Current.MainPage.Width, Application.Current.MainPage.Height * FoodViewsConstants.FLY_UP_END);
await FlyUp.LayoutTo(destinationRect, FoodViewsConstants.FLY_UP_SPEED, Easing.Linear);
await ContentGrid.FadeTo(1, FoodViewsConstants.CONTENT_FADE_SPEED);
}
Although I don't want my animation to get fired every time OnAppearing is fired, I've tried to add the animation code in my OnAppearing method but it doesn't work right. (the fade is working but the FlyUp not) and being an async method, it can't be placed in the constructor. Can you guys help me out?
Based on my test, I guess you do not get the correct from destinationRect. The Application.Current.MainPage.Width and Application.Current.MainPage.Height would get the width and height except on initial load when the MainPage hadn't been presented yet.
You could use the screen size instead.
public async Task BackgroundFlyUp()
{
// Get Metrics
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
// Width (in pixels)
var width = mainDisplayInfo.Width;
// Height (in pixels)
var height = mainDisplayInfo.Height;
var destinationRect = new Rectangle(0, height * (1 - FoodViewsConstants.FLY_UP_END),
width, height * FoodViewsConstants.FLY_UP_END);
await FlyUp.LayoutTo(destinationRect, 5000, Easing.Linear);
await ContentGrid.FadeTo(1, FoodViewsConstants.CONTENT_FADE_SPEED);
}
I need to be able to do some direct drawing in Xamarin Forms. Is there a control equivelent to a canvas? I saw somewhere that maybe the AbsoluteLayout was, but I need something that I can, for example, execute a DrawString or DrawArc on. Does such a thing exist, or do you have to create a custom control?
Try with SkiaSharp, it basically allows you to do more or less the same than you can do in the native canvas of Android.
To use it:
Add the NuGet package SkiaSharp.Views.Forms to your projects.
Add the Skia namespace to your page or layout:
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
Add the Skia canvas view, defining the name of the callback method that will be used to draw on it from the code behind:
<skia:SKCanvasView
x:Name="CanvasView"
PaintSurface="OnCanvasViewPaintSurface"/>
Draw whatever you want:
private void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
var info = args.Info;
var surface = args.Surface;
var canvas = surface.Canvas;
canvas.Clear();
// In this example, we will draw a circle in the middle of the canvas
var paint = new SKPaint
{
Style = SKPaintStyle.Fill,
Color = Color.Red.ToSKColor(), // Alternatively: SKColors.Red
};
canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, paint);
}
I have used Animation() method to make my view with the animation of scaling and Rotation. With the Rotation based on the Y axis, the default height and width of my view has been changed. It looks like the parallelogram.
rotation of rectangle along y-axis transformed to a parallelogram.
myview.Animate().RotationY(rotationangle)
.X(xposition)
.SetDuration(mduration)
.WithLayer()
.SetInterpolator(interpolate).Start();
My requirement:
I just want the rotation of my view no need to change its projection. How to restrict the rotation of rectangle along y-axis transformed to a parallelogram.
For more reference, please check the attached sample
now view be like,
Image
Please share your idea.
Thanks in Advance.
Note: while using PivotX and PivotY, there is no parallelogram shape. But I don't know the exact usage of that.
Regards,
Hemalatha Marikumar
is that not what are you looking for ?
it may work if you put this code in your current activity
Android: Temporarily disable orientation changes in an Activity
Do you want to create a 2D rotation?
You could try to use ScaleAnimation to rotate the view. If you want to rotate 360 degrees, you could use AnimationListener.
For example:
Button myview = (Button)FindViewById(Resource.Id.button2);
ScaleAnimation scaleAnimation = new ScaleAnimation(1, 0, 1, 1,
Android.Views.Animations.Dimension.RelativeToParent, 0.5f, Android.Views.Animations.Dimension.RelativeToParent, 0.5f);
ScaleAnimation scaleAnimation2 = new ScaleAnimation(0, 1, 1, 1,
Android.Views.Animations.Dimension.RelativeToParent, 0.5f, Android.Views.Animations.Dimension.RelativeToParent, 0.5f);
scaleAnimation.Duration = 4000;
scaleAnimation.SetAnimationListener(new AnimationListener(myview, scaleAnimation2));
scaleAnimation2.Duration = 4000;
myview.StartAnimation(scaleAnimation);
The Listener:
public class AnimationListener :Java.Lang.Object, IAnimationListener
{
View view;
Animation animation2;
public AnimationListener(View view, Animation animation)
{
this.view = view;
this.animation2 = animation;
}
public void OnAnimationEnd(Animation animation)
{
view.StartAnimation(animation2);
}
public void OnAnimationRepeat(Animation animation)
{
}
public void OnAnimationStart(Animation animation)
{
}
}
I have the following CustomRenderer to apply a style to buttons in my iOS project of my cross-platform Xamarin.Forms app.
The button used to have rounded edges, white text, and a blue gradient background.
Everything has been working just fine up until I downloaded Xcode 8.1. Since moving to 8.1, the same code will not present the background gradient. Can anyone see how I could change my code to get the background gradient working again?
The border radius and text color are all working as usual - it's just the background gradient which is missing.
[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
namespace MyApp.Forms.iOS.CustomRenderers
{
class CustomButtonRenderer : ButtonRenderer
{
public override void LayoutSubviews()
{
foreach (var layer in Control?.Layer.Sublayers.Where(layer => layer is CAGradientLayer))
{
layer.Frame = Control.Bounds;
}
base.LayoutSubviews();
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var gradient = new CAGradientLayer();
gradient.CornerRadius = Control.Layer.CornerRadius = 10;
gradient.Colors = new CGColor[]
{
UIColor.FromRGB(153, 204, 255).CGColor,
UIColor.FromRGB(51, 102, 204).CGColor
};
var layer = Control?.Layer.Sublayers.LastOrDefault();
Control?.Layer.InsertSublayerBelow(gradient, layer);
Control.SetTitleColor(UIColor.White, UIControlState.Normal);
Control.Layer.BorderColor = UIColor.FromRGB(51, 102, 204).CGColor;
Control.Layer.BorderWidth = 1;
}
}
}
}
Ok so I have finally worked out what was going on. In the LayoutSubviews method where I was setting each layer.Frame to the value of Control.Bounds, I noticed that Control.Bounds was a rectangle full of zeros, so my gradient was therefore 0 pixels in size.
I have modified the method as follows and it now works as expected again:
public override void LayoutSubviews()
{
var newBounds = Element.Bounds.ToRectangleF();
foreach (var layer in Control?.Layer.Sublayers.Where(layer => layer is CAGradientLayer))
{
layer.Frame = new CGRect(0, 0, newBounds.Width, newBounds.Height);
}
base.LayoutSubviews();
}
I'm not sure if this is a hack, but it seems to do the job - for now...
Is there no possibility to read and set the position of the scrollview? For example, I would like to start the app with the scroll position at the bottom, not at the top.
You can get the X and Y position of a ScrollView from the ScrollX and ScrollY properties of the ScrollView object. Then you can set the position with the ScrollView method ScrollToAsync.
var x = scrollView.ScrollX;
var y = scrollView.ScrollY;
...
bool animate = false;
scrollView.ScrollToAsync(x, y, animate);
I've a better approach to this!
You can add this to your onAppearing() method:
protected override void OnAppearing()
{
base.OnAppearing();
/*Other stuff*/
viewModel.Messages.CollectionChanged += (sender, e) =>
{
var target = viewModel.Messages[viewModel.Messages.Count - 1];
ItemsListView.ScrollTo(target, ScrollToPosition.End, false);
};
}
This means that if your collection change, you get the target which is the last item (the one in the bottom) the you use scrollTo target, position end, with animation false.
when you get to the page it will open in the bottom, you don't see the scrolling because animation is false!
For Android, I have found a solution:
I write a custom renderer and in the OnDraw override Method, I call FullScroll(FocusSearchDirection.Down) the first time when the method is called.
What it makes easy, the Android ScrollViewRenderer is subtype of Android.Widget.ScrollView.
At the moment, I don't need an implementation for iOS, so I have no solution for iOS.