Skip to content

Commit fa25606

Browse files
[Android] Fixed Material controls themeing issue (#30415)
* Fixed Exception * Optimized code * Updated fix * fixed checkbox * enabled android test * Fixed typo
1 parent e45c383 commit fa25606

5 files changed

Lines changed: 150 additions & 4 deletions

File tree

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#if ANDROID
2+
using Android.Content;
3+
using Android.OS;
4+
using View = Android.Views.View;
5+
using Google.Android.Material.BottomSheet;
6+
#endif
7+
using Microsoft.Maui.Platform;
8+
namespace Maui.Controls.Sample.Issues;
9+
10+
[Issue(IssueTracker.Github, 13356, "Java.Lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.MaterialComponent.", PlatformAffected.Android)]
11+
public class Issue13356 : TestContentPage
12+
{
13+
protected override void Init()
14+
{
15+
var stack = new VerticalStackLayout
16+
{
17+
Spacing = 25,
18+
Padding = new Thickness(30, 0),
19+
VerticalOptions = LayoutOptions.Center,
20+
Children =
21+
{
22+
CreateButton("Show Button Dialog", "showButtonDialogButton", Button_Dialog_clicked),
23+
CreateButton("Show CheckBox Dialog", "showCheckBoxDialogButton", CheckBox_Dialog_clicked),
24+
}
25+
};
26+
27+
Content = new ScrollView { Content = stack };
28+
}
29+
30+
Button CreateButton(string text, string automationId, EventHandler eventHandler) =>
31+
new()
32+
{
33+
Text = text,
34+
AutomationId = automationId,
35+
HorizontalOptions = LayoutOptions.Center,
36+
Command = new Command(() => eventHandler?.Invoke(this, EventArgs.Empty))
37+
};
38+
39+
void Button_Dialog_clicked(object sender, EventArgs e)
40+
{
41+
#if ANDROID
42+
var droidContext = Handler.MauiContext.Context;
43+
using var myDialog = new Issue13356Dialog(droidContext)
44+
{
45+
Content = new Button { Text = "Dialog Button", Padding = new Thickness(30) }
46+
.ToPlatform(Application.Current.Handler.MauiContext)
47+
};
48+
myDialog.ShowDialog();
49+
#endif
50+
}
51+
52+
void CheckBox_Dialog_clicked(object sender, EventArgs e)
53+
{
54+
#if ANDROID
55+
var droidContext = Handler.MauiContext.Context;
56+
using var myDialog = new Issue13356Dialog(droidContext)
57+
{
58+
Content = new CheckBox(){AutomationId = "DialogCheckBox" }
59+
.ToPlatform(Application.Current.Handler.MauiContext)
60+
};
61+
myDialog.ShowDialog();
62+
#endif
63+
}
64+
65+
#if ANDROID
66+
public class Issue13356Dialog : BottomSheetDialog
67+
{
68+
public View Content { get; set; }
69+
70+
public Issue13356Dialog(Context context) : base(context) { }
71+
72+
protected override void OnCreate(Bundle savedInstanceState)
73+
{
74+
base.OnCreate(savedInstanceState);
75+
SetContentView(Content);
76+
}
77+
78+
public void ShowDialog()
79+
{
80+
if (!IsShowing)
81+
Show();
82+
}
83+
}
84+
#endif
85+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#if ANDROID // This Issue is only reproduced in Android platform
2+
using NUnit.Framework;
3+
using UITest.Appium;
4+
using UITest.Core;
5+
6+
namespace Microsoft.Maui.TestCases.Tests.Issues;
7+
8+
public class Issue13356 : _IssuesUITest
9+
{
10+
public Issue13356(TestDevice testDevice) : base(testDevice)
11+
{
12+
}
13+
14+
protected override bool ResetAfterEachTest => true;
15+
public override string Issue => "Java.Lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.MaterialComponent.";
16+
17+
[Test]
18+
[Category(UITestCategories.Button)]
19+
public void DialogButtonAppearsWhenMaterialButtonIsTapped()
20+
{
21+
App.WaitForElement("showButtonDialogButton");
22+
App.Tap("showButtonDialogButton");
23+
App.WaitForElement("Dialog Button");
24+
}
25+
26+
[Test]
27+
[Category(UITestCategories.CheckBox)]
28+
public void DialogButtonAppearsWhenMaterialCheckBoxIsTapped()
29+
{
30+
App.WaitForElement("showCheckBoxDialogButton");
31+
App.Tap("showCheckBoxDialogButton");
32+
App.WaitForElement("DialogCheckBox");
33+
}
34+
}
35+
#endif

src/Core/src/Handlers/CheckBox/CheckBoxHandler.Android.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public partial class CheckBoxHandler : ViewHandler<ICheckBox, AppCompatCheckBox>
99
{
1010
protected override AppCompatCheckBox CreatePlatformView()
1111
{
12-
var platformCheckBox = new MaterialCheckBox(Context)
12+
var platformCheckBox = new MaterialCheckBox(MauiMaterialContextThemeWrapper.Create(Context))
1313
{
1414
SoundEffectsEnabled = false
1515
};

src/Core/src/Platform/Android/MauiMaterialButton.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@ public class MauiMaterialButton : MaterialButton
2323
internal const int IconGravityBottom = 0x1000;
2424

2525
public MauiMaterialButton(Context context)
26-
: base(context)
26+
: base(MauiMaterialContextThemeWrapper.Create(context))
2727
{
2828
}
2929

3030
protected MauiMaterialButton(nint javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
3131
{
3232
}
3333

34-
public MauiMaterialButton(Context context, IAttributeSet? attrs) : base(context, attrs)
34+
public MauiMaterialButton(Context context, IAttributeSet? attrs) : base(MauiMaterialContextThemeWrapper.Create(context), attrs)
3535
{
3636
}
3737

38-
public MauiMaterialButton(Context context, IAttributeSet? attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
38+
public MauiMaterialButton(Context context, IAttributeSet? attrs, int defStyleAttr) : base(MauiMaterialContextThemeWrapper.Create(context), attrs, defStyleAttr)
3939
{
4040
}
4141

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Android.Content;
2+
using Android.Views;
3+
4+
namespace Microsoft.Maui.Platform;
5+
6+
internal class MauiMaterialContextThemeWrapper : ContextThemeWrapper
7+
{
8+
public MauiMaterialContextThemeWrapper(Context context) : this(context, Resource.Style.Maui_MainTheme_Base)
9+
{
10+
}
11+
12+
MauiMaterialContextThemeWrapper(Context context, int themeResId) : base(context, themeResId)
13+
{
14+
15+
}
16+
17+
public static MauiMaterialContextThemeWrapper Create(Context context)
18+
{
19+
if (context is MauiMaterialContextThemeWrapper materialContext)
20+
{
21+
return materialContext;
22+
}
23+
24+
return new MauiMaterialContextThemeWrapper(context);
25+
}
26+
}

0 commit comments

Comments
 (0)