Xamarin Forms - Android: framework activity doesn't include project resources - xamarin

I'm trying to use project specific Android drawables for a ToolbarItem. Because of the framework structure I use it appears as if my project specific drawables don't exist.
I created a project where I have the following structure:
Project diagram
The Project.Android MainActivity inherits from a FrameworkMainActivity. The FrameworkMainActivity is responsible for calling the OnCreate method. The Xamarin.Forms.Application is acquired through an abstract method.
public abstract class FrameworkMainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
this.LoadApplication(this.GetApp());
}
protected abstract Xamarin.Forms.Application GetApp();
}
In the Framework.Xamarin.Forms project I have a MasterDetailPage that adds a demo toolbar item which uses an icon with source: 'demo.png'
public DemoMasterDetailPage()
{
this.Master = new DemoMenuPage();
this.Detail = new NavigationPage(new DemoContentPage());
this.ToolbarItems.Add(new ToolbarItem()
{
Icon = "demo.png",
Text = "Demo",
});
}
The ToolbarItem icon has to be project specific so I can't place it in my Framework. This is not possible because when I place my image in Project.Android > Resources > drawable folder the I get the following output:
[0:] Could not load image named: {0}: demo.png
When I place the image in the Framework.Android > Resources > drawable folder the ToolbarItem works perfectly and shows my icon correctly.
Can someone tell me what I'm doing wrong or how I can workaround the issue?
XF Version: 2.4.0.282

Related

I am trying to set a back arrow in my toolbar but I can't get it to take you to the previous page when clicked

I am working with xamarin.android.
I have tried to use the SetNavigationOnClickListener method but I have not been able to implement it. Could someone tell me what to set so that when I click the arrow it returns me to the previous page?
XML:
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
app:navigationIcon="#drawable/ic_back"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.appcompat.widget.Toolbar>
Code:
var toolbar = FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
toolbar.SetNavigationOnClickListener(//NOT WORK);
There is no need to create a toolbar again. Use the code below would show the back button in toolbar. And then override the OnOptionsItemSelected event to handle the back button click.
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
var actionBar = SupportActionBar;
actionBar.SetDisplayHomeAsUpEnabled(true);
actionBar.SetHomeButtonEnabled(true);
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
return base.OnOptionsItemSelected(item);
}
}

How to use activity_main layout as a widget on xamarin?

I have a xamarin project and my main purpose is creating a widget by using activity_main layout and my activity main layout includes tabbed pages such as Tab1 , Tab2 and Tab3 . That is why i want to show them on widget . According to my researches i need some xml file to create a widget on android . My xml file like this.
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dip"
android:minHeight="72dip"
android:resizeMode="horizontal"
android:minResizeWidth="144dip"
android:updatePeriodMillis="86400000"
android:initialLayout="#layout/activity_main"/>
I added activity_main as a initialLayout and i did some arrangement in the bag. My appwidget class like this .
[BroadcastReceiver(Label = "Widget")]
[IntentFilter(new string[] { "android.appwidget.action.APPWIDGET_UPDATE" })]
[MetaData("android.appwidget.provider", Resource = "#xml/widget_word")]
class AppWidget : AppWidgetProvider
{
public override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
context.StartService(new Intent(context, typeof(UpdateService)));
}
}
My updateService like this .
public override void OnStart(Intent intent, int startId)
{
// Build the widget update for today
RemoteViews updateViews = buildUpdate(this);
// Push update for this widget to the home screen
ComponentName thisWidget = new ComponentName(this, Java.Lang.Class.FromType(typeof(AppWidget)).Name);
AppWidgetManager manager = AppWidgetManager.GetInstance(this);
manager.UpdateAppWidget(thisWidget, updateViews);
}
public override IBinder OnBind(Intent intent)
{
throw new NotImplementedException();
}
public RemoteViews buildUpdate(Context context)
{
// Build an update that holds the updated widget contents
var updateViews = new RemoteViews(context.PackageName, Resource.Layout.activity_main);
return updateViews;
}
I am using fragments to display tab1 , tab2 , tab3 . If I add fragment axml file to the initialLayout it works fine . But it shows only tab1 . I feel like i should use activity_main to display 3 tabs on widget. Please help !
You cannot use bottomNavigationView in the appwidget,
If you set it you will get follow error.
Creating the App Widget layout is simple if you're familiar with Layouts. However, you must be aware that App Widget layouts are based on RemoteViews, which do not support every kind of layout or view widget.
A RemoteViews object (and, consequently, an App Widget) can support the following layout classes:
FrameLayout
LinearLayout
RelativeLayout
GridLayout
And the following widget classes:
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
ListView
GridView
StackView
AdapterViewFlipper
Descendants of these classes are not supported.
Here is Google article about it.
https://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout

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]

Add Page on Navigate Drawer Menu and navigate to respective page on menu click Xamarin Android

