Is it possible to embed Android.VideoView in Xamarin Forms ContentView - android

I need to create a mobile app that have to run on android 7.0 - 9.0 and the latest iOS
So in my VS 2017 15.9.6 on Windows 10 I try to use Xamarin.Forms 3.4 in a shared project as a container for a native Android.VideoView.
I try to figure out how to do that, since the Mono.Android examples don't use Xamarin.Forms. So, do I need a kind of #ifdef in the xaml file, to embedd ths Android VideoView? Or am I completely wrong with that approach?

Using a Shared Projects, you can define the native views in XAML and then access them in the code behind (which is basically a requirement since native Android|iOS controls are not directly bindable and most have method calls for setting up features that would not available via XAML (i.e. a VideoView has a .SetVideoURI method that has no Xamarin-based wrapper property so you have to execute that method to play a video).
XAML:
<?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:androidWidget="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
xmlns:androidGraphics="clr-namespace:Android.Graphics;assembly=Mono.Android;targetPlatform=Android"
xmlns:androidContext="clr-namespace:Forms40Shared.Droid;assembly=Forms40Shared.Android;targetPlatform=Android"
x:Class="Forms40Shared.NativeEmbedPage" >
<ContentPage.Content>
<StackLayout Margin="20">
<androidWidget:TextView x:Arguments="{x:Static androidContext:MainActivity.Instance}" Text="Welcome to Forms!" TextSize="24" View.HorizontalOptions="Center" >
<androidWidget:TextView.Typeface>
<androidGraphics:Typeface x:FactoryMethod="Create">
<x:Arguments>
<x:String>cursive</x:String>
<androidGraphics:TypefaceStyle>Normal</androidGraphics:TypefaceStyle>
</x:Arguments>
</androidGraphics:Typeface>
</androidWidget:TextView.Typeface>
</androidWidget:TextView>
<ContentView x:Name="contentView" HorizontalOptions="FillAndExpand" VerticalOptions="Center" HeightRequest="200" >
<androidWidget:VideoView x:Arguments="{x:Static androidContext:MainActivity.Instance}" />
</ContentView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Note: Do not enable XamlCompilation at the global assembly level or on XAML pages that contain native views as it will not work (and there are not errors during compiling or runtime, the views just do not show up as they have been stripped out)...
MainActivity
[Activity(Label ~~~~
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
internal static MainActivity Instance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
Instance = this;
~~~
}
Code Behind:
#if __ANDROID__
var videoView = (contentView as NativeViewWrapper).NativeView as VideoView;
videoView.SetVideoURI(Android.Net.Uri.Parse($"android.resource://{Android.App.Application.Context.PackageName}/raw/fireplace"));
videoView.Start();
#elif __IOS__
~~~
#endif
Output:
https://msdn.microsoft.com/en-us/magazine/mt790186.aspx

Related

Background color on mobile app above and below the ContentPage is white instead of black

I have a VS2019 for mac cross platform Xamarin Forms 4 app. I used the basic template to create it.
In my App.xaml.cs file I just set the MainPage to my ContentPage object.
This content page has the backgroundcolor set to black.
When I run it on my iPhone I get the following results. Notice how the top of the screen and the bottom both have white backgrounds. I can't seem to figure out where that is coming from.
I tried wrapping my content page in a NavigationPage and settings its background to black, but all that does it add a little more black at the top of my contentpage and move the rest of the page down.
I can't figure out where the background color for the top and bottom outside of my content page is being set.
Can someone tell me?
UPDATE: Added some things asked for in the comments:
App.xaml:
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="UpdateAgent.App">
<Application.Resources>
</Application.Resources>
</Application>
App.xaml.cs:
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace UpdateAgent
{
public partial class App : Application
{
Interfaces.IStartup Startup;
public App()
{
InitializeComponent();
Xamarin.Forms.DependencyService.Get<Interfaces.IStartup>().Init();
MainPage = new WebUpdatePage();
}
}
}
Visual Studio 2019 for Mac is latest version. Just updated the other day and when I check for updates there are not any.
I am using an iPhone XS Max not the simulator.
After seeing the comment I tried it out in the simulator the iPhone 12 Pro Max - 14.2 just to see if it was any different. It does the same thing.
UPDATE 2: Decided to add the WebUpdatePage xaml and class figuring it would be asked for eventually. Here they are:
WebUpdatePage.xaml:
<?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:local="clr-namespace:HybridWebViewMobile;assembly=HybridWebViewMobile"
x:Class="UpdateAgent.WebUpdatePage"
BackgroundColor="Black">
<ContentPage.Content>
<local:HybridWebView x:Name="hybridWebView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ContentPage.Content>
</ContentPage>
WebUpdatePage.xaml.cs:
using Xamarin.Forms;
using Devices.Communication.Mobile;
namespace UpdateAgent
{
public partial class WebUpdatePage : ContentPage
{
public WebUpdatePage()
{
InitializeComponent();
DependencyService.Get<IConnectDevice>().RegisterDetectors(hybridWebView).Wait();
DependencyService.Get<IConnectDevice>().Jsonfunctions(hybridWebView);
}
}
}
UPDATE 3:
Here is information about the HybridWebView:
The first iOS class is this:
[assembly: ExportRenderer(typeof(HybridWebView),typeof(HybridWebViewRenderer))]
namespace UpdateAgent.iOS
{
public class HybridWebViewRenderer : HybridWebViewRendererMobile
{
public HybridWebViewRenderer()
{
}
}
}
The second iOS implementation partially looks like this (only show the relevant parts):
public class HybridWebViewRendererMobile : WkWebViewRenderer, IWKScriptMessageHandler
{
const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
WKUserContentController userController;
public HybridWebViewRendererMobile() : this(new WKWebViewConfiguration())
{
}
public HybridWebViewRendererMobile(WKWebViewConfiguration config) : base(config)
{
userController = config.UserContentController;
var script = new WKUserScript(new NSString(JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript(script);
userController.AddScriptMessageHandler(this, "invokeAction");
}

Gif Xamarin forms Android

I know that xamarin forms currently support playing gif.
I've already tried the link https://github.com/jfversluis/AnimatedGifForms/
But It seems to work only for the gifs with the type in the example, I've tried another gif and it can not load on android.
It works perfectly on the IOS.
There are any config that I can do for playing gif in xamarin forms
I'm using Xamarin.form 4.6, and the latest Xamarin.Essential 1.5.3
You can use Image control to load gif in Xamarin.forms.
<StackLayout>
<!-- Place new controls here -->
<Image Source="sample.gif" IsAnimationPlaying="True"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
Starting and stopping is controlled through IsAnimationPlaying.
Originally we were going to use Start and Stop methods but all these
did was set IsAnimationPlaying to true or false respectively. This way
it can also be started and stopped via Binding!!
I uploaded a sample project here and you can check.
Refer: Gif Animation Support
Update:
Use Xamarin.FFImageLoading.Svg.Forms to load:
xmlns:ffimageloading="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
<StackLayout>
<ffimageloading:SvgCachedImage HorizontalOptions="Center" VerticalOptions="CenterAndExpand" Source="blue.gif" />
</StackLayout>
Don't forget to CachedImageRenderer.Init(true); in MainActivity:
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
//Forms.SetFlags("UseLegacyRenderers");
CachedImageRenderer.Init(true);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}

How to create progress bar with rounded corners / Edge in Xamarin forms

I need the expert help. I am struggling to create the ProgressBar with rounded corner in Xamarin Form. I have searched on google and found the couple of post by using the layer property ex. "Layer.CornerRadius = 5" but my code does not support it.
How to make a progress bar with rounded corners in Xamarin forms.
(The above example not supported)
How can I create the rounded Edge of the progress bar?
Sample Code (TestControls.xaml usnig XamarinForm):-
<?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:local="clr-namespace:Test.Mobile"
xmlns:ffimageloadingsvg="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
x:Class="Test.Mobile.UI.TestControls">
<ContentPage.Content>
<Grid Grid.Column="1" Margin="0" Padding="0" BackgroundColor= "LightYellow" >
<ProgressBar x:Name="pb_ProgressBar" Margin="70,0,30,0" Progress="0.0" WidthRequest="300" HeightRequest="20" ProgressColor="DarkSlateBlue" VerticalOptions="Center" BackgroundColor="AntiqueWhite"></ProgressBar>
</Grid>
</ContentPage.Content>
</ContentPage>
and Code behind file as
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Test.Mobile.UI
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TestControls : ContentPage
{
public TestControls ()
{
InitializeComponent ();
Device.BeginInvokeOnMainThread(async () =>
{
await pb_ProgressBar.ProgressTo(1.0, 10000, Easing.Linear);
});
}
}
}
Please help me how to make a progress bar with rounded corners in Xamarin forms?
I can not use xmlns:android="schemas.android.com/apk/res/android";. The device android tablet will be use offline and no internet access.
This is not library, you could refer to the question:
Why this line xmlns:android=“http://schemas.android.com/apk/res/android” must be the first in the layout xml file?
As NitroG42 said, in XML, xmlns declares a Namespace. In fact, when you do:
<LinearLayout android:id>
</LinearLayout>
Instead of calling android:id, the xml will use http://schemas.android.com/apk/res/android:id to be unique. Generally this page doesn't exist (it's a URI, not a URL), but sometimes it is a URL that explains the used namespace.
The namespace has pretty much the same uses as the package name in a Java application.
You could refer to the documentation:
Uniform Resource Identifier (URI)
A Uniform Resource Identifier (URI) is a string of characters which identifies an Internet Resource.
The most common URI is the Uniform Resource Locator (URL) which identifies an Internet domain address. Another, not so common type of URI is the Universal Resource Name (URN).

Route the swipe action inside segmentcontrol of a child page of tabbedpage

So I'm using Xamarin forms for a cross platform app, the main UI is a tabbed page, and one of the page has a segmented control in it, the segment control will switches the data of a list view control. The problem is when I swipe the screen, it switches between the different child pages of the tabbed page, but I'd like it to switch between the segment control inside the child page. Is there anyway I can let swipe not work with tabbed page, but the inner segment control?
XAML for tabbed page:
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MainApp"
x:Class="MainApp.MainPage">
<!--Pages can be added as references or inline-->
<local:NewsPage Title="News" Icon="icon.png"/>
<ContentPage Title="Guides" Icon="icon.png"/>
<ContentPage Title="Wallets" Icon="icon.png"/>
<ContentPage Title="Me" Icon="icon.png"/>
</TabbedPage>
News page:
<controls:SegmentedControl x:Name="SegControl" TintColor="#007AFF" SelectedSegment="0"
VerticalOptions="Center"
Grid.Column="1" ValueChanged="SegControl_ValueChanged">
<controls:SegmentedControl.Children>
<controls:SegmentedControlOption Text="Type1" />
<controls:SegmentedControlOption Text="Type2" />
</controls:SegmentedControl.Children>
</controls:SegmentedControl>
<ListView ItemsSource="{Binding Source={StaticResource SArray}}" Grid.Row="1" Grid.Column="0" RowHeight="85">
<ListView.ItemTemplate> ... </ListView>
I take it this is on Android? I'm not sure is swiping works on iOS.
One option is to disable swiping on the tab pages.
You can do this using a custom renderer.
[assembly: ExportRenderer(typeof(CustomTabbedPage), typeof(CustomTabbedPageRenderer))]
namespace App1.Droid
{
public class CustomTabbedPageRenderer : TabbedPageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
var info = typeof(TabbedPageRenderer).GetTypeInfo();
var fieldInfo = info.GetField("_useAnimations", BindingFlags.Instance | BindingFlags.NonPublic);
fieldInfo.SetValue(this, false);
base.OnElementChanged(e);
}
}
}
EDIT
Looks like this has been added to Xamarin Forms now:
https://github.com/xamarin/Xamarin.Forms/pull/409
ANOTHER EDIT
And another way. I'm learning lots today!
public partial class MainPage : Xamarin.Forms.TabbedPage
{
public MainPage()
{
InitializeComponent();
this.On<Xamarin.Forms.PlatformConfiguration.Android>().SetIsSwipePagingEnabled(false);
}
}
I'M ON A ROLL
From XAML
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.IsSwipePagingEnabled="False"

display master page over navigation bar in xamarin forms droid project

For those of you used to code in Java for Android, I believe you'll immediatly understand this concept, while others might not, but it's ok, I'll do my best to try and explain what I mean.
I have this project, company one, to deliver at work, in which I have to develop an App that, among other things, contains the Navigation Drawer concept form material design, but adapted to the company's adm favorite "concept" of development, i.e., Xamarin (Forms, in this case)... using Xamarin, well, almost the same thing but it's manageable to achieve the required, but in Forms?.... well, lets just say they didn't yet understand the concept behind it (child's play apps, most likely) and require a B2C app, very professional-like, developed with THAT... -_-
Anyways, among a huge series of other issues I've managed to find and have to face, is this: the nav drawer (a.k.a. here Master Page) needs to be displayed over the AppCompatBar (here Navigation Bar), because, well, because that's what is supposed to be felt using Android, that's how it works with every other app, that's how it was designed to work, and how it must work, but guess what? no go in Xamarin Forms...
I've tried the https://developer.xamarin.com/guides/xamarin-forms/user-interface/navigation/master-detail-page/, several blogs and forums in the web (except theirs, of course, as I'm still waiting for a very simple answer after 3 months, and the project must soon be presented as demo), their book "Creating
Mobile Apps with Xamarin.Forms" by Charles Petzold, online videos, and nothing, not a clue on how to display the master page over the navigation bar when it's called...
Here's the code for the main page in xaml:
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Mobile.UI.Pages;assembly=Mobile"
x:Class="Mobile.UI.Pages.MainPage"
BackgroundColor="White"
IsGestureEnabled="False"
MasterBehavior="Default">
<MasterDetailPage.Master>
<local:MasterPage x:Name="masterPage" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage
BarBackgroundColor="#27C6E5">
<x:Arguments>
<local:ItemListPage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
The master page also in xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Mobile.UI.Pages.MasterPage"
Icon="menu.png"
Title="Menu">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<StackLayout
VerticalOptions="FillAndExpand">
<StackLayout
VerticalOptions="Fill"
HorizontalOptions="Fill"
HeightRequest="128"
Orientation="Vertical"
BackgroundColor="White"
Padding="4">
<Image
Source="favicon.png"
HeightRequest="128"
WidthRequest="200"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
<ListView
x:Name="menuList"
VerticalOptions="FillAndExpand"
SeparatorVisibility="None"
HasUnevenRows="False">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell
ImageSource="{Binding IconSource}"
Text="{Binding Title}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Its code-behind:
public ListView ListView
{
get
{
return menuList;
}
}
public MasterPage()
{
InitializeComponent();
Padding = 0;
var menuListItems = new List<MenuListItem>();
menuListItems.Add(new MenuListItem()
{
Title = "Items",
IconSource = "items.png",
TargetType = typeof(ItemListPage)
});
menuListItems.Add(new MenuListItem()
{
Title = "Chat",
IconSource = "chat.png",
TargetType = typeof(ChatListPage)
});
menuList.ItemsSource = menuListItems;
}
And my main page:
public partial class MainPage : MasterDetailPage
{
public MainPage()
{
InitializeComponent();
masterPage.ListView.ItemTapped += ListView_ItemTapped;
if (Device.OS == TargetPlatform.WinPhone)
{
Master.Icon = "menu.png";
}
}
private void ListView_ItemTapped(object sender, ItemTappedEventArgs e)
{
var item = e.Item as MenuListItem;
if (item != null)
{
Detail = new NavigationPage((Page)Activator.CreateInstance(item.TargetType))
{
BarBackgroundColor = Color.FromRgb(204, 204, 204),
Title = item.Title
};
masterPage.ListView.SelectedItem = null;
IsPresented = false;
}
}
}
Anything else you might need, please just ask...
Any help, please?
Thanks in advance...
The key to this for me was to make sure that the Android activity inherited from FormsAppCompatActivity.
This blog post set us on the right track.

Categories

Resources