Xamarin GIF animation - xamarin

I just started developing Xamarin
But I encountered a problem
I have a login screen and I want to play gif there
but unfortunately no images are coming
Works well for png and jpeg files
my code is below;
Content = new StackLayout
{
Padding = new Thickness(10, 40, 10, 10),
Children = {
new Label { Text = "Versiyon:"+DependencyService.Get<INativeCall>().getApplicationVersion(), FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), TextColor = Color.White, HorizontalTextAlignment=TextAlignment.Center },
new Image { Source = "a.gif" },
username,
password,
btnLogin,
indicator,
infoServer,
infoUpdate
}
};

By default, when an animated GIF is loaded it will not be played. This is because the IsAnimationPlaying property, that controls whether an animated GIF is playing or stopped, has a default value of false. This property, of type bool, is backed by a BindableProperty object, which means that it can be the target of a data binding, and styled.
Therefore, when an animated GIF is loaded it will not be played until the IsAnimationPlaying property is set to true.
Modify code of Image as bellow :
new Image { Source = "a.jpg", IsAnimationPlaying = true}
For example , this is my gif file :
Xaml code :
<Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="Start" />
<Image Source="timg.gif" IsAnimationPlaying="True"/>
The effect :

Please use the nuget package - Xamarin.FFImageLoading.It processes GIFs quickly.
eg XAML -
<ffimageloading:SvgCachedImage Grid.Row="3" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Source="celebrate.gif" />

Related

How to make ActivityIndicator overlay full screen?

I have a StackLayout and a number of elements inside (buttons, texts etc).
I want the ActivityIndicator to overlay the entire screen and make it not able to do anything to those elements.
I have put ActivityIndicator inside the StackLayout but wrapped it with AbsoluteLayout thinking that AbsoluteLayout can easitly overlap everything:
<StackLayout>
<AbsoluteLayout>
<ActivityIndicator ... />
</AbsoluteLayout>
<...other elements...>
</StackLayout>
Instead activity indicator is displayed at the top of the StackLayout and other elements are available for affecting. I'm new in Xamarin and layouts, what am I doing wrong? All samples in the Internet have single ActivityIndicator per page...
It is better said that an AbsoluteLayout's children can easily overlap each other. Just as a StackLayout lets you stack controls inside , vertically or horizontally, an AbsoluteLayout lets you position controls inside using absolute or proportional values, thus if two controls have the same absolute positioning set, they will overlap 100%.
Therefore, you want to wrap your StackLayout and another StackLayout that has your ActivityIndicator inside an AbsoluteLayout using proportional sizing, e.g:
<AbsoluteLayout>
<StackLayout
x:Name="mainLayout"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All" >
<Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Do Something"
Clicked="DoSomethingBtn_Clicked" />
</StackLayout>
<StackLayout
x:Name="aiLayout"
IsVisible="False"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Gray" Opacity="0.5">
<ActivityIndicator
x:Name="ai"
IsRunning="False"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Color="Black"/>
</StackLayout>
</AbsoluteLayout>
The above sets the two StackLayouts to both take up the full size of the parent container of the AbsoluteLayout, which is presumably a Page. The StackLayout that has the indicator is initially hidden. IN the page code behind for the above example, I show the second StackLayout and start the activity indicator and show it for 2 seconds, and then hide it again:
private async void DoSomethingBtn_Clicked(object sender, EventArgs e)
{
ai.IsRunning = true;
aiLayout.IsVisible = true;
await Task.Delay(2000);
aiLayout.IsVisible = false;
ai.IsRunning = false;
}
Here is what it looks like:
And since the second StackLayout completely covers the first, none of the controls in the first StackLayout are clickable.
Might be worth going over the docs for the AbsoluteLayout to understand the AbsoluteLayout.LayoutBounds and AbsoluteLayout.LayoutFlags:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/absolute-layout
If you want to "overlap", you need to be outside of the StackLayout. A Grid is the most common control for this:
<Grid>
<StackLayout>
<...other elements...>
</StackLayout>
<ActivityIndicator ... />
</Grid>
Here's a hacked-up control for making things full-screen via the horribly-named RelativeLayout (tested in Android only)
[ContentProperty("ContentInner")]
public class FullScreenLayout : ContentView
{
public View ContentInner
{
get => ((RelativeLayout) Content).Children[0];
set
{
var display = DeviceDisplay.MainDisplayInfo;
var screenWidth = display.Width / display.Density;
var screenHeight = display.Height / display.Density;
var wrapper = new RelativeLayout();
wrapper.Children.Add(value, () => new Rectangle(0, 0, screenWidth, screenHeight));
Content = wrapper;
}
}
}
It can be used like this:
<controls:FullScreenLayout>
<!-- Anything you want fullscreen here -->
</controls:FullScreenLayout>
Unfortunately, if you use NavigationPage, this won't overlap the navigation bar. Every other solution currently on this page has the same issue. According to this question, it's not possible to solve this without using platform-specific customer renderers. Ugh.
If you don't mind the page being dimmed, you can use Rg.Plugins.Popup which implements the custom renderers needed.
I ended up solving my similar problem (dimming most of the screen) by implementing a custom renderer for the navigation page itself.

