how to display pdf in custom webview xamarin forms - xamarin

i want to display pdf in webview from url using pdfjs, but i am getting empty view. here is my code
CustomWebView.cs
public class CustomWebView : WebView
{
public static readonly BindableProperty UriProperty = BindableProperty.Create(propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(CustomWebView),
defaultValue: default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
}
MainPage.xaml
<ContentPage.Content>
<local:CustomWebView Uri="http://veezo2007pkk.somee.com/api/DiagnosticDetail/RetrieveFile/1" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ContentPage.Content>
App.Android
CustomWebViewRenderer.cs
public class CustomWebViewRenderer : WebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var customWebView = Element as CustomWebView;
Control.Settings.AllowUniversalAccessFromFileURLs = true;
Control.LoadUrl(string.Format("file:///android_asset/pdfjs/web/viewer.html?file={0}", string.Format("file:///android_asset/Content/{0}", WebUtility.UrlEncode(customWebView.Uri))));
}
}
}
it seems look fine, but i dont know why its not showing in webview....

I will assume two things here. One, you're not precious about PDF file being displayed in the WebView. Second you're OK with using 3rd party libraries.
I would suggest using SyncFusion PdfViewer. It's very easy to use and does everything you might want to do with PDFs - maybe not everything but a lot. If you're worried that you will need to pay a lot for these controls, fear not! SyncFusion has a free community license, which you can use (if you're not making more than a $1 mln USD and you don't have a larger team than 5 devs). You might want to have a look at this thread, talking about showing PDF from URL.

Related

Changing/Updating Image in XAML

I'm having an issue updating my Images in my Xamarin UWP app. First, I'd like to say I have seen multiple other threads on this issue, but none have been able to solve my predicament and a lot are very outdated.
Here is my scenario: I have three images I am using, named green.png, red.png, and gray.png. I am displaying one Image in my Xamarin app, and depending on a specific float called in my associated .cs file, I want to change the Image to another color. So, for example, if the float goes below 15, I want the Image to be the Red one.
Here is how I am currently displaying my Images without code for changing them, i.e. this code works fine and my Images appear in the app:
<Image Source="{pages:ImageResource BLE.Client.Pages.red.png}" Opacity="0.6"/>
They are currently stored in the same directory as the XAML files themselves. I know that on Android there is a Resources folder, but I don't see any equivalent for UWP, so I am loading my Images this way.
One way I attempted to do this based on another post I saw here is this:
<Image Source="{Binding HeadColor, StringFormat='pages:ImageResource BLE.Client.Pages.\{0\}.png', Mode=TwoWay}" Opacity="0.6"/>
The way this is supposed to function is depending on the value of my float, I used the string HeadColor in my .cs file and do an OnPropertyChanged on it. It always contains either the string "green", "red", or "gray", and with this method it should slot itself into the Image location string. However, this does not work.
For reference, here is how I update my HeadColor string in my .cs file:
private string _HeadColor;
public string HeadColor {get => _HeadColor; set {_HeadColor = value; OnPropertyChanged("HeadColor");}}
...
if (SensorAvgValue > 15) {_HeadColor = "green";}
else {_HeadColor = "red";}
RaisePropertyChanged(() => HeadColor);
I have also tried using an IValueConverter, but that does not work either.
So, in summary, my question is how to best go about dynamically changing which Image I'd like to use. They are all the same dimensions and in the same directory, the only difference being their names "green.png", "red.png", and "gray.png". Is there a better way to call/load the Images?
Thanks!
this works for me on iOS - I don't have a UWP env to test with, but it should work the same. I have two images "reddot.png" and "greendot.png" in my iOS Resources
<StackLayout Padding="20,50,20,50">
<Image Source="{Binding HeadColor, StringFormat='\{0\}dot.png'}" Opacity="0.6"/>
<Button Clicked="ChangeColor" Text="Click!!" />
</StackLayout>
code-behind
public partial class MainPage : ContentPage, INotifyPropertyChanged
{
private string headColor = "red";
public string HeadColor
{
get
{
return headColor;
}
set
{
headColor = value;
OnPropertyChanged();
}
}
public MainPage()
{
InitializeComponent();
this.BindingContext = this;
}
protected void ChangeColor(object sender, EventArgs args)
{
if (HeadColor == "red")
{
HeadColor = "green";
}
else
{
HeadColor = "red";
}
}
}

Xamarin Forms Android Autosize Label TextCompat pre android 8 doesn't autosize text

