Unable to play GIF image in Xamarin.Forms (Portable) - android

I am trying to play the GIF images with the Xamarin.Forms (Portable) project. I have implemented with the following code but unable to Play GIF, I don't event see the static image.
There is no error or crash in this code, but I am not able to see the
GIF image.
Is there anything wrong in the code?
Interface:
public interface IGif
{
string Get();
}
iOS Implementation:
[assembly: Dependency(typeof(GifView_iOS))]
namespace Project.iOS
{
public class GifView_iOS : IGif
{
public string Get()
{
return NSBundle.MainBundle.BundlePath;
}
}
}
Android Implementation:
[assembly: Dependency(typeof(GifView_Droid))]
namespace Project.Droid
{
public class GifView_Droid : IGif
{
public string Get()
{
return "file:///android_asset/";
}
}
}
GIF Image class:
public class Gif: WebView
{
public string GifSource
{
set
{
string imgSource = DependencyService.Get<IGif>.Get() + value;
var html = new HtmlWebViewSource();
html.Html = String.Format
(#"<html><body style='background: #000000;'><img src='{0}' /></body></html>",
imgSource);
SetValue(SourceProperty, html);
}
}
}
And Finally, I have added to the StackLayout.
Gif gifimage = new Gif();
gifimage.GifSource = "loading.gif";
StackGif.Children.Add(gifimage);
I have not tested this code in iPhone, maybe it is working in iPhone.
Thank You in advance.