Xamarin Forms - Frame change after update Xamarin Forms version

I used to use the Frame control of Xamarin.Forms as a CardView for Android, but I updated the Xamarin.Forms package to version 3.1.0 and the frame appearence has changed. It doesn't have elevation and shadows. I tried to create a custom renderer, but doesn't work.
To explain what I'm trying to say, see the pictures below. First picture is the old behaviour of frame. The appearence is exactly like CardView in Android and the second picture is the new behaviour, for the version 3.1.0 of Xamarin.Forms. The frame doesn't have elevation and shadows.
Old behaviour:
New behaviour
Here is my code that I use the Frame (for Android Platform, CardView is a simple frame)
<customViews:CardView>
<StackLayout Spacing="0">
<StackLayout.Margin>
<OnPlatform x:TypeArguments="Thickness" Android="16"/>
</StackLayout.Margin>
<ContentView>
<OnPlatform x:TypeArguments="View">
<OnPlatform.iOS>
<customViews:HeaderDivider/>
</OnPlatform.iOS>
</OnPlatform>
</ContentView>
public class CardView : Frame
{
public CardView()
{
Padding = 0;
if (Device.RuntimePlatform == Device.iOS)
{
HasShadow = false;
OutlineColor = Color.Transparent;
BackgroundColor = Color.Transparent;
}
}
}
<Frame HasShadow="true">
<Label Text="Test"/
</Frame>
I guess after Update default value for HasShadow in Frame is set to false;

Xamarin forms background image not working

I am working on Xamarin forms, cross platform app (Android and iOS). I wanted to have background image for login form.
I set it on constructor of form and code is :
this.BackgroundImage = ImageSource.FromResource("PCLProjectName.Images.Login.loginbackground.png").ToString();
And Image is in PCL project and I have set its action property as Embedded resource.
PCL project folder hierarchy as as below
Root
- Images
- Login
-loginbackground.png
Image is not displaying
If you want to add background image in XAML file for the entire page in Xamarin project, then use the BackgroundImage property and add your image to the Android project under Resources -> drawable folder and for iOS Resources folder.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PhoneDailerDemo"
x:Class="PhoneDailerDemo.MainPage"
BackgroundImage="image3.jpg">
<Label Text="Welcome to Xamarin Forms!"
VerticalOptions="Center"
HorizontalOptions="Center" />
<StackLayout Padding="100">
//..........
</StackLayout>
</ContentPage>
For images to work, they must be placed in different folders in iOS and android. Subfolders or custom file structures cannot be used to my knowledge.
For Android devices, images must be in the Android project under Android>Resources>Drawable. Build action set to Android Resource (this folder should already exist)
For iOS devices, images must be in the iOS project folder iOS>Resources. Build Action set to Bundle Resource (This folder should also already exist)
With the images in the respective folders, you can set the image like so..
this.BackgroundImage = ImageSource.FromFile("loginbackground.png")
edit: To continue with your PCL Embedded Resource approach..
You can run this piece of code somewhere to see that the images are detected correctly in the resources. I know from experience there are some weird file naming issues (though I don't see any I've encountered in your example)
var assembly = typeof(EmbeddedImages).GetTypeInfo().Assembly;
foreach (var res in assembly.GetManifestResourceNames())
System.Diagnostics.Debug.WriteLine("found resource: " + res);
Xamarin does not allow you to use an image from external storage or Url as background image of ContentPage.
so instead of setting a BackgroundImage ="image_name_in_resources" inside the root tag of page ( ContentPage ) , put it in an Image tag neighboring you inside code , both inside an AbsoluteLayout
here's a snippet of my Code
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
.....
.....>
<AbsoluteLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Image x:Name="imageBG" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" Aspect="AspectFill" Source="myimage.jpg" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/>
<StackLayout AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="All" >
....
</StackLayout>
</AbsoluteLayout>
to change the source prof CS code here's a little snippet i worked with
string serverAdress = Constants.HTTP_PRE + Constants.SERVER_IP;
Logo.Source = new UriImageSource
{
Uri = new Uri(serverAdress + Constants.HEADER_IMAGE),
CachingEnabled = true
};
For more controle over whether the server response is valid ...
try
{
string url = Constants.HTTP_PRE + DependencyService.Get<IStoredData>().GetData(Constants.SHARED_PREF_ADDRESS);
url += Constants.HEADER_IMAGE;
HttpWebRequest wrq = (HttpWebRequest)WebRequest.Create(url);
//You should be getting only the response header
wrq.Method = "HEAD";
if ( ( (HttpWebResponse)wrq.GetResponse() ).ContentLength > 0) // if filePath is correct - serverIP is set
{
Uri uri = new Uri(url);
UriImageSource uriImageSource = new UriImageSource { Uri = uri, CachingEnabled = true };
Logo.Source = uriImageSource;
}
}catch (Exception e) { System.Console.WriteLine(e.StackTrace); }