I want to utilise the auto-sizing feature of android textviews in my xamarin forms solution so that as the text length grows, the font sizes shrinks to never overflow the bounds of the label, and doesn't get truncated. I've created a custom Label control to do so and added an android custom renderer. It's not working in Android 7 and below. It is working in Android 8 and above.
According to the docs autosize support was introduced in android 8, but can be supported back to Android 4 with AppCompat.v4. However, my custom rendered label just renders the default font size in Android pre 8. It works fine in 8+ devices, the label text resizes as needed to not overflow the bounds. The accepted answer to this question with a similar issue on native android says it can be to do with not setting a width and height, I've tried setting widthrequest and heightrequest explicitly and it doesn't change anything. Also setting maxlines=1 doesn't change anything. An alternative thread suggests that custom fonts are the culprit. I created a vanilla forms solution using the default device font, and get the same effect.
My code:
internal class AutosizeLabelRenderer : LabelRenderer
{
#region constructor
public AutosizeLabelRenderer(Context context) : base(context)
{
}
#endregion
#region overridable
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || !(e.NewElement is AutoSizeLabel autoLabel) || Control == null) { return; }
TextViewCompat.SetAutoSizeTextTypeUniformWithConfiguration(Control, autoLabel.AutoSizeMinTextSize,
autoLabel.AutoSizeMaxTextSize, autoLabel.AutoSizeStepGranularity, (int)ComplexUnitType.Sp);
}
#endregion
}
public class AutoSizeLabel : Label
{
public int AutoSizeMaxTextSize
{
get => (int)GetValue(AutoSizeMaxTextSizeProperty);
set => SetValue(AutoSizeMaxTextSizeProperty, value);
}
public static readonly BindableProperty AutoSizeMaxTextSizeProperty = BindableProperty.Create(
nameof(AutoSizeMaxTextSize), // the name of the bindable property
typeof(int), // the bindable property type
typeof(AutoSizeLabel)); // the default value for the property
public int AutoSizeMinTextSize
{
get => (int)GetValue(AutoSizeMinTextSizeProperty);
set => SetValue(AutoSizeMinTextSizeProperty, value);
}
public static readonly BindableProperty AutoSizeMinTextSizeProperty = BindableProperty.Create(
nameof(AutoSizeMinTextSize), // the name of the bindable property
typeof(int), // the bindable property type
typeof(AutoSizeLabel)); // the default value for the property
public int AutoSizeStepGranularity
{
get => (int)GetValue(AutoSizeStepGranularityProperty);
set => SetValue(AutoSizeStepGranularityProperty, value);
}
public static readonly BindableProperty AutoSizeStepGranularityProperty = BindableProperty.Create(
nameof(AutoSizeStepGranularity), // the name of the bindable property
typeof(int), // the bindable property type
typeof(AutoSizeLabel)); // the default value for the property
//
}
Not working: Android 7 - text does not shrink
Working as expected: Android 8 and above
Xaml for above images:
<StackLayout HeightRequest="200" WidthRequest="100">
<Label Text="Fixed width and height, sentences get longer, text should shrink" />
<controls:AutoSizeLabel
AutoSizeMaxTextSize="50"
AutoSizeMinTextSize="8"
AutoSizeStepGranularity="1"
BackgroundColor="{StaticResource Shamrock}"
HeightRequest="40"
HorizontalOptions="Start"
MaxLines="1"
Text="A small sentence"
WidthRequest="200" />
<controls:AutoSizeLabel
AutoSizeMaxTextSize="50"
AutoSizeMinTextSize="8"
AutoSizeStepGranularity="1"
BackgroundColor="{StaticResource Shamrock}"
HeightRequest="40"
HorizontalOptions="Start"
MaxLines="1"
Text="A larger sentence that shrinks"
WidthRequest="200" />
<controls:AutoSizeLabel
AutoSizeMaxTextSize="50"
AutoSizeMinTextSize="8"
AutoSizeStepGranularity="1"
BackgroundColor="{StaticResource Shamrock}"
HeightRequest="40"
HorizontalOptions="Start"
MaxLines="1"
Text="An even larger sentence that shrinks more."
WidthRequest="200" />
</StackLayout>
TextView font size changes with the size of the control, which is new in Android 8.0 (API26),therefore, compatibility issues need to be considered when using the previous version.You could change the TextView to AppCompatTextView.
Change your
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || !(e.NewElement is AutoSizeLabel autoLabel) || Control == null) { return; }
AppCompatTextView appCompatTextView = new AppCompatTextView(_context);
appCompatTextView.Text = Element.Text;
appCompatTextView.SetMaxLines(1);
SetNativeControl(appCompatTextView);
TextViewCompat.SetAutoSizeTextTypeUniformWithConfiguration(Control,autoLabel.AutoSizeMinTextSize,autoLabel.AutoSizeMaxTextSize, autoLabel.AutoSizeStepGranularity, (int)ComplexUnitType.Sp);
}
Leo Zhu's answer got me most of the way there. There were a couple of extra steps I needed to take to get it fully working, so I'm posting the code as a separate answer here.
Differences between mine and Leo's answer:
Creating a new native control in scope like Leo suggested meant that it worked for a while but got disposed by the garbage collector and caused an exception when returning to the page after navigating away. To fix this I needed to override a property called ManageNativeControlLifetime to return false, and then manually manage disposing the object by overriding the dispose method and calling Control.RemoveFromParent();. This advice comes from a xamarin staff member in this thread.
Formatting and binding context are not automatically inherited when creating the new native control and need to be set manually. I needed to add those based on my needs using the android specific binding syntax. You may need to add other formatting and binding code based on your needs, I'm just doing font colour, gravity and binding context here.
I set the binding context with
appCompatTextView.SetBindingContext(autoLabel.BindingContext);
Once the binding context was set, I needed to add a new string property to my XF AutoSizeLabel class to pass in through XAML, then use it to set the binding path for the relevant property (In my case the text property). If more than one binding is required, you would need to add multiple new binding path properties for each required property. I set a specific binding like this:
appCompatTextView.SetBinding("Text", new Binding(autoLabel.TextBindingPath));
To facilitate this in my Xamarin Forms Xaml, my Xaml went from <Label Text="{Binding MyViewModelPropertyName}" /> to <controls:AutoSizeLabel TextBindingPath="MyViewModelPropertyName" />
Here's the full code of the renderer:
protected override bool ManageNativeControlLifetime => false;
protected override void Dispose(bool disposing)
{
Control.RemoveFromParent();
base.Dispose(disposing);
}
private AppCompatTextView appCompatTextView;
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (e.NewElement == null || !(e.NewElement is AutoSizeLabel autoLabel) || Control == null) { return; }
//v8 and above supported natively, no need for the extra stuff below.
if (DeviceInfo.Version.Major >= 8)
{
Control?.SetAutoSizeTextTypeUniformWithConfiguration(
autoLabel.AutoSizeMinTextSize,
autoLabel.AutoSizeMaxTextSize, autoLabel.AutoSizeStepGranularity,
(int)ComplexUnitType.Sp);
return;
}
appCompatTextView = new AppCompatTextView(Context);
appCompatTextView.SetTextColor(Element.TextColor.ToAndroid());
appCompatTextView.SetMaxLines(1);
appCompatTextView.Gravity = GravityFlags.Center;
appCompatTextView.SetBindingContext(autoLabel.BindingContext);
appCompatTextView.SetBinding("Text", new Binding(autoLabel.TextBindingPath));
SetNativeControl(appCompatTextView);
TextViewCompat.SetAutoSizeTextTypeUniformWithConfiguration(Control, autoLabel.AutoSizeMinTextSize, autoLabel.AutoSizeMaxTextSize, autoLabel.AutoSizeStepGranularity, (int)ComplexUnitType.Sp);
}