This was the silly mistake, I have to give the size of Image inside web view and to GIF class also.
Here is the updated code.
My GIF Class:
public class Gif: WebView
{
public string GifSource
{
set
{
string imgSource = DependencyService.Get<Dependency.IGif>().Get() + value;
var html = new HtmlWebViewSource();
html.Html = String.Format(#"<html><body><img src='{0}' style='width: 100px; height: 100px;' /></body></html>", imgSource);
SetValue(SourceProperty, html);
}
}
}
and Initialization in ContentPage:
Helpers.Controls.Gif gifImage = new Helpers.Controls.Gif();
gifImage.GifSource = "loading.gif";
gifImage.HorizontalOptions = LayoutOptions.Center;
gifImage.VerticalOptions = LayoutOptions.FillAndExpand;
gifImage.HeightRequest = 120;
gifImage.BackgroundColor = Color.Transparent;
GridLoad.Children.Add(gifImage);
Note: I am still working on the Background Part, as it is looking like
attached image, I want the transparent background in web view.
Image:

By default StackLayout occupies the whole available space but WebView doesn't.
Instead just
Gif gifimage = new Gif();
use
public WebViewProgrammaticallyPage()
{
var StackGif = new StackLayout()
{
BackgroundColor=Color.Red,
};
Gif gifimage = new Gif()
{
WidthRequest = 120,
HorizontalOptions = LayoutOptions.CenterAndExpand,
HeightRequest = 80,
VerticalOptions = LayoutOptions.CenterAndExpand,
};
gifimage.GifSource = "icon1.png";
StackGif.Children.Add(gifimage);
Content = StackGif;
}
Transparency of WebView is different problem. You should use custom renderers
https://forums.xamarin.com/discussion/34957/creating-a-webview-with-a-transparent-background

Related

Syncfusion SfAutoComplete for Android Xamarin rendering is nearly invisible on Hyper V Emulator

I am successfully using Xamarin Forms, however I decided to try Syncfusion but I cannot get the SfAutoComplete component (or probably any other) to show correctly, very very tiny rendering as per the screenshot, if you can see it! I have added the Android and PCL references as per the docs and my PCL sample code is shown. I also created a new project to ensure any rendering I added was not the cause. I am at a loss!
using Syncfusion.SfAutoComplete.XForms;
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace Greetings
{
public partial class Page1 : ContentPage
{
public Page1()
{
InitializeComponent();
ShowPage();
}
public void ShowPage()
{
SfAutoComplete countryAutoComplete = new SfAutoComplete();
List<String> countryName = new List<String>();
countryName.Add("Uganda");
countryName.Add("Ukraine");
countryName.Add("United Arab Emirates");
countryName.Add("United Kingdom");
countryName.Add("United States");
countryAutoComplete.AutoCompleteSource = countryName;
this.Content = countryAutoComplete;
}
}
}
This is silly, the text is so small it cannot be read. I used TextSize="40" and all is well. C# for completeness
countryAutoComplete.TextSize = 40;
You have added AutoComplete directly inside content page so that it takes full screen as its size. This is the reason for improper control rendering.Add countryAutoComplete in anyone of the layout/grid and try to set TextSize for countryAutoComplete.
public partial class Page1 : ContentPage
{
public Page1()
{
InitializeComponent();
ShowPage();
}
public void ShowPage()
{
SfAutoComplete countryAutoComplete = new SfAutoComplete();
List<string> countryName = new List<string>();
countryName.Add("Uganda");
countryName.Add("Ukraine");
countryName.Add("United Arab Emirates");
countryName.Add("United Kingdom");
countryName.Add("United States");
countryAutoComplete.AutoCompleteSource = countryName;
countryAutoComplete.TextSize = 20;
StackLayout stack = new StackLayout();
stack.Padding = new Thickness(50,100,50,100);
stack.Children.Add(countryAutoComplete);
this.Content = stack;
}
}
The TextSize property of AutoComplete is works well. Here I have attached the screenshots of AutoComplete when TextSize is 20 in another one TextSize is 40.
TextSize is 20 - https://i.stack.imgur.com/euNIg.png
TextSize is 40 - https://i.stack.imgur.com/zPbl9.png

Video Player In Xamarin Forms Throws System.InvalidOperationException: Sequence contains no matching element

Im making an app for iOS and android that offers the ability to watch video's. Im currently working on the iOS implementation but each time I dismiss the viewcontroller holding an AVPlayer or MPPlayer the app throws 'System.InvalidOperationException: Sequence contains no matching element'. I have no idea why this happens. Ill share some example code.
Renderer
using AnimeViewer.iOS.CustomRenderers;
using AnimeViewer.Views.Partials;
using AVFoundation;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(VideoPlayer), typeof(VideoPlayerRenderer))]
namespace AnimeViewer.iOS.CustomRenderers
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
public VideoPlayer VideoPlayer { get; set; }
protected override void OnElementChanged(ElementChangedEventArgs<VideoPlayer> e)
{
base.OnElementChanged(e);
if (e.NewElement == null) return;
VideoPlayer = e.NewElement;
SetNativeControl(new UIView {Frame = UIScreen.MainScreen.Bounds});
var player = new AVPlayer(new NSUrl(VideoPlayer.Source));
var playerLayer = new AVPlayerLayer
{
Player = player,
Frame = Control.Frame
};
Control.Layer.AddSublayer(playerLayer);
player.Play();
}
}
}
View
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:partials="clr-namespace:AnimeViewer.Views.Partials;assembly=AnimeViewer"
x:Class="AnimeViewer.Views.VideoPlayerPage">
<partials:VideoPlayer x:Name="Player"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
</ContentPage>
You don't need a custom renderer to call the video player, you can use a DependencyService:
public class VideoPLayer : IVideoPlayer
{
public void Play(string path)
{
var _player = new AVPlayer(NSUrl.FromFilename(path));
var _playerController = new AVPlayerViewController();
_playerController.Player = _player;
var window = UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
{
vc = vc.PresentedViewController;
}
vc.PresentViewController(_playerController, true, null);
_playerController.View.Frame = vc.View.Frame;
}
}
To learn more about DependencyService you can access the following link: https://developer.xamarin.com/guides/xamarin-forms/dependency-service/

Inline CSS for hr not applied while converting html to pdf using iText library

