diff --git a/Xamarin.Forms.ControlGallery.Android/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.Android/CustomRenderers.cs
index e6d70b96abf..e94afd93874 100644
--- a/Xamarin.Forms.ControlGallery.Android/CustomRenderers.cs
+++ b/Xamarin.Forms.ControlGallery.Android/CustomRenderers.cs
@@ -115,7 +115,7 @@ protected override void UpdateMenuItemIcon(Context context, IMenuItem menuItem,
if (toolBarItem.IconImageSource is FileImageSource fileImageSource)
{
var name = IOPath.GetFileNameWithoutExtension(fileImageSource.File);
- var id = Xamarin.Forms.Platform.Android.ResourceManager.GetDrawableByName(name);
+ var id = context.GetDrawableId(name);
if (id != 0)
{
if ((int)Build.VERSION.SdkInt >= 21)
diff --git a/Xamarin.Forms.ControlGallery.Android/FormsAppCompatActivity.cs b/Xamarin.Forms.ControlGallery.Android/FormsAppCompatActivity.cs
index d239b290489..7c910891cd3 100644
--- a/Xamarin.Forms.ControlGallery.Android/FormsAppCompatActivity.cs
+++ b/Xamarin.Forms.ControlGallery.Android/FormsAppCompatActivity.cs
@@ -51,6 +51,12 @@ protected override void OnCreate(Bundle bundle)
#endif
Forms.Init(this, bundle);
+ // null out the assembly on the Resource Manager
+ // so all of our tests run without using the reflection APIs
+ // At some point the Resources class types will go away so
+ // reflection will stop working
+ ResourceManager.Init(null);
+
FormsMaps.Init(this, bundle);
FormsMaterial.Init(this, bundle);
AndroidAppLinks.Init(this);
diff --git a/Xamarin.Forms.Platform.Android.UnitTests/ButtonTests.cs b/Xamarin.Forms.Platform.Android.UnitTests/ButtonTests.cs
index e56172ef76a..8e127fc9749 100644
--- a/Xamarin.Forms.Platform.Android.UnitTests/ButtonTests.cs
+++ b/Xamarin.Forms.Platform.Android.UnitTests/ButtonTests.cs
@@ -12,6 +12,7 @@
using Xamarin.Forms;
using Xamarin.Forms.CustomAttributes;
using AColor = Android.Graphics.Color;
+using AContextThemeWrapper = Android.Support.V7.View.ContextThemeWrapper;
namespace Xamarin.Forms.Platform.Android.UnitTests
{
@@ -95,25 +96,26 @@ public void StyleTextAllCapsSettingIsRespected()
}
// This is the ideal test for Issue11703. It's currently being tabled due to a Resource linking bug that we're working out with Android team
- //[Category("Button")]
- //[Description("Account for user's setting of styles property textAllCaps")]
- //[Issue(IssueTracker.Github, 11703, "[Bug] Android textAllCaps no longer works", issueTestNumber: 1)]
- //[TestCase(false)]
- //[TestCase(true)]
- //public void StyleTextAllCapsSettingIsRespected(bool allCaps)
- //{
- // ContextThemeWrapper contextThemeWrapper = null;
- // if (allCaps)
- // contextThemeWrapper = new ContextThemeWrapper(Context, Resource.Style.TextAllCapsStyleTrue);
- // else
- // contextThemeWrapper = new ContextThemeWrapper(Context, Resource.Style.TextAllCapsStyleFalse);
+ /*[Category("Button")]
+ [Description("Account for user's setting of styles property textAllCaps")]
+ [Issue(IssueTracker.Github, 11703, "[Bug] Android textAllCaps no longer works", issueTestNumber: 1)]
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task StyleTextAllCapsSettingIsRespected(bool allCaps)
+ {
+ AContextThemeWrapper contextThemeWrapper = null;
+ if (allCaps)
+ contextThemeWrapper = new AContextThemeWrapper(Context, Context.GetStyle("TextAllCapsStyleTrue"));
+ else
+ contextThemeWrapper = new AContextThemeWrapper(Context, Context.GetStyle("TextAllCapsStyleFalse"));
- // var button = new Button { Text = "foo" };
- // var buttonControl = GetRenderer(button, contextThemeWrapper).View as AppCompatButton;
- // var initialTextTransform = buttonControl.TransformationMethod;
+ var button = new Button { Text = "foo" };
+ var initialTextTransform = await GetControlProperty(button, x => x.TransformationMethod);
- // Assert.AreEqual(allCaps, initialTextTransform is AllCapsTransformationMethod);
- //}
+ // when set through a style the type is an internal version of AllCapsTransformationMethod
+ string typeName = $"{initialTextTransform}";
+ Assert.AreEqual(allCaps, typeName.Contains("AllCapsTransformationMethod"));
+ }*/
}
}
diff --git a/Xamarin.Forms.Platform.Android.UnitTests/ResourceManagerTests.cs b/Xamarin.Forms.Platform.Android.UnitTests/ResourceManagerTests.cs
new file mode 100644
index 00000000000..c2d457985f4
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android.UnitTests/ResourceManagerTests.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Threading.Tasks;
+using Android.Views;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Platform.Android.UnitTests
+{
+ [TestFixture]
+ public class ResourceManagerTests : PlatformTestFixture
+ {
+ [Test, Category("Resource")]
+ [Description("Retrieve Resources by Name")]
+ public void RetrieveResourcesByName()
+ {
+ ResourceManager.Init(null);
+ ResourceManager.DrawableClass = null;
+ ResourceManager.LayoutClass = null;
+ ResourceManager.ResourceClass = null;
+ ResourceManager.StyleClass = null;
+
+ Assert.Greater(ResourceManager.GetDrawableId(this.Context, "DrawableTEST"), 0);
+ Assert.Greater(ResourceManager.GetDrawableId(this.Context, "DrawableTEST.png"), 0);
+ Assert.Greater(ResourceManager.GetLayout(this.Context, "LayoutTest"), 0);
+ Assert.Greater(ResourceManager.GetStyle(this.Context, "TextAllCapsStyleTrue"), 0);
+ Assert.Greater(ResourceManager.GetResource(this.Context, "namewith.adot"), 0);
+ Assert.Greater(ResourceManager.GetResource(this.Context, "namewith_adot"), 0);
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Platform.Android.UnitTests/Resources/drawable/DrawableTest.png b/Xamarin.Forms.Platform.Android.UnitTests/Resources/drawable/DrawableTest.png
new file mode 100644
index 00000000000..fbf2947e12a
Binary files /dev/null and b/Xamarin.Forms.Platform.Android.UnitTests/Resources/drawable/DrawableTest.png differ
diff --git a/Xamarin.Forms.Platform.Android.UnitTests/Resources/layout/LayoutTest.axml b/Xamarin.Forms.Platform.Android.UnitTests/Resources/layout/LayoutTest.axml
new file mode 100644
index 00000000000..cc009618c21
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android.UnitTests/Resources/layout/LayoutTest.axml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android.UnitTests/Xamarin.Forms.Platform.Android.UnitTests.csproj b/Xamarin.Forms.Platform.Android.UnitTests/Xamarin.Forms.Platform.Android.UnitTests.csproj
index bac8d468ac5..8daa803ef28 100644
--- a/Xamarin.Forms.Platform.Android.UnitTests/Xamarin.Forms.Platform.Android.UnitTests.csproj
+++ b/Xamarin.Forms.Platform.Android.UnitTests/Xamarin.Forms.Platform.Android.UnitTests.csproj
@@ -70,6 +70,7 @@
+
@@ -97,6 +98,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Platform.cs b/Xamarin.Forms.Platform.Android/Platform.cs
index e4dc4448fdd..984eb84c6ab 100644
--- a/Xamarin.Forms.Platform.Android/Platform.cs
+++ b/Xamarin.Forms.Platform.Android/Platform.cs
@@ -803,7 +803,7 @@ void GetNewMasterDetailToggle()
if (fileImageSource == null)
throw new InvalidOperationException("Icon property must be a FileImageSource on Master page");
- int icon = ResourceManager.GetDrawableByName(fileImageSource);
+ int icon = _activity.GetDrawableId(fileImageSource);
FastRenderers.AutomationPropertiesProvider.GetDrawerAccessibilityResources(_activity, CurrentMasterDetailPage, out int resourceIdOpen, out int resourceIdClose);
#pragma warning disable 618 // Eventually we will need to determine how to handle the v7 ActionBarDrawerToggle for AppCompat
diff --git a/Xamarin.Forms.Platform.Android/Renderers/AndroidGIFImageParser.cs b/Xamarin.Forms.Platform.Android/Renderers/AndroidGIFImageParser.cs
index aa950008aa3..7689f5b2c39 100644
--- a/Xamarin.Forms.Platform.Android/Renderers/AndroidGIFImageParser.cs
+++ b/Xamarin.Forms.Platform.Android/Renderers/AndroidGIFImageParser.cs
@@ -194,7 +194,7 @@ public override bool SelectDrawable(int index)
InJustDecodeBounds = true
};
- int drawableIdentifier = ResourceManager.GetDrawableByName(file);
+ int drawableIdentifier = context.GetDrawableId(file);
if (drawableIdentifier != 0)
{
diff --git a/Xamarin.Forms.Platform.Android/ResourceManager.cs b/Xamarin.Forms.Platform.Android/ResourceManager.cs
index c6037561c3f..089991b6e01 100644
--- a/Xamarin.Forms.Platform.Android/ResourceManager.cs
+++ b/Xamarin.Forms.Platform.Android/ResourceManager.cs
@@ -29,7 +29,7 @@ public static class ResourceManager
static Assembly _assembly;
static Type FindType(string name, string altName)
{
- return _assembly.GetTypes().FirstOrDefault(x => x.Name == name || x.Name == altName);
+ return _assembly?.GetTypes().FirstOrDefault(x => x.Name == name || x.Name == altName);
}
static Type _drawableClass;
static Type _resourceClass;
@@ -93,7 +93,7 @@ public static Type LayoutClass {
if (imageSource is FileImageSource fileImageSource)
{
var file = fileImageSource.File;
- var id = IdFromTitle(file, DrawableClass);
+ var id = IdFromTitle(file, DrawableClass, "drawable", context);
// try the drawables via id
if (id != 0)
@@ -353,19 +353,35 @@ public static Drawable GetDrawable(this Context context, string name)
return AndroidAppCompat.GetDrawable(context, id);
}
+ public static int GetDrawableId(this Context context, string title)
+ {
+ return IdFromTitle(title, DrawableClass, _drawableDefType, context);
+ }
+
+ [Obsolete("GetDrawableByName(string) is obsolete as of version 4.8. "
+ + "Please use GetDrawableId(string, context) instead.")]
public static int GetDrawableByName(string name)
{
- return IdFromTitle(name, DrawableClass);
+ return IdFromTitle(name, DrawableClass, _drawableDefType, Forms.ApplicationContext);
}
+ [Obsolete("GetResourceByName(string) is obsolete as of version 4.8. "
+ + "Please use GetResource(string, context) instead.")]
public static int GetResourceByName(string name)
{
- return IdFromTitle(name, ResourceClass);
+ return IdFromTitle(name, ResourceClass, "id", Forms.ApplicationContext);
+ }
+
+ public static int GetResource(this Context context, string title)
+ {
+ return IdFromTitle(title, ResourceClass, "id", context);
}
+ [Obsolete("GetLayoutByName(string) is obsolete as of version 4.8. "
+ + "Please use GetLayout(string, context) instead.")]
public static int GetLayoutByName(string name)
{
- return IdFromTitle(name, LayoutClass);
+ return IdFromTitle(name, LayoutClass, "layout", Forms.ApplicationContext);
}
public static int GetLayout(this Context context, string name)
@@ -373,9 +389,11 @@ public static int GetLayout(this Context context, string name)
return IdFromTitle(name, LayoutClass, "layout", context);
}
+ [Obsolete("GetStyleByName(string) is obsolete as of version 4.8. "
+ + "Please use GetStyle(string, context) instead.")]
public static int GetStyleByName(string name)
{
- return IdFromTitle(name, StyleClass);
+ return IdFromTitle(name, StyleClass, "style", Forms.ApplicationContext);
}
public static int GetStyle(this Context context, string name)
@@ -388,16 +406,6 @@ public static void Init(Assembly masterAssembly)
_assembly = masterAssembly;
}
- static int IdFromTitle(string title, Type type)
- {
- if (title == null)
- return 0;
-
- string name = IOPath.GetFileNameWithoutExtension(title);
- int id = GetId(type, name);
- return id;
- }
-
static int IdFromTitle(string title, Type resourceType, string defType, Resources resource)
{
return IdFromTitle(title, resourceType, defType, resource, AppCompat.Platform.GetPackageName());
@@ -405,7 +413,7 @@ static int IdFromTitle(string title, Type resourceType, string defType, Resource
static int IdFromTitle(string title, Type resourceType, string defType, Context context)
{
- return IdFromTitle(title, resourceType, defType, context.Resources, context.PackageName);
+ return IdFromTitle(title, resourceType, defType, context?.Resources, context?.PackageName);
}
static int IdFromTitle(string title, Type resourceType, string defType, Resources resource, string packageName)
@@ -414,24 +422,38 @@ static int IdFromTitle(string title, Type resourceType, string defType, Resource
if (title == null)
return id;
- string name = IOPath.GetFileNameWithoutExtension(title);
+ string name;
- id = GetId(resourceType, name);
+ if (defType == "style" || (resourceType != null && resourceType == StyleClass))
+ name = title;
+ else
+ name = title.ToLower();
- if (id > 0)
+ if (defType == _drawableDefType || (resourceType != null && resourceType == DrawableClass))
+ name = IOPath.GetFileNameWithoutExtension(name);
+
+ if ((id = SearchByIdentifier(name, defType, resource, packageName)) > 0)
return id;
- if (packageName != null)
+ // When searching by reflection you would use a "_" instead of a "."
+ // So this accounts for cases where users were searching with an "_"
+ if ((id = SearchByIdentifier(name.Replace("_", "."), defType, resource, packageName)) > 0)
+ return id;
+
+ int SearchByIdentifier(string n, string d, Resources r, string p)
{
- id = resource.GetIdentifier(name, defType, packageName);
+ int returnValue = 0;
- if (id > 0)
- return id;
- }
+ if (p != null)
+ returnValue = r.GetIdentifier(n, d, p);
- id = resource.GetIdentifier(name, defType, null);
+ if (returnValue == 0)
+ returnValue = r.GetIdentifier(n, d, null);
+
+ return returnValue;
+ }
- return id;
+ return GetId(resourceType, name);
}
static int GetId(Type type, string memberName)