I have made a sample with Navigate Drawer Menu from Left side. I have fixed 4 menu items as (Home, About Us, Enquiry, Contact Us).
Now I need to add pages to my layout, By default it should show Home Page with respective content. Then when I would click on About Us menu item then should display About Us Page with respective content...so on for other menu links too.
I didn't have an idea to how to add page and how should I make menu clickable and to track which menu item should have been clicked and which page should have to open and how.
I have searched a lot for this on google, on YouTube and on several tutorials, but didn't found any proper guidance. Therefore kindly help me regarding this please....
below it the code of MainActivity.cs
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Support.V7.App;
using Android.Support.V4.Widget;
using V7Toolbar = Android.Support.V7.Widget.Toolbar;
using Android.Support.Design.Widget;
namespace NavigationDrawerLayout
{
[Activity(Label = "J&K Tour and Travel", Theme = "#style/Theme.DesignDemo", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : AppCompatActivity
{
DrawerLayout drawerLayout;
NavigationView navigationView;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
drawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
// Create ActionBarDrawerToggle button and add it to the toolbar
var toolbar = FindViewById<V7Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
var drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, Resource.String.drawer_open, Resource.String.drawer_close);
drawerLayout.SetDrawerListener(drawerToggle);
drawerToggle.SyncState();
navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
setupDrawerContent(navigationView);
}
void setupDrawerContent(NavigationView navigationView)
{
navigationView.NavigationItemSelected += (sender, e) => {
//e.MenuItem.SetChecked(true);
drawerLayout.CloseDrawers();
};
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
navigationView.InflateMenu(Resource.Menu.nav_menu);
return true;
}
}
}
Also i am sharing a link of .rar file of my whole sample project below. I have made this project using VS 2017 Community Edition using c#:
https://drive.google.com/open?id=0B584mT-OF6vJZzdFem4tMG9jV1U
It is recommended to use NavigationDrawer with Fragment to show different pages.
In your layout you can place a FrameLayout for the container of fragments for example:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<FrameLayout android:id="#+id/framelayout"
android:layout_height="match_parent"
android:layout_width="match_parent" />
<android.support.design.widget.NavigationView
android:layout_width="wrap_content"
android:layout_gravity="start"
android:layout_height="match_parent"
android:id="#+id/nav_view"
app:menu="#menu/nav_menu"
app:headerLayout="#layout/drawer_header" />
</android.support.v4.widget.DrawerLayout>
Then in the OnCreate method first commit your home page like this:
FragmentTransaction transaction = this.FragmentManager.BeginTransaction();
HomeFragment home = new HomeFragment();
transaction.Add(Resource.Id.framelayout, home).Commit();
Then in the NavigationItemSelected event:
var naviview = FindViewById<NavigationView>(Resource.Id.nav_view);
naviview.NavigationItemSelected += (sender, e) =>
{
e.MenuItem.SetChecked(true);
FragmentTransaction transaction1 = this.FragmentManager.BeginTransaction();
switch (e.MenuItem.TitleFormatted.ToString())
{
case "Home":
HomeFragment home = new HomeFragment();
transaction1.Replace(Resource.Id.framelayout, home).AddToBackStack(null).Commit();
break;
case "About Us":
VideoFragment video = new VideoFragment();
transaction1.Replace(Resource.Id.framelayout, video).AddToBackStack(null).Commit();
break;
}
drawerLayout.CloseDrawers();
};
Since it is Fragment, then for example, your Home Page should be something like this:
public class HomeFragment : Fragment
{
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = inflater.Inflate(Resource.Layout.homelayout, container, false);
return view;
}
}

reaching a page from xamarin.forms inside android project

I'm working on an android app with xamarin. I made tabbed pages. For the second page, i want to show the camerastream from my android camera. For that, some sample code said me I need to use a textureView inside the android part of the app, but that textureview needs to be putted on that second page. Whenever I try to reach a Stacklayout inside that Page, the following error shows up: 'Page1.camera' is inaccessible due to its protection level.
Using x:FieldModifier="public" inside that stacklayout doesn't work either.
Here is the structure of my code to make it more clear
Here I make the tabbed pages:
MainPage = new TabbedPage
{
Children = {
new MainPage(),
new Page1(),
new Page2()
}
};
Inside that Page1 i have this:
<?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="App4.Page1"
Title="Licht">
<StackLayout x:Name="camera" x:FieldModifier="public" Orientation="Vertical">
</StackLayout>
</ContentPage>
And inside the MainActivity.cs i have this where i have to access the camera.
_textureView = new TextureView(Page1.camera);
And this is the structure of my app
And this is the structure of my app
Using x:FieldModifier="public" inside that stacklayout doesn't work either.
I have tried x:FieldModifier="public"in xamarin form, even though I use x:FieldModifier="public", the "camera" property is still private. This feature is not useful.
As far as I know there is no way to access "camera" inside MainActivity.cs in Xamarin form.
As a workaround you can design a page render for android platform and create a TextureView in your page render code.
how to create a page render
_textureView = new TextureView(Page1.camera);
BTW to initialize TextureView you need the object that implements the ISurfaceTextureListener interface at android platform.
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,ISurfaceTextureListener
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
TextureView textureView = new TextureView(this);
textureView.SurfaceTextureListener = this;
LoadApplication(new App());
}
public void OnSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
//start
}
public bool OnSurfaceTextureDestroyed(SurfaceTexture surface)
{
//stop
}
public void OnSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)
{
throw new NotImplementedException();
}
public void OnSurfaceTextureUpdated(SurfaceTexture surface)
{
throw new NotImplementedException();
}
}
Please follow the TextureView guide for Android.

Resources