I am using Itext library for android for converting html to pdf which is working fine but at certain things it is not parsing properly. I want to create a dotted line separator of red color but it is always gives me a solid line separator with dark gray color.
My html tag is
<hr noshade style="border: 0; width:100%;border-bottom-width: 1px; border-bottom-style: dotted; border-bottom-color: red">
My conversion code
Document document = new Document(PageSize.A4);
//this sets the margin to the created pdf
document.setMargins(35, 35, 150, 100);
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream(fileWithinMyDir));
if (isPrescription) {
HeaderFooterPageEvent event = new HeaderFooterPageEvent();
writer.setPageEvent(event);
} else {
CertificateFooterPageEvent event = new CertificateFooterPageEvent();
writer.setPageEvent(event);
}
document.open();
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
htmlContext.setImageProvider(new AbstractImageProvider() {
public String getImageRootPath() {
Uri uri = Uri.parse("file:///android_asset/");
return uri.toString();
}
});
CSSResolver cssResolver =
XMLWorkerHelper.getInstance().getDefaultCssResolver(false);
// Pipelines
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
InputStream is = new ByteArrayInputStream(htmlString.getBytes());
XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);
p.parse(is);
document.close();
I'm a .NET developer, so the code is in C#. But you should be able to easily translate the following.
iText is a PDF-first library, and [X]HTML parsing is quite complex so it's not full featured in that regard. Whenever parsing [X]HTML and things aren't going the way you expect for specific tags, the basic steps you should follow are:
Verify XML Worker supports the tag: Tags class.
If the tag is supported, which in this case is true, take a look at the default implementation. Here it's handled by the the HorizontalRule class. However, we see there's no support for your use case, so one way to go is use that code as a blueprint. (follows below) You can also inherit from the specific tag class and override the End() method as done here. Either way, all you're doing is implementing a custom tag processor.
If the tag is not supported, you need to roll your own custom tag processor by inheriting from AbstractTagProcessor.
Anyway, here's a simple example to get you started. First, the custom tag processor:
public class CustomHorizontalRule : AbstractTagProcessor
{
public override IList<IElement> Start(IWorkerContext ctx, Tag tag)
{
IList<IElement> result;
LineSeparator lineSeparator;
var cssUtil = CssUtils.GetInstance();
try
{
IList<IElement> list = new List<IElement>();
HtmlPipelineContext htmlPipelineContext = this.GetHtmlPipelineContext(ctx);
Paragraph paragraph = new Paragraph();
IDictionary<string, string> css = tag.CSS;
float baseValue = 12f;
if (css.ContainsKey("font-size"))
{
baseValue = cssUtil.ParsePxInCmMmPcToPt(css["font-size"]);
}
string text;
css.TryGetValue("margin-top", out text);
if (text == null) text = "0.5em";
string text2;
css.TryGetValue("margin-bottom", out text2);
if (text2 == null) text2 = "0.5em";
string border;
css.TryGetValue(CSS.Property.BORDER_BOTTOM_STYLE, out border);
lineSeparator = border != null && border == "dotted"
? new DottedLineSeparator()
: new LineSeparator();
var element = (LineSeparator)this.GetCssAppliers().Apply(
lineSeparator, tag, htmlPipelineContext
);
string color;
css.TryGetValue(CSS.Property.BORDER_BOTTOM_COLOR, out color);
if (color != null)
{
// WebColors deprecated, but docs don't state replacement
element.LineColor = WebColors.GetRGBColor(color);
}
paragraph.SpacingBefore += cssUtil.ParseValueToPt(text, baseValue);
paragraph.SpacingAfter += cssUtil.ParseValueToPt(text2, baseValue);
paragraph.Leading = 0f;
paragraph.Add(element);
list.Add(paragraph);
result = list;
}
catch (NoCustomContextException cause)
{
throw new RuntimeWorkerException(
LocaleMessages.GetInstance().GetMessage("customcontext.404"),
cause
);
}
return result;
}
}
Most of the code is taken directly from the existing source, with the exception of the checks for CSS.Property.BORDER_BOTTOM_STYLE and CSS.Property.BORDER_BOTTOM_COLOR to set border style and color if they're inlined in the <hr> style attribute.
Then you add the custom tag processor above to the XML Worker TagProcessorFactory:
using (var stream = new FileStream(OUTPUT_FILE, FileMode.Create))
{
using (var document = new Document())
{
var writer = PdfWriter.GetInstance(document, stream);
document.Open();
var tagProcessorFactory = Tags.GetHtmlTagProcessorFactory();
// custom tag processor above
tagProcessorFactory.AddProcessor(
new CustomHorizontalRule(),
new string[] { HTML.Tag.HR }
);
var htmlPipelineContext = new HtmlPipelineContext(null);
htmlPipelineContext.SetTagFactory(tagProcessorFactory);
var pdfWriterPipeline = new PdfWriterPipeline(document, writer);
var htmlPipeline = new HtmlPipeline(htmlPipelineContext, pdfWriterPipeline);
var cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(true);
var cssResolverPipeline = new CssResolverPipeline(
cssResolver, htmlPipeline
);
var worker = new XMLWorker(cssResolverPipeline, true);
var parser = new XMLParser(worker);
var xHtml = "<hr style='border:1px dotted red' />";
using (var stringReader = new StringReader(xHtml))
{
parser.Parse(stringReader);
}
}
}
One thing to note is that even though we're using the shorthand border inline style, iText's CSS parser appears to set all the styles internally. I.e., you can use any of the four longhand styles to check - I just happened to use CSS.Property.BORDER_BOTTOM_STYLE and CSS.Property.BORDER_BOTTOM_COLOR.
The resulting PDF:
You could use a div without any or with any content you want instead of an hr and give border style to that div, I am sure it will work in your case.

