Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[regression/8.0.0-preview.4.8333] [Android] Setting the background property of AppCompatEditText in a handler mapping does not work #18720

Closed
matt-goldman opened this issue Nov 13, 2023 · 34 comments · Fixed by #22573
Assignees
Labels
area-controls-entry Entry fixed-in-8.0.90 fixed-in-9.0.0-rc.1.24453.9 i/regression This issue described a confirmed regression on a currently supported version p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Milestone

Comments

@matt-goldman
Copy link
Contributor

matt-goldman commented Nov 13, 2023

Description

In a .NET MAUI project using the latest .NET 8 RC, setting the background property of a AppCompatEditText doesn't seem to work.

Using this code:

Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("TestEntry", (handler, view) =>
{
    handler.PlatformView.Background = null;
    handler.PlatformView.SetBackgroundColor(Android.Graphics.Color.Pink);
    handler.PlatformView.SetTextColor(Android.Graphics.Color.Aqua);
});

Has the following results:

image

❌ Figure: PlatformView background properties not applied, but other mappings are applied

image

✅ Figure: The same code in .NET 7

Repro is linked below. Repo with working version in .NET 7: https://github.com/matt-goldman/Net7AndroidHandlers

Steps to Reproduce

  1. Create a .NET MAUI app in .NET 8
  2. Create a handler mapping to set the background of the PlatformView for Entry
  3. Add an Entry to your UI
  4. Run the app, observe bug 🐞

Link to public reproduction project repository

https://github.com/matt-goldman/Net8AndroidHandlers

Version with bug

8.0.0-preview.4.8333

Is this a regression from previous behavior?

Yes, this used to work in .NET MAUI

Last version that worked well

8.0.0-preview.3.8149

Affected platforms

Android

Affected platform versions

Android - all versions

Did you find any workaround?

I could not find a workaround

Relevant log output

No response

@matt-goldman matt-goldman added the t/bug Something isn't working label Nov 13, 2023
@jsuarezruiz jsuarezruiz added area-controls-entry Entry potential-regression This issue described a possible regression on a currently supported version., verification pending labels Nov 14, 2023
@ghost ghost added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label Nov 14, 2023
@ieuangriffiths97
Copy link

Came across the same issue just commenting to keep track of this issue.

@borrmann
Copy link
Contributor

also applies to Picker and Editors

@borrmann
Copy link
Contributor

anyone have a workaround?

@matt-goldman
Copy link
Contributor Author

@borrmann I expect the team will fix this pretty quickly as it will affect everyone. And probably the controls vendors too.

@XamlTest XamlTest added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed labels Nov 16, 2023
@XamlTest
Copy link

Verified this on Visual Studio Enterprise 17.9.0 Preview 1. Repro on Android 14.0-API34(8.0.3), not repro on Android 14.0-API34(7.0.101) with below Project:
Net8AndroidHandlers.zip

@vhugogarcia
Copy link
Contributor

Hello @matt-goldman , it appears this is not a .NET MAUI 8/7 issue. On this post found in StackOverflow, the Android developers shared that to change the edit text line color we must use BackgroundTint, and we should not use BackgroundColor.

Honestly, I was like you, I have been using the background color to remove the line color on Android in .NET MAUI 7, but after reviewing I was able to remove the bottom line of the edit text on android in my .NET MAUI 8 projects, by using the following code line on my handler:
handler.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());

I updated my article on my blog, reflecting this change: So, based on the findings, I believe this is not a bug of .NET MAUI and instead we were setting wrong the code to hide the Entry form control border in Android. I just wanted to share my grain of salt @jsuarezruiz .

I hope this helps other developers!

Reference of the official Android documentation: https://developer.android.com/reference/androidx/core/view/TintableBackgroundView

Thanks in advance.

cc: @XamlTest @borrmann @ieuangriffiths97

@matt-goldman
Copy link
Contributor Author

Nice catch @vhugogarcia! Thanks for this, and the write-up too!

@vhugogarcia
Copy link
Contributor

Nice catch @vhugogarcia! Thanks for this, and the write-up too!

Happy to help. Please feel free to close this issue if you believe it has been solved.

@matt-goldman
Copy link
Contributor Author

Do we know what changed between .NET 8 and .NET 7?

@vitalbit
Copy link

vitalbit commented Nov 28, 2023

@vhugogarcia, @matt-goldman

I believe there is still handler.PlatformView.Background setter, that is required to be fixed. Meanwhile we have ability to remove line for entry with Colors.Transparent approach, we still not able to update Background with any native Android.Graphics.Drawables.Drawable in .NET8.

@samhouts
Copy link
Member

samhouts commented Dec 7, 2023

Hey friends! From reading the comments, it looks like this can be closed. Is there further action required from the MAUI team? Thanks!

@samhouts samhouts added the s/needs-info Issue needs more info from the author label Dec 7, 2023
@ghost
Copy link

ghost commented Dec 7, 2023

Hi @matt-goldman. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@vitalbit
Copy link

vitalbit commented Dec 8, 2023

Hello @samhouts,
I prepared sample to show that Background property of AppCompatEditText does not apply changes. In the project you can find CustomEntryHandler.cs which change Background to round violet border and usage of CustomEntry.cs in MainPage.xaml.

https://github.com/vitalbit/AndroidEntryBackgroundChangeSample/

master branch - provides .NET 7 project, which works fine.
Screenshot_1702025338

net8-migration branch - provides .NET 8 project, with background issue.
Screenshot_1702025575

The workaround mentioned above provides possibility to remove underline for Android, meanwhile we still can not fully control Background natively for Android, that's why I believe this bug should still be in Open state.

@ghost ghost added s/needs-attention Issue has more information and needs another look and removed s/needs-info Issue needs more info from the author labels Dec 8, 2023
@samhouts samhouts changed the title [Regression][Android] Setting the background property of AppCompatEditText in a handler mapping does not work [regression/8.0.3] [Android] Setting the background property of AppCompatEditText in a handler mapping does not work Dec 8, 2023
@zh0018
Copy link

zh0018 commented Jan 30, 2024

I have tested it in version 8.06 and still have this issue

Hello @samhouts, I prepared sample to show that Background property of AppCompatEditText does not apply changes. In the project you can find CustomEntryHandler.cs which change Background to round violet border and usage of CustomEntry.cs in MainPage.xaml.

https://github.com/vitalbit/AndroidEntryBackgroundChangeSample/

master branch - provides .NET 7 project, which works fine. Screenshot_1702025338

net8-migration branch - provides .NET 8 project, with background issue. Screenshot_1702025575

The workaround mentioned above provides possibility to remove underline for Android, meanwhile we still can not fully control Background natively for Android, that's why I believe this bug should still be in Open state.

@ALJASAC
Copy link

ALJASAC commented Feb 11, 2024

I came here with the same issue, please this needs attention.

@ieuangriffiths97
Copy link

Any update from the MAUI team on when this will be fixed? This is stopping me from using .NET 8 Android in production. .NET 7 end of life is in May.

@Kirill-Novozhilov
Copy link

Kirill-Novozhilov commented Mar 21, 2024

Are there any workarounds, on how to change the line color in EditText and setting a background color in so that it works?

If set the BackgroundColor and set the BackgroundTintList in handler, then the whole view gets the color of the tintlist.

@samhouts samhouts removed s/needs-attention Issue has more information and needs another look potential-regression This issue described a possible regression on a currently supported version., verification pending labels Apr 10, 2024
@knasher
Copy link

knasher commented Jul 13, 2024

I can confirm this is still happening in 8.0.70

@mackayn
Copy link

mackayn commented Jul 29, 2024

Just ran into this too, applying a gradient has no effect in the handler in Android.

 public class AndroidBorderedEntryHandler : EntryHandler
 {
     protected override AppCompatEditText CreatePlatformView()
     {
         var nativeView =  base.CreatePlatformView();
         if (VirtualView is BorderedEntry entry)
         {
             // Remove underline
             nativeView.BackgroundTintList = ColorStateList.ValueOf(Color.Transparent);

             GradientDrawable gd = new GradientDrawable();
             gd.SetCornerRadius(3);
             gd.SetStroke(1, entry.BorderColor.ToAndroid());
             nativeView.Background = gd;
             return nativeView;
         }
         return nativeView;
     }
 }

MAUI 8.0.70

@PureWeen PureWeen modified the milestones: .NET 8 SR8, .NET 8 SR9 Jul 30, 2024
@tbaggett
Copy link

tbaggett commented Aug 3, 2024

+1

@PureWeen PureWeen moved this from In Progress to Ready To Review in MAUI SDK Ongoing Aug 12, 2024
@mattleibow
Copy link
Member

mattleibow commented Aug 19, 2024

This all looks very complicated with the append mapper and/or custom handler. It appears you want to replace the background? We have a feature for that since net6:

builder.ConfigureMauiHandlers(handlers =>
{
#if ANDROID
    EntryHandler.Mapper.ReplaceMapping<IEntry, IEntryHandler>("Background", (handler, view) =>
    {
        var platformView = handler.PlatformView;

        // Android will reset the padding when setting a Background drawable, so we need to reapply the padding after
        var padLeft = platformView.PaddingLeft;
        var padTop = platformView.PaddingTop;
        var padRight = platformView.PaddingRight;
        var padBottom = platformView.PaddingBottom;

        // Set the custom background
        var gd = new Android.Graphics.Drawables.GradientDrawable();
        gd.SetCornerRadius(3);
        gd.SetStroke(1, Android.Graphics.Color.Red);
        gd.SetColor(Android.Graphics.Color.Pink);
        platformView.Background = gd;

        // Apply previous padding
        platformView.SetPadding(padLeft, padTop, padRight, padBottom);
    });
#endif
});

This results in:

Screenshot_1724076838

@pmahend1
Copy link

Thank you! @mattleibow . This is really helpful.
Looks like we need more documentation on when to use AppendMapping and when to use ReplaceMapping.

@mackayn
Copy link

mackayn commented Aug 19, 2024

This all looks very complicated with the append mapper and/or custom handler. It appears you want to replace the background? We have a feature for that since net6:

builder.ConfigureMauiHandlers(handlers =>
{
#if ANDROID
    EntryHandler.Mapper.ReplaceMapping<IEntry, IEntryHandler>("Background", (handler, view) =>
    {
        var platformView = handler.PlatformView;

        // Android will reset the padding when setting a Background drawable, so we need to reapply the padding after
        var padLeft = platformView.PaddingLeft;
        var padTop = platformView.PaddingTop;
        var padRight = platformView.PaddingRight;
        var padBottom = platformView.PaddingBottom;

        // Set the custom background
        var gd = new Android.Graphics.Drawables.GradientDrawable();
        gd.SetCornerRadius(3);
        gd.SetStroke(1, Android.Graphics.Color.Red);
        gd.SetColor(Android.Graphics.Color.Pink);
        platformView.Background = gd;

        // Apply previous padding
        platformView.SetPadding(padLeft, padTop, padRight, padBottom);
    });
#endif
});

This results in:

Screenshot_1724076838

Thanks but not really what I was trying to achieve, is there a way to apply using this approach to a subclassed control ? this would apply to all entries in the app. I can add a mapper to my custom handler I suppose, it's just pretty clunky...

@pmahend1
Copy link

pmahend1 commented Aug 19, 2024

@mackayn I was able to apply it for sub-classed control
Here is how I did it.

MauiProgram.cs

 MauiApp.CreateBuilder().ConfigureMauiHandlers(handlers =>
 {
     handlers.AddHandler(typeof(BorderedEntry), typeof(BorderedEntryHandler));
 });

Created BorderedEntryHandler in Platforms/Android, namespace has to be same as of MauiProgram

public partial class BorderedEntryHandler : EntryHandler
{
    public BorderedEntryHandler()
    {
        Mapper.ReplaceMapping<IEntry, IEntryHandler>("Background", BorderedEntryMapper);
    }

    private void BorderedEntryMapper(IEntryHandler handler, IEntry entry)
    {
        var platformView = handler.PlatformView;

        // Android will reset the padding when setting a Background drawable, so we need to reapply the padding after
        var padLeft = platformView.PaddingLeft;
        var padTop = platformView.PaddingTop;
        var padRight = platformView.PaddingRight;
        var padBottom = platformView.PaddingBottom;

        // Set the custom background
        var gd = new Android.Graphics.Drawables.GradientDrawable();
        gd.SetCornerRadius(3);
        gd.SetStroke(1, Android.Graphics.Color.Red);
        gd.SetColor(Android.Graphics.Color.Pink);
        platformView.Background = gd;

        // Apply previous padding
        platformView.SetPadding(padLeft, padTop, padRight, padBottom);
   }
}

@mackayn
Copy link

mackayn commented Aug 19, 2024

@mackayn I was able to apply it for sub-classed control Here is how I did it.

MauiProgram.cs

 MauiApp.CreateBuilder().ConfigureMauiHandlers(handlers =>
 {
     handlers.AddHandler(typeof(BorderedEntry), typeof(BorderedEntryHandler));
 });

Created BorderedEntryHandler in Platforms/Android, namespace has to be same as of MauiProgram

public partial class BorderedEntryHandler : EntryHandler
{
    public BorderedEntryHandler()
    {
        Mapper.ReplaceMapping<IEntry, IEntryHandler>("Background", BorderedEntryMapper);
    }

    private void BorderedEntryMapper(IEntryHandler handler, IEntry entry)
    {
        var platformView = handler.PlatformView;

        // Android will reset the padding when setting a Background drawable, so we need to reapply the padding after
        var padLeft = platformView.PaddingLeft;
        var padTop = platformView.PaddingTop;
        var padRight = platformView.PaddingRight;
        var padBottom = platformView.PaddingBottom;

        // Set the custom background
        var gd = new Android.Graphics.Drawables.GradientDrawable();
        gd.SetCornerRadius(3);
        gd.SetStroke(1, Android.Graphics.Color.Red);
        gd.SetColor(Android.Graphics.Color.Pink);
        platformView.Background = gd;

        // Apply previous padding
        platformView.SetPadding(padLeft, padTop, padRight, padBottom);
   }
}

I never thought of consuming the API that way, your 100% right about needing more documentation on mappers, I'm guessing some of these 3.5K open issues are this type of thing, a misunderstanding of the mappers API. That's working very nicely, thanks.

@mattleibow
Copy link
Member

mattleibow commented Aug 19, 2024

You should be able to override the behaviour using the generics (note the use of BorderedEntry instead of IEntry:

EntryHandler.Mapper.ReplaceMapping<BorderedEntry, IEntryHandler>("Background", (handler, view) =>
{
    // your code here
});
public class BorderedEntry : Entry
{
}

With this XAML where once is a normal entry and the other is a custom one, the mapper only applies to the custom one - without requiring a new handler and new handler registration. We basically register the mapper as a smaller unit.

<Entry
    Text="Hello, World!"
    Background="Orange" />

<local:BorderedEntry
    Text="Hello, World!"
    Background="Orange" />

@PureWeen PureWeen assigned mattleibow and unassigned samhouts Aug 19, 2024
@mackayn
Copy link

mackayn commented Aug 19, 2024

You should be able to override the behaviour using the generics (note the use of BorderedEntry instead of IEntry:

EntryHandler.Mapper.ReplaceMapping<BorderedEntry, IEntryHandler>("Background", (handler, view) =>
{
    // your code here
});
public class BorderedEntry : Entry
{
}

With this XAML where once is a normal entry and the other is a custom one, the mapper only applies to the custom one - without requiring a new handler and new handler registration. We basically register the mapper as a smaller unit.

<Entry
    Text="Hello, World!"
    Background="Orange" />

<local:BorderedEntry
    Text="Hello, World!"
    Background="Orange" />

Nice, worked well for the Editor too.

@github-project-automation github-project-automation bot moved this from In Progress to Done in MAUI SDK Ongoing Aug 21, 2024
@pmahend1
Copy link

@mackayn how were you able to make it work for Editor. As soon as I set Background or BackgroundTintList the background color is getting reset to white. It is annoyingly evident in Dark theme mode. I tried replace and append mapper both

@borrmann
Copy link
Contributor

@pmahend1
I use this:

public partial class MyEditorHandler : Microsoft.Maui.Handlers.EditorHandler
{
    protected override void ConnectHandler(AppCompatEditText platformView)
    {
        base.ConnectHandler(platformView);

        if(platformView != null)
        {
            // remove the line below text
            platformView.SetBackgroundColor(Color.Transparent);
            platformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Color.Transparent);
        }
    }

@pmahend1
Copy link

@borrmann Thanks but I had tried the same logic. I am on Android 34 if that matters.

@mackayn
Copy link

mackayn commented Sep 19, 2024

@mackayn how were you able to make it work for Editor. As soon as I set Background or BackgroundTintList the background color is getting reset to white. It is annoyingly evident in Dark theme mode. I tried replace and append mapper both

Sorry, on vacation, not near a dev env but if you setup the correct handler type it works for editor in iOS and Android, don't override ConnectHandler.

https://learn.microsoft.com/en-us/dotnet/maui/user-interface/handlers/?view=net-maui-8.0#view-handlers. Use the approach recommended by @mattleibow

@github-actions github-actions bot locked and limited conversation to collaborators Nov 17, 2024
@sheiksyedm sheiksyedm added partner/syncfusion Issues / PR's with Syncfusion collaboration and removed partner/syncfusion Issues / PR's with Syncfusion collaboration labels Dec 17, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-controls-entry Entry fixed-in-8.0.90 fixed-in-9.0.0-rc.1.24453.9 i/regression This issue described a confirmed regression on a currently supported version p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.