Skip to content

Instantly share code, notes, and snippets.

@jassmith
Last active October 20, 2020 14:56
Show Gist options
  • Save jassmith/a3b2a543f99126782936 to your computer and use it in GitHub Desktop.
Save jassmith/a3b2a543f99126782936 to your computer and use it in GitHub Desktop.
Xamarin.Forms FormsAppCompatActivity usage instructions

Introduction

Using the Xamarin.Forms AppCompat backend for Android enables a more modern look and feel for your app. In order to use the new backend several changes will be needed for your project.

Update Activity

The default Xamarin.Forms Activity has been the FormsApplicationActivity. All Xamarin.Forms apps derive from this Activity. The AppCompat backend is enabled by changing the base Activity to derive from FormsAppCompatActivity.

public class MyActivity : FormsApplicationActivity

becomes

public class MyActivity : FormsAppCompatActivity

Add required resources

You will need to add the following resources to your Android Application project. They should be added in the layout directory.

TabLayout.axml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.TabLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/sliding_tabs"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:tabIndicatorColor="@android:color/white"
    app:tabGravity="fill"
    app:tabMode="fixed" />

Toolbar.axml

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

You may modify the theming and properties specified on these view templates to match your theming desires.

Next let your activity know where to find these resources.

protected override void OnCreate (Bundle bundle)
{
	// Must be called before base.OnCreate (bundle);
	ToolbarResource = Resource.Layout.Toolbar;
	TabLayoutResource = Resource.Layout.TabLayout;

	base.OnCreate (bundle);

	Forms.Init (this, bundle);
	FormsMaps.Init (this, bundle);

	LoadApplication (new App ());
}

Set your application theme

Your Android Application must use an AppCompat derived theme.

Define a new theme, place this theme in your values directory.

style.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<resources>
  <style name="MyTheme" parent="MyTheme.Base">
  </style>
  <!-- Base theme applied no matter what API -->
  <style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
    <item name="windowNoTitle">true</item>
    <!--We will be using the toolbar so no need to show ActionBar-->
    <item name="windowActionBar">false</item>
    <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette-->
    <!-- colorPrimary is used for the default action bar background -->
    <item name="colorPrimary">#2196F3</item>
    <!-- colorPrimaryDark is used for the status bar -->
    <item name="colorPrimaryDark">#1976D2</item>
    <!-- colorAccent is used as the default value for colorControlActivated
         which is used to tint widgets -->
    <item name="colorAccent">#FF4081</item>
     <!-- You can also set colorControlNormal, colorControlActivated
         colorControlHighlight and colorSwitchThumbNormal. -->
    <item name="windowActionModeOverlay">true</item>

    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
  </style>

  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#FF4081</item>
  </style>
</resources>

Modify your AndroidManifest.xml to use the theme you created, it will look something like:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="AndroidControlGallery.AndroidControlGallery" android:installLocation="auto">
	<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="22" />
	<uses-permission android:name="android.permission.INTERNET" />
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
	<!-- The following two permissions are not required to use
		 Google Maps Android API v2, but are recommended. -->
	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.BATTERY_STATS" />
	<uses-permission android:name="android.permission.READ_PHONE_STATE" />
	<uses-permission android:name="android.permission.READ_LOGS" />
	<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
	<uses-feature android:glEsVersion="0x00020000" android:required="true" />
	<application android:label="YourAppName" android:theme="@style/MyTheme">
		<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="YOUR_KEY" />
		<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
	</application>
</manifest>

That should be it, all done.

@ChaseFlorell
Copy link

Nicely done.

@xabre
Copy link

xabre commented Oct 12, 2015

Very nice :). Great job!

I do have one problem, in my old FormsApplicationActivity I used to override the OnOptionsItemSelected method to intercept when the user was clicking on the back arrow icon and do some viewmodel cleanup. Apparently this method is not being called after using the FormsAppCompatActivity.
How can I intercept the "soft" back button press (toolbar icon not hard back button) ?

I also tried to override the Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer but i can't seem to override it :(

@ChaseFlorell
Copy link