Xamarin Forms InputTransparent doesn't work on Android

Here is my xaml. InputTransparent is set to true, but Entry still catches the input.
<Grid>
<DatePicker
Date="{Binding FundraiserEndDate}" />
<Entry
Text="{Binding FundraiserEndDateText}"
TextColor="Gray"
FontSize="13"
HorizontalTextAlignment="Center"
InputTransparent="True" />
</Grid>
Found a couple of bug reports about this, and it seems more universal than just with an Entry and DatePicker in a Grid.
See:
https://bugzilla.xamarin.com/show_bug.cgi?id=50992
https://bugzilla.xamarin.com/show_bug.cgi?id=50362
I added the info from this question to the reports to let them know that it seems more universal than just the specific scenarios noted in the above bug reports.
I had the same prob (InputTransparent not working issue is still actual)
I wanted to avoid user inputs in a custom hydrated form object w/o having to handle disabled inputs rendering (example of a switch disabled which is grey even if toogled).
For that I simply used a grid as example with a stackLayout on top of it so user cannot interact with all my form (entry, switches and so) :
grid.Children.Add(form.MainLayout);
//Trick to avoid user inputs
grid.Children.Add(new StackLayout { BackgroundColor = Color.Transparent, VerticalOptions = LayoutOptions.FillAndExpand, HorizontalOptions = LayoutOptions.FillAndExpand });
scrollView.Content = grid;
Content = scrollView;

Xamarin Forms button with loading indicator

I'm into Xamarin since about week and have a question about the possibility of making loading icon inside a button.
I would like to achieve something similiar to this:
https://jsfiddle.net/mr8fwtcv/
I was trying to achieve this effect with FontAwesome but had a problem animating it, so it would be not bad to use Activity Indicator in the solution.
My button is placed inside Stack Layout, and here is the code:
var loginButton = new Button
{
BackgroundColor = Color.FromHex("689F38"),
TextColor = Color.White,
HeightRequest = 46,
Text = "Log in",
FontAttributes = FontAttributes.Bold,
FontSize = 18,
Margin = margin
};
I was already looking for some plugins / solutions but couldn't find any.
Thanks in advance.
You will have to use a Layout to have more than one control in it. If you are not looking for CustomRenderers then what you could do is have a RelativeLayout and inside that both the Button and the Activity Indicator. You will also have to write a Converter for the button text that will set the text to string.Empty when the IsBusy is true.
For example:
<StackLayout>
<ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}" />
<Button Text="{Binding ButtonText, Converter={StaticResource ButtonTextConverter}, ConverterParameter={Binding IsBusy}}" />
</StackLayout>
Also if you are planning to use this in multiple places you can create this as a custom control.
You can check out the custom control code here.
The full project is available here.

Resources