White overlay in WebView after update to AppCompat with Xamarin Forms

In my Xamarin Forms app I have a WebView used as a form by inserting a div with contentEditable set to true. It all worked fine until the update to AppCompat styles.
Now, a strange white overlay (white square) appears when the user tries to write inside the WebView, that disappears when the keyboard is dismissed. In order to find the root cause of the problem I have created a sample project with just one page containing just a vertical stack layout containing another stack layout and the webview. What I have noticed is that this problem happens if the height of the internal stack layout is enough for the webview to be covered by the keyboard when it appears. In this case the webview is pushed up, and this strange overlay appears. The webview is fully functional, and it is possible to write text, even though it is hidden by this white square, that disappears when the keyboard is dismissed.
This is an example of a simple page that can be used to test the issue. The buttons have been added only to increase and decrease the size of the layout to show the problem more easily
public class MainPage : ContentPage
{
const string ContentEdit = #"<div contentEditable=""true"" style =""min-height: 200px"">";
const string ContentEditEnd = "</div>";
const string EmptyDocument = #"<body>" + ContentEdit + ContentEditEnd + #"</body>";
WebView webView;
public MainPage()
{
InitializePage();
}
void InitializePage()
{
webView = new WebView()
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
};
var button1 = new Button
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
Text = "-",
};
var button2 = new Button
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
Text = "+",
};
var tallLayout = new StackLayout()
{
Orientation = StackOrientation.Horizontal,
HeightRequest = 200,
BackgroundColor = Color.Lime,
Children = { button1, button2, },
};
button1.Clicked += (sender, e) => tallLayout.HeightRequest = tallLayout.Height - 20;
button2.Clicked += (sender, e) => tallLayout.HeightRequest = tallLayout.Height + 20;
var layout = new StackLayout
{
Orientation = StackOrientation.Vertical,
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Children = { tallLayout, webView },
};
Content = layout;
}
protected override void OnAppearing()
{
InitializeEmptyContent();
}
public void InitializeEmptyContent()
{
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = EmptyDocument;
webView.Source = htmlSource;
}
}
I have tried to reproduce this simple layout also just using native Android, but it seems I don't have any similar bug. Is this a Xamarin Forms bug or am I doing something wrong?
In the end the problem was recognised as a Xamarin bug.

Image Caching Issue In Xamarin Android

I am working on Xamarin Android Application.To Cache the Images I have included this packages:
MvvmCross.HotTuna.Plugin.DownloadCache
MvvmCross.HotTuna.Plugin.File
MvvmCross.HotTuna.Plugin.Json
My BootStrap Files are,
using Cirrious.CrossCore.Plugins;
namespace Main.Droid.Bootstrap
{
public class DownloadCachePluginBootstrap
: MvxPluginBootstrapAction<Cirrious.MvvmCross.Plugins.DownloadCache.PluginLoader>
{
}
}
using Cirrious.CrossCore.Plugins;
namespace Main.Droid.Bootstrap
{
public class FilePluginBootstrap
: MvxPluginBootstrapAction<Cirrious.MvvmCross.Plugins.File.PluginLoader>
{
}
}
using Cirrious.CrossCore.Plugins;
namespace Main.Droid.Bootstrap
{
public class JsonPluginBootstrap
: MvxPluginBootstrapAction<Cirrious.MvvmCross.Plugins.Json.PluginLoader>
{
}
}
And This is how I download Image from Internet:
private void GetImageBitmapFromUrlAsync(string url)
{
WebClient webClient = new WebClient();
webClient.DownloadDataCompleted += delegate(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Result != null && e.Result.Length > 0)
{
var options = new BitmapFactory.Options
{
InJustDecodeBounds = false,
};
// BitmapFactory.DecodeResource() will return a non-null value; dispose of it.
using (var dispose = BitmapFactory.DecodeByteArray(e.Result,0, e.Result.Length, options))
imageview.SetImageBitmap(dispose);
}
};
webClient.DownloadDataAsync(new Uri(url));
}
My Problem is Images are not being cached.What am I doing wrong ? Any Solution ? Please Help !
The best way for handling images without concerning cache, delay or retry of a download of an image, transformation, speed and more (because all of those are handled automatically) is Picasso.
Once you try it you will never come back.

Categories

Resources