What would be the trick to gaining access to the Toolbar so that we can add an Icon based on the Element.Icon?
Doing this results in toolbar == null

var iconId = ResourceManager.GetDrawableByName(Element.Icon.File);
var toolbar = FindViewById<Toolbar>(Resource.Layout.Toolbar);
if (toolbar != null)
{
    toolbar.SetNavigationIcon(iconId);
}

@Cybrosys
Copy link

The TableView does not seem to honor the Android theme settings. I get a blue holo light separator at the top of all my TableViews. I often use multiple TableSections and use the Intent.Menu.

I've never been able to find the correct theme tags to modify the dividers and colors of a TableView.

@Femilshajin
Copy link

Anybody feels MasterDetailPage Loads slower than before.. I experience performance lagging on MasterDetailPage..

@apuyana
Copy link

apuyana commented Oct 27, 2015

In my case, the back arrow is black (the theme I set has the hamburger icon white) when the client navigates to a page

@felagund18
Copy link

Hi, how can i set icons on tabLayout tabs in Android using TabbedPage?

@khanzzirfan
Copy link

Hi, the sample application Hanselman.Forms, does not have Tabbed view as shown in the original blog. Wondering how would I implement tabbed view properly (material theme).

@bozood
Copy link

bozood commented Jan 20, 2016

Hello All,
@ChaseFlorell:
Did you finally find a solution, because i have the same problem?

@patnarred
Copy link

Hi, I am not able to see options menu for the first page if we set SupportActionToolbar.

@kentcb
Copy link

kentcb commented May 27, 2016

Didn't work straight away for me in XF 2.2.0.31:

System.InvalidOperationException: Sequence contains no elements
  at System.Linq.Enumerable.Last[TSource] (IEnumerable`1 source) [0x00079] in /Users/builder/data/lanes/2923/4a7a7db5/source/mono/external/referencesource/System.Core/System/Linq/Enumerable.cs:983
  at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.OnAttachedToWindow () [0x00011] in C:\BuildAgent3\work\aad494dc9bc9783\Xamarin.Forms.Platform.Android\AppCompat\NavigationPageRenderer.cs:182
  at Android.Views.View.n_OnAttachedToWindow (IntPtr jnienv, IntPtr native__this) [0x00009] in /Users/builder/data/lanes/2923/eabab320/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Android.Views.View.cs:13912
  at at (wrapper dynamic-method) System.Object:3903b674-83ed-49f0-99ad-c30cad8bb3c7 (intptr,intptr)

The code in question includes:

Enumerable.Last<Fragment>(this._fragmentStack).UserVisibleHint = true;

It seems the compat pieces require a root page be pushed where the non-compat pieces do not. My app starts with a login dialog so I didn't bother to have a root page initially. Now looks like I'll need to dummy one in until the user authenticates.

@allbdeveloper
Copy link

Is there no way to get toolbar object??
Can't access it.
Many guys are facing same problem.
Could you help?

@pemqs
Copy link

pemqs commented Sep 14, 2016

@Femilshajin no, actually what I felt is the whole thing got 3 times slower. Master Detail flickers a lot. Components I display onAppearing or even when the page is being constructed, take 3 seconds to display on screen (and I am speaking of a very simple grid I use to simulate the bottom navigation bar for android, since the only plugin available required profile 259), and a lot more. yes it makes the thing a little closer to what google developed, but it is still way far from being android.

@pemqs
Copy link

pemqs commented Sep 14, 2016

@allbdeveloper about that, what exactly are you missing? the access to the layout files? - (which may happen a lot, specially if you are not importing (using) the proper Resources folder where you are calling the layout files) - or are you simply missing creating and setting the toolbar xml file to the Toolbar property of FormsAppCompatActivity? if needed, please post a snippet of the code you are using, please.

@mehmetavsar
Copy link

mehmetavsar commented May 3, 2017

solution : i figured out that I didn't include Xamarin.Android.Support.Design nuget package in android project.

It runs perfect on debug mode on device, but when I deploy APK release, app immediately crashes with this message:
java.lang.ClassNotFoundException: Didn't find class “android.support.v7.appcompat.R$styleable”

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment