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

Entry and Editor: option to disable borders and underline (focus) #7906

Open
leoderja opened this issue Jun 9, 2022 · 32 comments
Open

Entry and Editor: option to disable borders and underline (focus) #7906

leoderja opened this issue Jun 9, 2022 · 32 comments

Comments

@leoderja
Copy link

leoderja commented Jun 9, 2022

Description

Would be very usefull a property called HideBorder of boolean type. The same for the underline that appears bellow the control when it has the focus.

Public API Changes

<Entry HideBorder="true" HideUnderLine="true" />

Intended Use-Case

This change is useful when you need to design a cleaner UI.

@Eilon Eilon added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label Jun 9, 2022
@Symbai
Copy link
Contributor

Symbai commented Jun 9, 2022

Instead of these two boolean properties I would prefer BorderThickness (set to 0 to hide the borders) and UnderlineColor + UnderlineFocusedColor (set to transparent to hide it). This supports much more scenarios and aligns better with other control properties.

@leoderja
Copy link
Author

it doesn't necessarily have to be "instead of"... one thing doesn't invalidate the other

@leoderja leoderja changed the title Option to disable borders and underline (focus) Entry and Editor: option to disable borders and underline (focus) Jun 16, 2022
@jsuarezruiz jsuarezruiz added the t/enhancement ☀️ New feature or request label Jun 17, 2022
@jfversluis jfversluis added this to the Backlog milestone Aug 12, 2022
@ghost
Copy link

ghost commented Aug 12, 2022

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@philipag
Copy link

philipag commented Oct 2, 2022

This is really easy to do using handlers:

In CreateMauiApp add this:

Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });

Then just subclass Entry control and add the NoUnderline property and in XAML set it to True.

@balintn22
Copy link

balintn22 commented Dec 30, 2022

This is really easy to do using handlers:

In CreateMauiApp add this:

Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });

Then just subclass Entry control and add the NoUnderline property and in XAML set it to True.

Tried, works, thank you!
Instead of placing it in MauiProgram/CreateMauiApp() I placed it in Platforms/Android/MainApplication/CreateMauiApp:
`namespace MyNamespace
{
[Application]
public class MainApplication : MauiApplication
{
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
: base(handle, ownership)
{
}

    protected override MauiApp CreateMauiApp()
    {
        // Remove Entry control underline
        Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) =>
        {
            h.PlatformView.BackgroundTintList =
                Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());
        });

        return MauiProgram.CreateMauiApp();
    }
}

}`
It is for Android only, would be nice to see the magic line for iOS as well.

@GnanaPriyaNamasivayam
Copy link

Any update for iOS to remove underline ?

@kosalawije
Copy link

kosalawije commented Jan 17, 2023

Here is iOS workaround.

    public class BorderlessEntry : Entry
    {
        public BorderlessEntry() 
        {
        }       
    }

    public App()
    {
        InitializeComponent();

        SetupHandlers();

        MainPage = new AppShell();
    }
    private void SetupHandlers()
    {
        Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
        {
            if (view is BorderlessEntry)
            {

#if IOS || MACCATALYST
                handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.None;
#endif
            }
        });
    }

@GnanaPriyaNamasivayam
Copy link

GnanaPriyaNamasivayam commented Jan 17, 2023

For Android, it accepts the enum with namespace but for iOS, it does not. The app fails to compile.
image

Do you know the reason for this?

It's strange that android specific code only works inside device info platform and as common but not working when added inside compile directive so I'm trying to use the DeviceInfo platform instead.

@K0Ma19
Copy link

K0Ma19 commented Mar 27, 2023

Это очень легко сделать с помощью обработчиков:
В CreateMauiApp добавьте это:
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });
Затем просто создайте подкласс элемента управления Entry и добавьте свойство NoUnderline, а в XAML установите для него значение True.

Попробовал, работает, спасибо! Вместо того, чтобы поместить его в MauiProgram/CreateMauiApp(), я поместил его в Platforms/Android/MainApplication/CreateMauiApp: `namespace MyNamespace { [Application] public class MainApplication: MauiApplication { public MainApplication (дескриптор IntPtr, владение JniHandleOwnership) : base (дескриптор, владение ) { }

    protected override MauiApp CreateMauiApp()
    {
        // Remove Entry control underline
        Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) =>
        {
            h.PlatformView.BackgroundTintList =
                Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());
        });

        return MauiProgram.CreateMauiApp();
    }
}

}` Это только для Android, было бы неплохо увидеть волшебную строку и для iOS.

I also used this method, but I have a text in the border, which cuts it off from above, how is it possible to indent the text so that it is centered on the border?

@bradencohen
Copy link
Contributor

This would be a nice implementation. It's worth noting that the workaround in the thread doesn't seem to work on some newer versions of Android.

I wanted this behavior disabled globally (I mean it is a BorderlessEntry control), so I just set that style in the ConnectHandler:

namespace Project.Droid.Handlers
{
    public class BorderlessEntryHandler : EntryHandler
    {
        protected override void ConnectHandler( AppCompatEditText platformView )
        {
            base.ConnectHandler( platformView );

            platformView.Background = null;
            platformView.SetPadding( 0, 0, 0, 0 );

            // We do this to hide the bottom underline in MAUI.
            platformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf( Colors.Transparent.ToAndroid() );
        }
    }
}

& of course register my handler in the MauiProgram:

#if ANDROID
    handlers.AddHandler( typeof( BorderlessEntry ), typeof( Droid.Handlers.BorderlessEntryHandler ) );
#endif

@nnn149
Copy link

nnn149 commented Jun 6, 2023

使用处理程序真的很容易做到:

在CreateMauiApp中添加以下内容:

Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });

然后,只需子类 Entry 控件并添加 NoUnderline 属性,并在 XAML 中将其设置为 True。

What if I only want to change a certain entry separately? Your method is globally effective. @hartez

@philipag
Copy link

philipag commented Jun 6, 2023

@nnn149 You can make this conditional on a custom property which you can then e.g. set in XAML:

internal class OurEntry : Entry
{
public bool NoUnderline { get; set; }
}

and then

		Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(nameof(OurEntry.NoUnderline), (h, v) =>
		{
			// Remove underline:
			var oe = v as OurEntry;
			if (oe != null && oe.NoUnderline)
				h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());
		});

@nnn149
Copy link

nnn149 commented Jun 6, 2023

@nnn149 You can make this conditional on a custom property which you can then e.g. set in XAML:

internal class OurEntry : Entry
{
public bool NoUnderline { get; set; }
}

and then

		Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(nameof(OurEntry.NoUnderline), (h, v) =>
		{
			// Remove underline:
			var oe = v as OurEntry;
			if (oe != null && oe.NoUnderline)
				h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());
		});

Thank you, it works!

@BobbyCannon
Copy link

Where's the windows solutions... is Maui going to be like Xamarin where it's only iOS and Android...

@Tamirlan7
Copy link

Tamirlan7 commented Jun 19, 2023

would be nice to see for windows, but also i do not want blue underline to appear when entry is focused on windows

@Tamirlan7
Copy link

Tamirlan7 commented Jun 19, 2023

this is how i removed entry's borders for windows

public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .UseMauiCommunityToolkit()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });

#if WINDOWS
            Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderlineWindows", (h, v) =>
            {
                h.PlatformView.BorderThickness = new Microsoft.UI.Xaml.Thickness()
                {
                    Bottom = 0,
                    Top = 0,
                    Left = 0,
                    Right = 0,
                };
            });
#endif

@Dan-Banfield
Copy link

Dan-Banfield commented Jul 2, 2023

This is really easy to do using handlers:
In CreateMauiApp add this:
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });
Then just subclass Entry control and add the NoUnderline property and in XAML set it to True.

Tried, works, thank you! Instead of placing it in MauiProgram/CreateMauiApp() I placed it in Platforms/Android/MainApplication/CreateMauiApp: `namespace MyNamespace { [Application] public class MainApplication : MauiApplication { public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership) { }

    protected override MauiApp CreateMauiApp()
    {
        // Remove Entry control underline
        Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) =>
        {
            h.PlatformView.BackgroundTintList =
                Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());
        });

        return MauiProgram.CreateMauiApp();
    }
}

}` It is for Android only, would be nice to see the magic line for iOS as well.

Thanks! This works great. Is there a way to change the colour of the caret?

@enisn
Copy link

enisn commented Aug 2, 2023

Those changes are enough to remove all visual effects from the entry:

gradientDrawable.SetColor(global::Android.Graphics.Color.Transparent);
nativeView.SetBackground(gradientDrawable);

I did it for all platforms, you can take a look at it:
https://github.com/enisn/Xamarin.Forms.Plainer/blob/7015e41fb1d681b8f044f027a70e0d4b70a96f77/src/Plainer.Maui/Handlers/EntryViewHandler.cs#L36-L40

@OudomMunint
Copy link

Is there a way to just change colors of the underline?

@nelsonrc
Copy link

Those changes are enough to remove all visual effects from the entry:

gradientDrawable.SetColor(global::Android.Graphics.Color.Transparent);
nativeView.SetBackground(gradientDrawable);

I did it for all platforms, you can take a look at it: https://github.com/enisn/Xamarin.Forms.Plainer/blob/7015e41fb1d681b8f044f027a70e0d4b70a96f77/src/Plainer.Maui/Handlers/EntryViewHandler.cs#L36-L40

Net 8 Preview 7, additionally requires:
nativeView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());

@mfranc28
Copy link

mfranc28 commented Oct 4, 2023

This is really easy to do using handlers:

In CreateMauiApp add this:

Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });

Then just subclass Entry control and add the NoUnderline property and in XAML set it to True.

In my case I don't subclass Entry, Just add handler in MauiProgram and work for every Entry in my xlml pages

@mla03
Copy link

mla03 commented Oct 16, 2023

Using .net 8 (8.0.0-rc.2.9373/8.0.100-rc.2), what am I doing wrong?
I'm trying to get rid of the Entry underline in Android, and adding

Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { #if ANDROID h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); #endif });

to MauiProgram.cs will make the entire entry transparent.
Adding BackgroundColor in styles.xaml or setting it on the Entry in my .xaml file doesn't change the color. So right now I can choose from ugly underline, or no BackgroundColor?

Is the goto really to create my own entry, referencing different handlers that sets the "BackgrundTintList" to my desired BackgroundColor?

@bradencohen
Copy link
Contributor

Using .net 8 (8.0.0-rc.2.9373/8.0.100-rc.2), what am I doing wrong? I'm trying to get rid of the Entry underline in Android, and adding

Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { #if ANDROID h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); #endif });

to MauiProgram.cs will make the entire entry transparent. Adding BackgroundColor in styles.xaml or setting it on the Entry in my .xaml file doesn't change the color. So right now I can choose from ugly underline, or no BackgroundColor?

Is the goto really to create my own entry, referencing different handlers that sets the "BackgrundTintList" to my desired BackgroundColor?

I ran into this too (setting the BackgroundTintList hides any MAUI BackgroundColor), and was able to work around it like this:

// Either transparent or the provided background color
var backgroundTint = editor.BackgroundColor.IsDefault() ? Android.Content.Res.ColorStateList.ValueOf( Colors.Transparent.ToAndroid() )
: Android.Content.Res.ColorStateList.ValueOf( editor.BackgroundColor.ToAndroid() );

handler.PlatformView.BackgroundTintList = backgroundTint;

@wolfgang-ironsoftware
Copy link

wolfgang-ironsoftware commented Dec 25, 2023

this is how i removed entry's borders for windows

public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .UseMauiCommunityToolkit()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });

#if WINDOWS
            Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderlineWindows", (h, v) =>
            {
                h.PlatformView.BorderThickness = new Microsoft.UI.Xaml.Thickness()
                {
                    Bottom = 0,
                    Top = 0,
                    Left = 0,
                    Right = 0,
                };
            });
#endif

I don't think this works when the Entry is highlighted. At least I dod something similar (but not 100% the same, using a Handler) and I couldn't get this approach to work properly when entry got focused (border would appear).

However, the following seems to work fine on Windows when using handlers - this would be the native Windows implementation of a custom view:

using MauiEntry = Microsoft.Maui.Controls.Entry;

public class NativeTextField : Grid, IDisposable
{
    private readonly TextField _textField;

    private readonly TextBox _textBox;

    // keep a reference, so we can unhook event on Dispose
    private MauiEntry _entry;

    // TextField is my virtual view, a custom class that behaves a bit like an entry
    public NativeTextField(TextField textField) 
    {
        _textField = textField;

        _entry = new MauiEntry();
        _entry.Focused += Entry_Focused;
        _textBox = (TextBox)_entry.ToPlatform(textField.Handler!.MauiContext!);          
    }

    public void Dispose()
    {
        _entry.Focused -= Entry_Focused;
        
        GC.SuppressFinalize(this);
    }
    
    // when focused: recursively look for a child border and if found, hide it
    private void Entry_Focused(object? sender, Microsoft.Maui.Controls.FocusEventArgs e)
    {
        if (_textBox.GetFirstChildOfType<Border>() is Border border)
        {
            border.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
        }
    }
}

// instead of this manual implementation, could also use a CommunityToolkit WinUI Nuget package that has some Linq stuff
internal static class DependencyObjectExtensions
{
    internal static DependencyObject? GetFirstChildOfType<T>(this DependencyObject textBox) where T : DependencyObject
    {
        var childCount = VisualTreeHelper.GetChildrenCount(textBox);

        for (var i = 0; i < childCount; i++)
        {
            var child = VisualTreeHelper.GetChild(textBox, i);
            if (child.GetType().Equals(typeof(T)))
            {
                return child;
            }
            else
            {
                if (GetFirstChildOfType<T>(child) is T obj)
                {
                    return obj;
                }
            }
        }

        return null;
    }  
}

P.S.: I think more or less the same code could be used in a Behavior, which would probably be a better idea than writing a custom Entry.

@nucombo
Copy link

nucombo commented Jan 23, 2024

That works nicely to remove that bottom border of the Entry control but its not removing the border of the text when I type something in the Entry. Is there a quick hack to remove that as well?

I've tried changing the BackgroundColor as well as setting the Background to null as suggested in many links but that did not do the trick for the underline of the text when typing in the Entry.

For context, my issue is on android, by adding h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); I can perfectly fine remove the bottom border but as you can see here, when typing something, I still get a different underline which I would like to remove as well.

qemu-system-x86_64_2024-01-23_15-00-34

Best regards.

@HuaFangYun
Copy link

Have you made any further progress on this issue?

@eschimmel
Copy link

eschimmel commented Mar 26, 2024

It would be very useful to have BorderColor and BorderWisth properties on any control. I would like to set these properties similarly as the BackgroundColor.

There is clearly a need for these properties.

It should not be necessary that every developer has to add similar code on platform level to get this done. This should be part of MAUI.

I am looking forward to these properties in the next version :-)

Thanks

@Dorna-10
Copy link

This is the solutiont to just change the color!!! I spent so long looking for it :') Go to -> Platforms/Android/Resources/values/colors.xml

Is there a way to just change colors of the underline?

@Eilon Eilon removed the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label May 10, 2024
@matt-goldman
Copy link
Contributor

This is such a ubiquitous requirement, this absolutely be in .NET MAUI. Yep easy enough to do with handlers but there have been a couple of regressions, so making this part of .NET MAUI itself would ensure these get picked up in testing of releases. This is absolutely something nearly everyone needs and would be awesome to include.

@rodolfo-sousa
Copy link

this is how i removed entry's borders for windows

public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .UseMauiCommunityToolkit()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });

#if WINDOWS
            Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderlineWindows", (h, v) =>
            {
                h.PlatformView.BorderThickness = new Microsoft.UI.Xaml.Thickness()
                {
                    Bottom = 0,
                    Top = 0,
                    Left = 0,
                    Right = 0,
                };
            });
#endif

I was able to remove the borders, in Windows, when Entry is with focus with this line:
nativeView.Style = null;
No need to add color resources in Platform\Windows\App.xaml too.

@justinkingst
Copy link

Any update in 2024?

@nicholasyin
Copy link

Any update in 2024?

After two years MS still chooses not to listen to developers' feedback, as always.

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

No branches or pull requests