I am using Xamarin.Forms to develop an application for Android.
I am using the Xamarin.
I want to display the background as tiles.
I have prepared an image of 100x100 pixels.
\Android\MyApp\MyApp.Android\Resources\drawable\background.jpg
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewmodels="clr-namespace:MyApp.ViewModels"
x:DataType="viewmodels:LoginViewModel"
mc:Ignorable="d"
x:Class="MyApp.Views.LoginPage"
Shell.NavBarIsVisible="False"
BackgroundImage="background.jpg"
>
This way, the background.jpg will be enlarged and displayed.
I want to display it repeatedly in tiles.
You can display it repeatedly in tiles through below steps.
1.Create a drawable xml file on your Android project:
<?xml version="1.0" encoding="utf-8" ?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:tileMode="repeat"
android:src="#drawable/clock" >
</bitmap>
2.After that create below two effect classes on your shared project:
//base class
namespace AppTiles
{
public class BaseEffect : RoutingEffect
{
public const string EffectNamespace = "AppTiles";
public BaseEffect(String effectId) : base($"{EffectNamespace}.
{effectId}")
{
}
}
}
//effect class
namespace AppTiles
{
public class CoverEffect : BaseEffect
{
public CoverEffect() : base(nameof(CoverEffect))
{
}
}
}
3.Create a effect class in your Android project
[assembly: ResolutionGroupName("AppTiles") ]
[assembly: ExportEffect(typeof(AppTiles.Droid.CoverEffect),
nameof(CoverEffect))]
namespace AppTiles.Droid
{
public class CoverEffect : PlatformEffect
{
protected override void OnAttached()
{
UpdateBackground();
}
protected override void OnDetached()
{
}
private void UpdateBackground()
{
Android.Views.View mView = Container as Android.Views.View;
if (mView != null)
{
mView.Background = ContextCompat.GetDrawable(mView.Context, Resource.Drawable.XMLFile1);
}
}
}
}
4.Add below xmal in shared main page code behind:
<StackLayout Orientation="Vertical" Spacing="0">
<StackLayout.Effects>
<effects:CoverEffect/>
</StackLayout.Effects>
</StackLayout>
Below is the screenshot:
Related
I looked at this video to make a simple AR with Arcore for Android:
Augmented Reality with Arcore
Everything went well, but now I want to see this in xamarin forms, in a custom view.
But I can not :(
what i tried last:
In Forms:
<?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:controls="clr-namespace:FormsAR.Controls"
x:Class="FormsAR.MainPage">
<StackLayout BackgroundColor="Red" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Label BackgroundColor="Blue" TextColor="White" Text="JUST TEST"/>
<controls:ARView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="Yellow"/>
</StackLayout>
</ContentPage>
And:
using System;
using Xamarin.Forms;
namespace FormsAR.Controls
{
public class ARView : View
{
}
}
And Android:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/fragmentAR"
android:name="com.google.ar.sceneform.ux.ArFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
and finally:
[assembly: ExportRenderer(typeof(ARView), typeof(ARViewRenderer))]
namespace FormsAR.Droid.Controls
{
public class ARViewRenderer : ViewRenderer<ARView, Android.Views.View>
{
private ArFragment arFragment;
private Material readyColor;
Android.Views.View _view;
public ARViewRenderer(Context context) : base(context){}
protected override void OnElementChanged(ElementChangedEventArgs<ARView> e)
{
base.OnElementChanged(e);
_view = LayoutInflater.From(this.Context).Inflate(Resource.Layout.ARLayout, null, false);
AddView(_view);
if (Control == null)
{
Initialize();
}
}
private void Initialize()
{
var activity = this.Context as AppCompatActivity;
arFragment = (ArFragment)activity.SupportFragmentManager.FindFragmentById(Resource.Id.fragmentAR);
setupPlane();
MaterialFactory.MakeOpaqueWithColor(Context, new Google.AR.Sceneform.Rendering.Color(Android.Graphics.Color.Yellow)).GetAsync().ContinueWith(materialTask =>
{
readyColor = (Material)materialTask.Result;
});
}
private void setupPlane()
{
arFragment.TapArPlane += (sender, args) => this.OnTapArPlaneListener(args.HitResult, args.Plane, args.MotionEvent);
}
private void OnTapArPlaneListener(HitResult hitResult, Plane plane, MotionEvent motionEvent)
{
Anchor anchor = hitResult.CreateAnchor();
AnchorNode anchorNode = new AnchorNode(anchor);
anchorNode.SetParent(arFragment.ArSceneView.Scene);
CreateModel(anchorNode);
}
private void CreateModel(AnchorNode anchorNode)
{
TransformableNode node = new TransformableNode(arFragment.TransformationSystem);
node.SetParent(anchorNode);
var nodeRenderable = ShapeFactory.MakeSphere(0.08f, new Google.AR.Sceneform.Math.Vector3(0.0f, 0.15f, 0.0f), readyColor);
node.Renderable = nodeRenderable;
node.Select();
}
}
}
but i can't see:
image result
Link for project
Can you please help me identify where error?
How to use Web View in "Onappering" Event?
protected async override void OnAppearing()
{
base.OnAppearing();
if (Settings.Session)
{
while (!BrowserMaster.IsInNativeLayout)
{
await Task.Delay(50);
CallServer(url);
}
}
}
i have a webview in Xamarin forms that used onappering event
but error
"The full view has not been loaded yet"
This not only waits for your web view instance to be ready, it also waits for the site to be loaded, so you can use your site's assets.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App1.TestPage">
<WebView x:Name="BrowserMaster" Source="https://google.com/" Navigated="BrowserMaster_Navigated" />
</ContentPage>
public partial class TestPage
{
public TestPage()
{
InitializeComponent();
}
bool _isFirstTime = true;
async void BrowserMaster_Navigated(object sender, WebNavigatedEventArgs e)
{
if (_isFirstTime)
{
_isFirstTime = false;
await BrowserMaster.EvaluateJavaScriptAsync("alert(document.title)");
}
}
}
I am looking for tabs which will be on the bottom part of the page. I tried the xamarin forms TabbedPage, but for ios only the tabs are coming bottom and for android and windows the tabs are showing on the top. Is there any way to achieve this feature?
Edit: for new Xamarin.Forms projects you should use Xamarin.Forms Shell, it provides easy tabs and other great features.
To accomplish that you have 3 options:
1) To use new bottom tabbar native control you must have Xamarin Forms version 3.1 or above.
On your tabbed page you need to add the android specification for bottom placemente:
XAML
<?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:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom"
x:Class="YouProjectNameSpace.MyTabbedPage">
</TabbedPage>
Or c# code behind
using System;
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
using Xamarin.Forms;
namespace YouProjectNameSpace
{
public partial class MyTabbedPage : TabbedPage
{
public MyTabbedPage()
{
InitializeComponent();
On<Android>().SetToolbarPlacement(ToolbarPlacement.Bottom);
}
}
}
If you want more customization you can add:
<?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:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom"
BarBackgroundColor="#2196F3"
BarTextColor="White"
android:TabbedPage.BarItemColor="#66FFFFFF"
android:TabbedPage.BarSelectedItemColor="White"
x:Class="YouProjectNameSpace.MyTabbedPage">
</TabbedPage>
2) Create a custom renderer for Android of the tabbed page and move it to the bottom
using System;
using Xamarin.Forms;
namespace YouProjectNameSpace
{
public class CustomTabbedPage : TabbedPage
{
}
}
And the renderer:
using System;
using Android.Content;
using Android.Support.Design.Widget;
using Android.Support.V4.View;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android.AppCompat;
[assembly: ExportRenderer(typeof(CustomTabbedPage), typeof(CustomTabbedPageRenderer))]
namespace YouProjectNameSpace.Android
{
public class CustomTabbedPageRenderer : TabbedPageRenderer
{
public CustomTabbedPageRenderer(Context context): base(context)
{
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
this.InvertLayoutThroughScale();
base.OnLayout(changed, l, t, r, b);
}
private void InvertLayoutThroughScale()
{
this.ViewGroup.ScaleY = -1;
TabLayout tabLayout = null;
ViewPager viewPager = null;
for (int i = 0; i < ChildCount; ++i)
{
Android.Views.View view = GetChildAt(i);
if (view is TabLayout tabs)
tabLayout = tabs;
else if (view is ViewPager pager)
viewPager = pager;
}
tabLayout.ViewTreeObserver.AddOnGlobalLayoutListener(new GlobalLayoutListener(viewPager, tabLayout));
tabLayout.ScaleY = viewPager.ScaleY = -1;
}
private class GlobalLayoutListener : Java.Lang.Object, Android.Views.ViewTreeObserver.IOnGlobalLayoutListener
{
private readonly ViewPager viewPager;
private readonly TabLayout tabLayout;
public GlobalLayoutListener(ViewPager viewPager, TabLayout tabLayout)
{
this.viewPager = viewPager;
this.tabLayout = tabLayout;
}
public void OnGlobalLayout()
{
this.viewPager.SetPadding(0, -this.tabLayout.MeasuredHeight, 0, 0);
this.tabLayout.ViewTreeObserver.RemoveOnGlobalLayoutListener(this);
}
}
}
}
3) Use specific library like PXTabs, this one creates a full Xamarin Forms bottom tabs without any native code.
If you want to read more about bottom tabs and renderers:
Setting TabbedPage Toolbar Placement and Color
Xamarin.Forms: Official Bottom Navigation/Bottom Tabs on Android
BottomNavigationBarXF
c# code worked it.
using System;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
using Xamarin.Forms;
namespace YouProjectNameSpace
{
public partial class MyTabbedPage : TabbedPage
{
public MyTabbedPage()
{
InitializeComponent();
On<Xamarin.Forms.PlatformConfiguration.Android>().SetToolbarPlacement(ToolbarPlacement.Bottom);
}
}
}
Is there a way how to provide a nested view it's own viewmodel?
Example:
Master view of type TabbedView has multiple tabs.
<mvx:MvxTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Foo.Core.Pages.Access.MainPage"
xmlns:res="clr-namespace:Foo.Core.Resources;assembly=Foo.Core"
xmlns:mvx="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
xmlns:views="clr-namespace:Foo.Core.Pages.Access">
<TabbedPage.Children>
<views:LoginPage></views:LoginPage>
<views:RegisterPage></views:RegisterPage>
</TabbedPage.Children>
</mvx:MvxTabbedPage>
The LoginPage and RegisterPage are in separate views. But all the binding must be in the MainViewModel and I want the bindings to be separately in the LoginViewModel and RegisterViewModel.
Is there a way how to setup the binding to the properties to appropriate viewmodel? Preferably in XAML.
In order that to work you need to let the NavigationService (and therefore the Presenter) to load the children pages:
Xamarin.Forms View Presenter -> MvxTabbedPagePresentationAttribute
In your case it should be something like:
ViewModels
public class MyTabsContainerViewModel : MvxViewModel
{
private readonly IMvxNavigationService _navigationService;
public MyTabsContainerViewModel(IMvxNavigationService navigationService)
{
_navigationService = navigationService ?? throw new ArgumentNullException(nameof(navigationService));
}
public override async void ViewAppearing()
{
await ShowInitialViewModels();
base.ViewAppearing();
}
private async Task ShowInitialViewModels()
{
var tasks = new List<Task>();
tasks.Add(_navigationService.Navigate<LoginViewModel>());
tasks.Add(_navigationService.Navigate<RegisterViewModel>());
await Task.WhenAll(tasks);
}
}
public class LoginViewModel : MvxViewModel
{
}
public class RegisterViewModel : MvxViewModel
{
}
Views
MyTabsContainerPage.xaml
<?xml version="1.0" encoding="utf-8"?>
<views:MvxTabbedPage x:TypeArguments="viewModels:MyTabsContainerViewModel" xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:Foo.Core.ViewModels;assembly=Foo.Core"
xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
x:Class="Foo.Core.Pages.Access.MyTabsContainerPage">
</views:MvxTabbedPage>
MyTabsContainerPage.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
[MvxMasterDetailPagePresentation(Position = MasterDetailPosition.Detail, NoHistory = true)]
public partial class MyTabsContainerPage : MvxTabbedPage<MyTabsContainerViewModel>
{
public MyTabsContainerPage()
{
InitializeComponent();
}
}
LoginPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<views:MvxContentPage x:TypeArguments="viewModels:LoginViewModel" xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:Foo.Core.ViewModels;assembly=Foo.Core"
xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
x:Class="Foo.Core.Pages.Access.MixedNavTab1Page">
<StackLayout>
<Label Text="This is Tab 1" />
</StackLayout>
</views:MvxContentPage>
LoginPage.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
[MvxTabbedPagePresentation(WrapInNavigationPage = false, Title = "LoginTab1")]
public partial class LoginPage : MvxContentPage<LoginViewModel>
{
public LoginPage()
{
InitializeComponent();
}
}
RegisterPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<views:MvxContentPage x:TypeArguments="viewModels:RegisterViewModel" xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:Foo.Core.ViewModels;assembly=Foo.Core"
xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
x:Class="Foo.Core.Pages.Access.RegisterPage">
<StackLayout>
<Label Text="This is Tab 2" />
</StackLayout>
</views:MvxContentPage>
RegisterPage.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
[MvxTabbedPagePresentation(WrapInNavigationPage = false, Title = "RegisterTab2")]
public partial class RegisterPage : MvxContentPage<RegisterViewModel>
{
public RegisterPage()
{
InitializeComponent();
}
}
Full sample in the Playground project
HIH
I'm using Prism 6.3.0
I trying to use the following code but i'm getting the following errors.
'Application' does not contain a constructor that takes 1 arguments
'App.OnInitialized()': no suitable method found to override
'App.RegisterTypes()': no suitable method found to override
public partial class App : PrismApplication
{
public App(IPlatformInitializer initializer = null) : base(initializer) { }
protected override void OnInitialized()
{
InitializeComponent();
}
protected override void RegisterTypes()
{
}
}
What am I doing wrong?
Thanks
The reason was that the XAML file should have been like:
<?xml version="1.0" encoding="utf-8" ?>
<prism:PrismApplication xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Unity;assembly=Prism.Unity.Forms"
x:Class="Intro.App">
<Application.Resources>
<!-- Application resource dictionary -->
</Application.Resources>
</prism:PrismApplication>