Xamarin Iconize IconTabbedPage Example

Can someone provide an example of how to use the IconTabbedPage in Iconize, preferably in Xaml? I have an IconTabbedPage with IconNavigation pages as children, all defined in Xaml. I then set the Icon property of the subpages by specifiying the font awesome name (“fa-home”). I tried to set the title as well, but neither of these will render the icon. I have search (a lot) for examples of the IconTabbedPage but couldn’t find any in Xaml. Additional bonus if you can provide an example of how to use the icons in a list cell context action.
Looking into #Niklas Code, you can create a tabbed page with a base class that inherits from IconTabbedPage , then your xaml will look like this.
<icon:IconTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:icon="clr-namespace:Plugin.Iconize;assembly=Plugin.Iconize"
....
>
<icon:IconTabbedPage.Children>
<ContentPage Title="Build" Icon="md-build">
</ContentPage>
</icon:IconTabbedPage.Children>
I hope it will help somebody
I think you can take a look on Sample on GitHub
[\[assembly: XamlCompilation(XamlCompilationOptions.Compile)\]
namespace Iconize.FormsSample
{
public class App : Application
{
public App()
{
// The root page of your application
var tabbedPage = new IconTabbedPage { Title = "Iconize" };
foreach (var module in Plugin.Iconize.Iconize.Modules)
{
tabbedPage.Children.Add(new Page1
{
BindingContext = new ModuleWrapper(module),
Icon = module.Keys.FirstOrDefault()
});
}
MainPage = new IconNavigationPage(tabbedPage);
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}][1]

Telerik UWP DataForm changing bound data and Updating

I'm currently using telerik in UWP to create list of items, i want to be able to use a browse button and update a certain piece of data in the Telerik-RadDataForm. I have all the bindings setup using MVVM and it displays data fine if it isn't edited on the code side. My XAML is setup as so:
<Data:RadDataForm x:Name="dataform"
HorizontalAlignment="Left" Grid.Row="0"
Grid.RowSpan="2" Grid.Column="2"
VerticalAlignment="Center" Width="454"
Item="{Binding CurrentSceneViewModel, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" CommitMode="Immediate"
ValidationMode="Immediate" Height="664" Margin="0,28" />
The CurrentSceneViewModel is:
public SceneViewModel CurrentSceneViewModel
{
get => _currentSceneViewModel;
set=> _currentSceneViewModel= value;
}
And the data i wish to change is :
public string FileName
{
get => _fileName;
set
{
Scene.SceneFile = value;
_fileName = Path.GetFileName(value);
OnPropertyChanged(nameof(FileName));
}
}
The problem i have is pushing this information to the user interface the code-behind doesn't seem to update the UI, even using PropertyChanged. I'm not sure what else to try ? And if this is something the RadDataform simply doesn't support. It should be noted FileName is a property of CurrentScene ViewModel.
public abstract class BaseViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected IPageNavigationService navservice = new PageNavigationService();
}

Localizing the default windows phone date picker

I have localised the whole app but not able to localise the date picker. A bit of searchin in the forum gave me few answers like this one
but i cant find a properties folder with the resx for different lang for toolkit! I have jus added the toolkit reference in the solution explorer under reference and thats im able to access date picker. I have made a folder called toolkit.content to put the ok and cancel images.
so how do i add the resx for the toolkit date picker :(
You can also create a custom control which inherits from the original DatePicker.
public class MyDatePicker : Microsoft.Phone.Controls.DatePicker
{
public string PickerPageHeader
{
get { return (string)GetValue(PickerPageHeaderProperty); }
set { SetValue(PickerPageHeaderProperty, value); }
}
// Using a DependencyProperty as the backing store for PickerPageHeader. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PickerPageHeaderProperty =
DependencyProperty.Register("PickerPageHeader", typeof(string), typeof(MyDatePicker)
, new PropertyMetadata("Choose date text in your language"));
public MyDatePicker()
{
base.PickerPageUri = new Uri("/Sample;component/CustomControls/MyDatePickerPage.xaml?Header=" + PickerPageHeader, UriKind.Relative);
//Don't forget to change the project name and xaml location
}
}
And create picker page xaml file in a CustomControls folder:
<toolkit:DatePickerPage
x:Class="Sample.MyDatePickerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
/>
Code behind:
public partial class MyDatePickerPage : Microsoft.Phone.Controls.DatePickerPage
{
public MyDatePickerPage ()
{
InitializeComponent();
foreach (var item in base.ApplicationBar.Buttons)
{
IApplicationBarIconButton button = item as IApplicationBarIconButton;
if (null != button)
{
if ("DONE" == button.Text.ToUpper())
{
button.Text = "done in your language";
}
else if ("CANCEL" == button.Text.ToUpper())
{
button.Text = "cancel in your language";
}
}
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
(base.FindName("HeaderTitle") as TextBlock).Text = e.Uri.OriginalString.Substring(e.Uri.OriginalString.IndexOf("Header=") + 7);
base.OnNavigatedTo(e);
}
}
You have to get the source for the ToolKit and rebuild it with your localization
WP7 ToolKit Source
It's very simple: Parameter - Language.
Xaml code:
<toolkit:DatePicker Language="ru-RU" Margin="-12, 0" Value="{Binding BirthDate, Mode=TwoWay}" />

Resources